📜 ⬆️ ⬇️

We make objects from arrays

image
PHP contains a very powerful tool - arrays. Half of the functions in PHP return the result as associative arrays. When working with such functions, it is easy to make mistakes in the naming of the keys of the array. It is clear that for an experienced developer this is not a problem, but for beginners it can often become a headache, especially if we get huge json or just edit legasy legacy code, but for non-programmers ... (like me) it can serve as a scary code shit .

Here I will give some trick that allows you to use an array as an object / collection. Maybe someone will find this stupid, and someone will give ideas for use.

At once I will make a reservation that the implementation is working for PHPStorm, in other IDEs you need to check.

Some examples will be taken from the ceiling, some will be taken from Instagram api.
')
First, examples.

Examples


Example 1. We work with form data.

We have the form:
<form method="post" action="actionurl?route=myroute"> <label for="id">clientID:</label><input id="id" name="id" type="text" value="6041eee77ac94e6ba83fbcec61ad46c4"><br> <label for="secret">ClientSecret:</label><input id="secret" name="secret" type="text" value="539141addd854a8c8d431465d6016590"><br> <label for="tag">Tag:</label><input id="tag" name="tag" type="text" value=""><br> <input type="submit" value="subscribe" name="subscribe"> | <input type="submit" value="unsubscribe" name="subscribe"> | <input type="submit" value="list" name="subscribe"> </form> 


