I am trying to turn an query result into classes.
$result->setFetchMode(PDO::FETCH_CLASS, \'myclass\', array());
This works quite well howev
I think wich the best answer is here.
How to use PDO::FETCH_CLASS with abstract class?
This cant really be done automaticly, it is too specific. You can just loop over each row and instantiate the correct class with the proper arguments.
I would not use PDO::FETCH_CLASS for that. You can change your SQL to return class name based on value of age
SELECT
id,
name,
age,
CASE WHEN age < 21 THEN 'child'
ELSE 'adult' END
AS class_name
FROM SOME_TABLE";
Then use your PDO::FETCH_ASSOC as fetch type
Then when you loop over your results
you can easily instantiave class based on
$result['class_name'] like this:
$class = $result['class_name'];
$obj = new $class;
As you do not know the type (classname) of the returned objects before you do the query, you can not specify it.
However, you could encapsulate that logic inside another type you use as return type which can then return the specific return type:
/**
* Should not have any private, public or protected members in it's definition.
*
* Does only work for public properties.
*/
class ReturnObject {
public function getConcrete()
{
/* decide here which class */
$classname = 'Child'; // or 'Adult'
return $this->selfAs($classname);
}
private function selfAs($classname)
{
$l = strlen(__CLASS__);
$s = sprintf('O:%d:"%s"', strlen($classname), $classname).substr(serialize($this), 5+strlen($l)+$l);
$instance = unserialize($s);
$instance->__construct();
return $instance;
}
}
You can then use the getConcrete()
function on each returned object to return your specific type, your decision logic bound to the database return.
Edit: I changed it into a version that will first initialize the objects properties via unserialize (please test if this works, it's based on the assumption that we're talking about public properties only and I don't know if PDO just does the setters or more via reflection in the mode you're using) and then calls the constructor function. The constructor needs to be public (and it must exist) so that this works.
It's technically possible to make this available for private and protected members as well, however this needs real reflection and it as well needs parsing of the serialized data as well. This class only renames the classname, but not inside private properties.
However this is only one way for doing so. You probably only need a ->isChild()
or ->isAdult()
function on your Person
class.