7

I have classes that extends an abstract class. I need to create instances of these classes through a string - preferably JSON.

Many of the objects are nested, and many properties are private. I need a way to:

  1. Create a JSON string of the complete object (with private properties and nested objects - with their private properties).
  2. Create a new Object from a JSON string, with the correct type and all nested objects.

I guess it needs to be recursive.

I'm using namespaces that end up looking like crap if I just cast the object to an array.

I'm thinking of writing a parser, label the classes in my JSON strings and then hardcode a factory function for every class, but that would take a lot of time.

1
  • hey there. I removed the laravel tag as nothing seems to indicate it's implication? Feel free to add it again it you think it's relevant, but please add why it is in your question. Commented Nov 16, 2015 at 18:24

4 Answers 4

1

I suggest you to use php's serialize function

In cases like this it's better to use this function because it exists for this purpose: you can store the serialized string wherever you want and after unserializing it you will get back the original PHP object with all the properties

With JSON, as you said, you'll have no clue of what class the object was (unless you store it manually as a string) and of course there will be all the problems related to the private properties

Sign up to request clarification or add additional context in comments.

9 Comments

The thing i that 'm building an application where another application will serve it with data, through a MySQL DB. However I'm the one that's going to build that app too, so I can make all the decisions. Would it be a viable solution to turn the serialized string into JSON? And then the JSON into a serialized string which I use to create my objects with?
I'm not sure if you can store the serialized string in JSON (but probably yes), you'll have to try it. Is there a specific reason you have to use JSON and not store a plain serialized string?
Well. The other application is going to create this data through a Javascript frontend app. I won't build that app in a few weeks so I don't know what difficulties I will run into there. So trying to use JSON as much as possible to shuffle data around might be a good idea.
Yes, but are you sure you'll need to create this data (regarding php objects) through frontend code? If you can i think it would be better use server-side code. I.e. you could create the data throught an ajax call
The actual data is going to be created in frontend. you kind of build these objects with blocks. So even if I use backend to create the objects, or the serialize data, I need to pull data from the frontend that will describe the hierarchy, object types and data.
|
1

I suggest using the jms serializer: http://jmsyst.com/libs/serializer Easy to use, configuarble and supports all the features you requested.

Comments

1

There are three methods for doing this: JSON, Serialize, and var_export.

With JSON, it will only work with objects of stdClass, but it's easy to read and can be used outside of PHP.

Serialize works with instances of classes other than stdClass, but it can be difficult to read and can only be used by PHP. http://php.net/manual/en/function.serialize.php

