2

What does the following do?

public static function find_by_sql($sql="") 
{
    global $database;
    $result_set = $database->query($sql);
    $object_array = array();
    while ($row = $database->fetch_array($result_set)) 
    { 
        // fetch_array=mysql_fetch_array
        $object_array[] = self::instantiate($row);
    }
    return $object_array;
} 

private static function instantiate($record) 
{
    $object = new self;
    foreach($record as $attribute=>$value)
    {
        if($object->has_attribute($attribute))
        {
            $object->$attribute = $value;
        }
    }
    return $object;
}

private function has_attribute($attribute) 
{
    return array_key_exists($attribute, $this->attributes());
}

protected function attributes() 
{ 
    // return an array of attribute names and their values
    $attributes = array();
    foreach(self::$db_fields as $field) 
    {
        if(property_exists($this, $field)) 
        {
            $attributes[$field] = $this->$field;
        }
    }
    return $attributes;
}

The class attributes are,

public $id;
public $username;
public $password;
public $first_name;
public $last_name;
public $power;

So the while loop is looping through each row, but what does the instantiate function do? and how does instantiate optimize the script?

Also, what does $object = new self mean, is this a new instance of the class? and when you return the $object what are you returning?

Thanks, Daniel.

Rich Adams
  • 26,096
  • 4
  • 39
  • 62
dgamma3
  • 2,333
  • 4
  • 26
  • 47

4 Answers4

2

The instantiate function creates a new object based on the containing class ("instantiate" just means to create an instance out of something, in this case, the class in which it resides), and in this case, the function iterates through the supplied array, checking if its keys are defined as being within the class' attributes array, and if so, populating the object with those keys' values.

In the while loop, $object_array is populated with separate instances of the containing class for each row.

This call to instantiate does not optimize the script (it slows it down slightly since it has to call the function rather than, e.g., just inserting the rows into the array), but the reason for it may be: 1) to wrap the rows in a way where you can use object methods on them, and 2) To ensure that SQL columns which are not specified as attributes on the class are not exposed in the return array's rows.

For self, see What does new self(); mean in PHP? . Basically, yes, $object = new self creates a new instance of the class, since self means the current class. It is a convenience as you do not need to change this reference if you decide to change the class name.

The global variable, btw, is a concern, as globals would more properly be supplied to the class instance to avoid name conflicts.

Community
  • 1
  • 1
Brett Zamir
  • 14,034
  • 6
  • 54
  • 77
1

self is just a shortcut that refers to the current class. The same way $this refers to the current object.

class Foo {
    public function bar() {
        new self;
        new Foo;
    }
}

These are both the same things, both instantiate a new object from the class Foo. It's just more elegant to use self since you can change the class name of Foo without having to rename every use of it as well.

So what your ::instantiate function is doing is to instantiate a new object of the same class, set a few properties on it and return it. The call to self::instantiate is just calling the instantiate method statically, the same way $this->instantiate() would call it as a method of the current object.

deceze
  • 510,633
  • 85
  • 743
  • 889
  • Thanks for explaining this, can you tell me if this is the best practice? Is this the way everyone takes data from the database and creates objects from them? If not then what is the correct way? Thanks for your time! – youngcouple10 Aug 24 '12 at 11:54
  • @youngcouple10 It's not exactly the way **everybody** does it, but a "static constructor" is a valid thing to use. Just the `private static function instantiate` in this example is alright, though the rest of the class uses some bad practices like `global`. – deceze Aug 24 '12 at 11:57
  • Thanks, but the general idea of having an instantiate function is normal I take it. Why is global not good? Do you personally have a instantiate function that you use? – youngcouple10 Aug 24 '12 at 12:00
  • Search for why `global` is not good, there's enough talk about it. Yes, I'm using similar code personally. – deceze Aug 24 '12 at 12:02
  • Thanks for your help and time. One last thing, is it possible in PHP to set a static property to the result of a function? `public $table = get_class();`? If not why not? – youngcouple10 Aug 24 '12 at 12:04
0

The instantiate function creates a class instance from the array data returned by the db and then return the object instance. That instanc eis then added to the array that find_by_sql() returns. Essentially its performing data mapping from database columns to object instance properties.

I must say though... this implementation doesnt smell very good :-)

prodigitalson
  • 60,050
  • 10
  • 100
  • 114
0

Here instantiate function is creating new objects of the same class. $Object = new self; creates an object of the same class and here its assigning to an attribute of the same class which is of course a bad implementation and is not all required. you can keep an array to hold the values, since if you want to retrieve the values you need to loop through the array of objects.

Shameer
  • 3,036
  • 1
  • 21
  • 27