Créer une instance à la manière de PDO et du mode FETCH_CLAS

Eléphant du PHP | 121 Messages

24 août 2011, 00:47

C'est facile de créer une instance de classe, un petit "new" et on en obtient une toute neuve. Mais comment créer une instance à la manière de PDO et du mode de récupération FETCH_CLASS qui renseigne les propriétés de l'instance avant que le constructeur ne soit appelé ? PHP ne propose aucune fonction pour cela, pourtant il en existe une qui permet d'obtenir des instances dont les propriétés sont renseignées. Ce pourrait-il que l'on puisse tromper cette fonction pour en faire autant ?

Si vous souhaitez en savoir plus, il y a une article sur mon blog : Créer une instance à la manière de PDO et du mode FETCH_CLAS.

Voici la fonction :
<?php

function instantiate($class_name, array $properties=array(), array $construct_args=array())
{
    $class_reflection = new \ReflectionClass($class_name);
    $properties_count = 0;
    $serialized = '';

    if ($properties)
    {
        $class_reflection = new \ReflectionClass($class_name);
        $class_properties = $class_reflection->getProperties();
        $defaults = $class_reflection->getDefaultProperties();

        $done = array();

        foreach ($class_properties as $property)
        {
            if ($property->isStatic())
            {
                continue;
            }

            $properties_count++;

            $identifier = $property->name;
            $done[] = $identifier;
            $value = null;

            if (array_key_exists($identifier, $properties))
            {
                $value = $properties[$identifier];
            }
            else if (isset($defaults[$identifier]))
            {
                $value = $defaults[$identifier];
            }

            if ($property->isProtected())
            {
                $identifier = "\x00*\x00" . $identifier;
            }
            else if ($property->isPrivate())
            {
                $identifier = "\x00" . $property->class . "\x00" . $identifier;
            }

            $serialized .= serialize($identifier) . serialize($value);
        }

        $extra = array_diff(array_keys($properties), $done);

        foreach ($extra as $name)
        {
            $properties_count++;

            $serialized .= serialize($name) . serialize($properties[$name]);
        }
    }

    $serialized = 'O:' . strlen($class_name) . ':"' . $class_name . '":' . $properties_count . ':{' . $serialized . '}';

    $instance = unserialize($serialized);

    if (method_exists($instance, '__construct'))
    {
        call_user_func_array(array($instance, '__construct'), $construct_args);
    }

    return $instance;
}