Tomáš Fejfar Tomáš Fejfar - 1 month ago 6
MySQL Question

Is there a reason why PDO does not have option to create objects via constructor with FETCH_CLASS?

It seems like there is no way to make PDO create the new object using constructor/setters when using PDO::FETCH_CLASS.

Currently with FETCH_CLASS the member variables get filled using reflection I guess. They are certainly not passed through constructor. That's a pitty because it circumvents any checks you may have in your constructor to ensure object's consistency (task cannot have $status = finished while not having $finishedDate set).

There are various options, some of which are special to very edge cases (like PDO::FETCH_NAMED). That leads me to the assumption that constructor creation is not implemented because there is some reason why it's not a good idea.

Note: I am not looking for the third argument of fetchAll (ctor_args) that does not pass the row's values, but rather the supplied ones.

Update: It seems I was not clear in describing what I'm asking. Imagine I have constructor like this:

public function __construct($id, $number) {
if ($id == $number) {
throw new InvalidArgumentException("Number and ID can't be same");
}
}


and do

SELECT id, number FROM table


With any settings, even
$st->setFetchMode(PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE, 'Foo');
it won't throw an exception and will happily create the object in inconsistent state. Because the values are not set via constructor. Actually closest approximation of what I would call expected behaviour would be what's mentioned in http://stackoverflow.com/a/33027392/112000

Update: I created a feature request for this https://bugs.php.net/bug.php?id=73397 just in case you're interested in it as well.

Answer

I think it's for historical reasons.

At first there was mysql_fetch_object - just to supplement the fetching triad - a list, a hash, an object - to create a class instance right off the database row.

Then enter PDO, with a lot of nice features, but still under the same paradigm - to assign the newly created variable's properties after the columns in the database.

So I think that it's simply because nobody had an idea that PDO can be used this way.

So I think that the nearest outcome you can get using a closure to create an instance:

$job = $pdo
    ->query('SELECT id, number FROM users')
    ->fetchAll(PDO::FETCH_FUNC, function($id,$number) {return new Job($id,$number);});