Home > other >  Convert an object to an array and remove its default values
Convert an object to an array and remove its default values

Time:03-01

I have this class :

class MyObject{
  var $title = null;
  var $description = null;
  var $items = [];
  var $metas = [];
  var $image = null;
  var $country = 'Belgium';
}

And this data :

$data = new MyObject();
$data->title = 'NEW ITEM';
$data->children = ['CHILD1','CHILD2'];
$data->image = 'image.gif';
$data->country = 'Belgium';

Before storing my data in my database, I would like to remove all the defaults values from the datas, and get this output:

$output = array(
  'title'=>'NEW ITEM',
  'children'=>['CHILD1','CHILD2'],
  'image'=>'image.gif'
);

I made an attempts with

$blank = new MyObject();
$defaults = (array)$blank;
$output = array_diff((array)$data, (array)$blank);

But it doesn't work since I get an Array to string conversion.

How could I do ?

Thanks !

CodePudding user response:

Try this:

class MyObject {
  public $title = null;
  public $description = null;
  public $children = [];
  public $metas = [];
  public $image = null;
  public $country = 'Belgium';
  
  protected $default = [];
  
  function getDefault()
  {
    $reflect = new ReflectionClass(__CLASS__);
    $vars = $reflect->getProperties(ReflectionProperty::IS_PUBLIC);

    $default = [];
    foreach ($vars as $privateVar) {
        $default[$privateVar->getName()] = $this->{$privateVar->getName()};
    }
    
    return $default;
  }
}


$data = new MyObject();

$one = $data->getDefault();

$data->title = 'NEW ITEM';
$data->children = ['CHILD1','CHILD2'];
$data->image = 'image.gif';
$data->country = 'Belgium';

$two = $data->getDefault();

echo '<pre>';
print_r($one);
print_r($two);

$output = [];
foreach($one as $key => $value){
    if($value != $two[$key]){
        $output[$key] = $two[$key];
    }
}
print_r($output);

We get default values and set in $one

After set new data, we get default values and set in $two

Then, we check which key is not changed

CodePudding user response:

First of all. Imagine that you use this class everytime you want to create a Movie entry. (I put this example because your class is very general).

class Movie{
    var $title = null;
    var $description = null;
    var $items = [];
    var $metas = [];
    var $image = null;
    var $country = 'Belgium';
 }

Every time you want to create a new Movie record, for database or any other thing (how well have you done before).

You can create a new object.

$movie1 = new Movie();
$movie1->title = 'NEW ITEM';
$movie1->children = ['CHILD1','CHILD2'];
$movie1->image = 'image.gif';
$movie1->country = 'Belgium';

And then, if you need another one, you just have to instantiate a new object (which by default are already initialized; that's what class constructors are for) Well, we don't have a constructor here yet, but now we'll add it later

    $movie1 = new Movie();
$movie1->title = 'Another title';
$movie1->items = ['SOME','ITEMS'];
$movie1->metas = ['SOME', 'METAS'];
$movie1->image = 'image.gif';
$movie1->country = 'Belgium';
$movie1->description = "Some description";

// tehere is no need for emtpy 

$movie2 = new Movie();
$movie2->title = 'Title movie 2';
$movie2->items = ['SOME','ITEMS', 'MOVIE2'];
$movie2->metas = ['SOME', 'METAS', 'MOVIE"'];
$movie2->image = 'image2.gif';
$movie2->country = 'France';
$movie1->description = "Another description";

$movie1 and $movie2 now are different objects with different data.

But let's make it even better:

<?php
class Movie{
      
    var $title;
    var $description;
    var $items;
    var $metas;
    var $image;
    var $country;
      
    
    function __construct($title, $description, $items, $metas, $image, $country) {
    
        $this->title       = $title;
        $this->description = $description;
        $this->items       = $items;
        $this->metas       = $metas;
        $this->image       = $image;
        $this->country     = $country;
    }
    
    function GetClassVars() {
        return array_keys(get_class_vars(get_class($this))); 
    }
    
}

$movie1 = new Movie("Ttile one", 
                    "the description",
                    ['SOME','ITEMS'], 
                    ['SOME', 'METAS'], 
                    "image.gif", 
                    "Belgium");
                    


$movie2 = new Movie("Ttile two", 
                    "the description of two",
                    ['SOME','ITEMS', 'MORE'], 
                    ['SOME', 'METAS', 'AND MORE'], 
                    "image2.gif", 
                    "France");
                    

PrintMovie($movie1);
PrintMovie($movie2);
                
                


function PrintMovie($object){
    
    echo "#############################";
    
    
    $class_vars = $object->GetClassVars();
    
    foreach ($class_vars as $nombre) {
    
        $val = $object->{$nombre};
    
        if(gettype($val) == "array"){
            
            foreach($val as $v){
                echo "<pre>";
                echo "\t$nombre ->";
                echo " " .$v;
                echo "</pre>";
            }
        }
        else{
            echo "<pre>";
            echo "$nombre -> $val";
            echo "</pre>";
        }
    }
    
    echo "#############################\n";
}
 

As you are seeing in the example. I am creating two different movies (without having to delete the data each time; the constructor takes care of that, to initialize the data each time)

You also have an array with all the names of the properties of the class. In order to iterate over them and print them on the screen. You could even modify its value, since, like the PrintMovie function (it could also be called GetMovieData, if we wanted to modify it instead of printing the value)
The result of

PrintMovie($movie1);
PrintMovie($movie2);

is:

#############################

title -> Ttile one

description -> the description

items -> SOME

items -> ITEMS

metas -> SOME

metas -> METAS

image -> image.gif

country -> Belgium

############################# #############################

title -> Ttile two

description -> the description of two

items -> SOME

items -> ITEMS

items -> MORE

metas -> SOME

metas -> METAS

metas -> AND MORE

image -> image2.gif

country -> France

############################# 

As you can see we have not had to delete anything and we have all the names of the properties in an array, to access them dynamically (as long as we have the object). That's why we pass it to the PrintMovie function

We could have put the print function inside the class, but I think it is also understood that way. In any case, I have invented the example so that you understand that with object-oriented programming, each object is different, therefore you do not have to delete anything to reuse it. You simply create a new object.

  • Related