var_export outputs the PHP code to create the object (so you'd write it to a PHP file), it's very easy to read but can't be used outside PHP. The objects will need to have the set state method. http://php.net/manual/en/function.var-export.php

Comments

1

One thing thay you can do is using the magic methods in every class that you want to serialize and unserialize , the methods are '__serialize()' and '__unserialize(array $data)', __serialize return a associative array with properties of the own object is like the getter, and __unserialize set the state of the object base on the data from the array is like the setter!. Below a show a example that i used to solve that, is a example using OOP.

this is like the main of the project and what it does is basically build an array of objects and this objects contain an array of other objects and so on. then serialize all the wrapped object and then unserialize creating another object of the same instance using __unserialize and get all the information correct here it is. NOTE:The class cargarArchivo.php is at the end, that class is use for load the information of the Costa Rica political division of the 'provincias => like a state in US.' and the tows of the provincias with the data asociative to it. LOOK TO THE FILE 'costaRica.xml & costaRica.json'the information is loaded from this files look to the gitHub repository. https://github.com/Gabriel-Barboza-Carvajal/Fetch-API-PHP-JSON/blob/master/servidor.php

include_once './modelo/division.php';
        include_once './modelo/canton.php';
        include_once './modelo/distrito.php';
        include_once './modelo/provincia.php';
        include_once './modelo/division_total.php';
        include_once './cargarArchivo.php';
       
        $divi=new division_total();
        $divi->provincias= cargarArchivo::devolverXMLCostaRica();
        //serializamos la informacion obtenida.
        $data = $divi->__serialize();
        
        //deserealizamos.
        $diviDeserea=new division_total();
        
        $diviDeserea->__unserialize($data);
        

abstract class division {

    private $numero, $nombre;
    

    public function __construct($numero, $nombre) {
        $this->numero = $numero;
        $this->nombre = $nombre;
    }


    public function __destruct() {
//        echo "<br>destruyendo obj general<br>";
    }

    public function getNumero() {
        return $this->numero;
    }

    public function getNombre() {
        return $this->nombre;
    }

    public function setNumero($numero) {
        $this->numero = $numero;
        return $this;
    }

    public function setNombre($nombre) {
        $this->nombre = $nombre;
        return $this;
    }
    
    abstract public function __serialize():array;
    abstract public function __unserialize(array $data):void;
    abstract public function __toString():string;
}
And the other classes the same like this...


class provincia extends division {

    public $cantones;

    public function __construct($num, $nom, $cant=null) {
        parent::__construct($num, $nom);
        $this->cantones = $cant;
    }

     public function __serialize(): array {
        return[
            'nombre' => $this->getNombre(),
            'número' => $this->getNumero(),
            'cantones' => $this->serializarCantones()
        ];
    }

    public function serializarCantones(): array {
        $todos = array();
        for ($index = 0; $index < count($this->cantones); $index++) {
            array_push($todos, ($this->cantones[$index])->__serialize());
        }
        return $todos;
    }

    public function __unserialize(array $data): void {
        $this->setNombre($data['nombre']);
        $this->setNumero($data['número']);
        $this->unserializarCantones($data);
    }
    
    public function unserializarCantones(array $data): void {
        $dis = $data['cantones'];
        $cont=0;
        foreach ($dis as $value) {
            $this->cantones[$cont] = new canton('', '');
            $this->cantones[$cont]->__unserialize($value);
            $cont+=1;
        }
    }

    public function __toString(): string {
        $str='';
        $str = '<br>' . $this->getNombre() . "|" . $this->getNumero() . '<br>';
        foreach ($this->cantones as $value) {
            $str .=$value->__toString();
        }
        return $str;
    }

}

class canton extends division {

    public $distritos;

    public function __construct($num, $nom, $distro = array()) {
        parent::__construct($num, $nom);
        $this->distritos = $distro;
    }

    public function agregarCantones($distritos) {
        $this->distritos = $distritos;
    }
    
    public function __serialize(): array {
        return[
            'nombre' => $this->getNombre(),
            'número' => $this->getNumero(),
            'distritos' => $this->serializarDistritos()
        ];
    }

    public function serializarDistritos(): array {
        $todos = array();
        for ($index = 0; $index < count($this->distritos); $index++) {
            array_push($todos, ($this->distritos[$index])->__serialize());
        }
        return $todos;
    }

    public function unserializarDistritos(array $data): void {
        $dis = $data['distritos'];
        $cont=0;
        foreach ($dis as $value) {
            $this->distritos[$cont] = new distrito('', '');
            $this->distritos[$cont]->__unserialize($value);
            $cont+=1;
        }
    }

    public function __unserialize(array $data): void {
        $this->setNombre($data['nombre']);
        $this->setNumero($data['número']);
        $this->unserializarDistritos($data);
    }

    public function __toString(): string {
        $str='';
        $str = '<br>' . $this->getNombre() . "|" . $this->getNumero() . '<br>';
        foreach ($this->distritos as $value) {
            $str .= $value->__toString();
        }
        return $str;
    }

}



class distrito extends division {

    private $secuencia;

    public function __construct($num = '', $nom = '', $sec = null) {
        parent::__construct($num, $nom);
        $this->secuencia = $sec;
    }

    public function getSecuencia() {
        return $this->secuencia;
    }

    public function setSecuencia($secuencia) {
        $this->secuencia = $secuencia;
        return $this;
    }

    public function __serialize(): array {
        return [
            'nombre'=> $this->getNombre(),
            'número'=> $this->getNumero(),
            'secuencia'=> $this->getSecuencia()
            ];
    }

    public function __unserialize(array $data): void {
        $this->secuencia=$data['secuencia'];
        $this->setNombre($data['nombre']);
        $this->setNumero($data['número']);
    }

    public function __toString(): string {
        $str='';
        $str= $this->getNombre() . ' , ' .$this->getNumero() . ' , ' . $this->getSecuencia();
        return $str;
    }

}
class division_total extends division{
    
    function __construct() {
        parent::__construct('0', 'Costa Rica');
    }

      public function __serialize(): array {
        return[
            'nombre' => $this->getNombre(),
            'número' => $this->getNumero(),
            'provincias' => $this->serializarProvincias()
        ];
    }

    public function serializarProvincias(): array {
        $todos = array();
        for ($index = 0; $index < count($this->provincias); $index++) {
            array_push($todos, ($this->provincias[$index])->__serialize());
        }
        return $todos;
    }

    public function __unserialize(array $data): void {
        $this->setNombre($data['nombre']);
        $this->setNumero($data['número']);
        $this->unserializarProvincias($data);
    }
    
    public function unserializarProvincias(array $data): void {
        $dis = $data['provincias'];
        $cont=0;
        foreach ($dis as $value) {
            $this->provincias[$cont] = new provincia('', '');
            $this->provincias[$cont]->__unserialize($value);
            $cont+=1;
        }
    }

    public function __toString(): string {
        $str='';
        $str = '<br>' . $this->getNombre() . "|" . $this->getNumero() . '<br>';
        foreach ($this->provincias as $value) {
            $str .=$value->__toString();
        }
        return $str;
    }

    public $provincias = array();
    
  
}
class cargarArchivo {

    public function __construct() {
        
    }

    static public function devolverXMLCostaRica() {
        libxml_use_internal_errors(true);
        $xml = simplexml_load_file('CostaRica.xml');
        if ($xml === false) {
            echo "Failed loading XML: ";
            foreach (libxml_get_errors() as $error) {
                echo "<br>", $error->message;
            }
        } else {
//            print_r($xml);
            //recorremos las provincias
            $divisionPolitica= array();
            foreach ($xml->children() as $data)
            {
                $nombre= $data['nombre'];
                $numero= $data['número'];
                $provin=new provincia($numero, $nombre);
                $cantones=array();
                array_push($divisionPolitica,$provin);//agregamos la provincia a la division politica.
                //recorremos el numero de cantones que tiene la provincia
                for ($index = 0; $index < $data->cantón->count(); $index++) {                    
                    $nomDistrCanton=$data->cantón[$index]['nombre'];
                    $numDistrCanton=$data->cantón[$index]->count();
                    $canton=new canton($numDistrCanton, $nomDistrCanton);
                    array_push($cantones,$canton);//agregamos un canton a la provincia
                    //ahora ocupamos recorrer todos los distritos que maneja este primer canton
                    $x=$data->cantón[$index];
                    $distritos=array();
                    for ($index1 = 0; $index1 < $data->cantón[$index]->count(); $index1++) {
                         $nom=$data->cantón[$index]->distrito['nombre'];
                         $num=$data->cantón[$index]->distrito['número'];
                         $sec=$data->cantón[$index]->distrito['secuencia'];
                        $distri=new distrito($num, $nom, $sec);
                        array_push($distritos,$distri);
                    }
                    $canton->distritos=$distritos;
                    $provin->cantones=$cantones;
                }
                
            }
            
            
            }
            
            
        
        return $divisionPolitica;
    }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.