When sending, we get $ _POST. I have always disliked such use (omit the check for the existence of keys)
$id = $_POST['id];
It is much more interesting to use all the features of our IDE and to know in advance about variables in our POST.
Create a class for the form:
 /* @property $id string*/ /* @property $secret string */ /* @property $tag string*/ /* @property $subscribe string value from MyForm::const*/ class MyForm extends Post { const SUBSCRIBE = 'subscribe'; const UNSUBSCRIBE = 'unsubscribe'; const LIST_ = 'list'; } 

Well, the result of using this "class"
image
We immediately see what we are dealing with.

Example 2. We work with sessions.

We need to work with sessions as simple as possible.
Our class:
 /* @property $var1 string */ /* @property $var2 string */ /* @property $var3 string */ class MySession extends Session{ function __construct() { parent::__construct('mySession'); } } 


Class for sessions (ArrayClass code will be at the end):
 class Session extends ArrayClass { function __construct($arrayName = 'session') { if(!isset($_SESSION[$arrayName])) $_SESSION[$arrayName] = array(); parent::__construct($_SESSION[$arrayName]); } public static function init(){ session_start(); } } 

This allows us to work quietly like this:
$s = new MySession();
$s->var1 = 10;

Everything is simple and transparent.

Example 3. Instagram, json and complex arrays

We need to call the API. We do it like this:
 $response = file_get_contents("https://api.instagram.com/v1/tags/instaprint/media/recent?access_token=14135310***************************9f2a26b8a"); $r = new Response(json_decode($response, true)); //$r = new Response($response);   $body = "Data count = ".$r->data->count(); $body.= "\n"; $tags = $r->data; $data = new TagData($r->data->get(0)); $url = $data->images->standard_resolution->url; $body.= $data->id; $body.= "Image0 url: ".$url; $body.= '<img src="'.$url.'">'; 

Class Code:
Some Instagram API
 /** * Class Response * @package instagram * * @property Meta $meta * @property \ArrayClass $data * @property Pagination $pagination * */ class Response extends \ArrayClass { public function getMeta(){ return new Meta($this->get('meta')); } public function getPagination(){ return new Pagination($this->get('pagination')); } } /** * Class Meta * @package instagram * * @property integer $code */ class Meta extends \ArrayClass { } /** * Class Pagination * @package instagram * * @property integer $next_max_tag_id * @property integer $next_max_id * @property integer $next_min_id * @property string $next_url */ class Pagination extends \ArrayClass { } /** * Class TagsData * @package instagram * * @property $attribution * @property \ArrayClass $tags * @property string $type * @property $location * @property $comments * @property $filter * @property integer $created_time * @property $link * @property $likes * @property Images $images * @property \ArrayClass $users_in_photo * @property Caption $caption * @property boolean $user_has_liked * @property integer $id * @property User $user */ class TagData extends \ArrayClass { public function getImages(){ return new Images($this->get('images')); } public function getCaption(){ return new Caption($this->get('caption')); } public function getUser(){ return new User($this->get('user')); } } /** * Class Image * @package instagram * * @property Image $low_resolution * @property Image $thumbnail * @property Image $standard_resolution */ class Images extends \ArrayClass { function __get($name) { return new Image($this->$name); } } /** * Class Image * @package instagram * * @property string $url * @property string $width * @property string $height */ class Image extends \ArrayClass { } /** * Class Caption * @package instagram * * @property integer $created_time * @property string $text * @property User $from * @property int $id * */ class Caption extends \ArrayClass{ public function getFrom(){ return new User($this->get('from')); } } /** * Class From * @package instagram * * @property string $username * @property string $website * @property string $profile_picture * @property integer $id * @property string $full_name * @property string $bio */ class User extends \ArrayClass{ } 



How it looks in IDE:
image

In 2 words. We get json from Instagram and wrap it up in our classes. At the output we get the structure of classes and help from our IDE.

Well, now ArrayClass itself:
 class ArrayClass implements Iterator { private $array; //... /** * @param array|ArrayClass|json_string $array */ function __construct(&$array); // ... public function get($index); // ... public function count(); public function ar(){ return $this->array; } public function json(){ return json_encode($this->array); } } 

Full code ArrayClass
<? php
 /** * Created by PhpStorm. * User: calc * Date: 02.07.14 * Time: 0:57 */ class ArrayClass implements Iterator { private $array; private $haveNext = false; /** * @param array|ArrayClass $array */ function __construct(&$array) { if($array === null) $array = array(); if($array instanceof ArrayClass){ $this->array = &$array->array; } else if(is_string($array)){ $this->array = json_decode($array, true); } else{ $this->array = &$array; } $this->rewind(); } function __get($name) { return $this->get($name); } function __set($name, $value) { $this->array[$name] = $value; } function __isset($name) { return isset($this->array[$name]); } function __unset($name) { unset($this->array[$name]); } public function get($index){ if(isset($this->array[$index])){ if(is_array($this->array[$index])){ return new ArrayClass($this->array[$index]); } return $this->array[$index]; } return null; //return isset($this->array[$index]) ? $this->array[$index] : null; } public function count(){ return count($this->array); } public function ar(){ return $this->array; } /** * (PHP 5 >= 5.0.0)<br/> * Return the current element * @link http://php.net/manual/en/iterator.current.php * @return mixed Can return any type. */ public function current() { return current($this->array); } /** * (PHP 5 >= 5.0.0)<br/> * Move forward to next element * @link http://php.net/manual/en/iterator.next.php * @return void Any returned value is ignored. */ public function next() { $this->haveNext = next($this->array); } /** * (PHP 5 >= 5.0.0)<br/> * Return the key of the current element * @link http://php.net/manual/en/iterator.key.php * @return mixed scalar on success, or null on failure. */ public function key() { return key($this->array); } /** * (PHP 5 >= 5.0.0)<br/> * Checks if current position is valid * @link http://php.net/manual/en/iterator.valid.php * @return boolean The return value will be casted to boolean and then evaluated. * Returns true on success or false on failure. */ public function valid() { return $this->haveNext; } /** * (PHP 5 >= 5.0.0)<br/> * Rewind the Iterator to the first element * @link http://php.net/manual/en/iterator.rewind.php * @return void Any returned value is ignored. */ public function rewind() { $this->haveNext = $this->array === array() ? false : true; reset($this->array); } public function json(){ return json_encode($this->array); } } 



We create an array wrapper and give this wrapper a couple of interesting possibilities.


This is what we get at the output:
image

As an option, you can add checks to the child classes.
The advantages are that if after a year you get into your own or someone else's IDE code, you will be given a hint and you will not have to re-read half of the project code to understand what magic constants are in $ _GET ['magic'] and similar lines of code.

If anyone has any add-ons on memory usage and performance, please unsubscribe in the comments. Thank.

PS
GET, POST, SESSION
 class Get extends ArrayClass { function __construct() { parent::__construct($_GET); } } class Post extends ArrayClass { function __construct() { parent::__construct($_POST); } } class Session extends ArrayClass { function __construct($arrayName = 'session') { if(!isset($_SESSION[$arrayName])) $_SESSION[$arrayName] = array(); parent::__construct($_SESSION[$arrayName]); } public static function init(){ session_start(); } } 

Source: https://habr.com/ru/post/228805/


All Articles