Skip to content

Result Hydration

Glynn Quelch edited this page Jan 29, 2022 · 16 revisions

It is possible to use any of the WordPress WPDB return types ARRAY_A, ARRAY_N, OBJECT, OBJECT_K. BUt also to use custom models, complete with a basic constructor and simple hydration.

Using WPDB Types

By default every instance of the QueryBuilder will return its results in standard stdClass objects. This is the same as using the OBJECT constant provided by WPDB. To change this, just use the setFetchMode method.

$builder
    ->table('foo')
    ->setFetchMode(OBJECT_K)
    ->get();
// This would then return your results in an array where the primary key is set as the array key.

This is the same process as with ARRAY_A, ARRAY_N

Using Custom Models

You can use custom models/objects to return your results. You can even pass in constructor arguments to the class, which will be used when creating the instance (prior to hydration). While you can use the setFetchMode method, its usually a little easier to read using the asObject method.

class Result {
    protected $something;
    protected $column1;
    public function __construct($something){
        $this->something = $something;
    }

    public function setColumn1($value){
        $this->column1 = $this->something($value);
    }
}

For more details on setting values, please see below

In the Result class, we need to pass in an argument when this is constructed. To do this, we can just pass the class name and the dependencies to the asObject method.

$builder
    ->table('foo')
    ->asObject(Result::class, [new SomethingHelper()])
    ->get();
// This would then return your results mapped as a Result instance.

Under the hood the following will happen.

$class = $this->getFetchMode();
$args = $this->getFetchModeArgs();
$model = new $class($args);
$model->setColumn1($dbRow->column1);
return $model;

Defining with new instance of builder You can define the return type when you create an instance of the builder.

$builder = new QueryBuilderHandler($connection, Model::class, ['constructor', 'args']);

Setting Model Values

When we come to set values, there is a small flow the Hydrator follows.

  • First it will check if PSR12 setter exists setColumnName this will add set to the start of the property name and capitalise the first char myVal would become setMyVal()
  • Second we check if an underscored setter exists, this adds set_ to the start of the property myVal would become set_myVal()
  • Finally we just set as a public property, if it doesnt exist it will be added as a dynamic property (which should be avoided)
  • You can handle all possibilities with the magic __set() method.

Model Example

class FooModel {

    protected int $id;
    public string $someValue;
    protected string $someJson;

    public function setId($id): void {
        $this->id = (int) $id;
    }

    public function set_someJson($someJson): void {
        $this->someJson = json_decode($someJson);
    }
}

If we get the following data from a query

{"id":12, "someValue":"foo", "someJson":{"key":"some value"}}

When this is populated to the model, the following will happen.

  • FooModel object is created
  • id will be set using $modelInstance->setId($row->id)
  • someValue will be set using $modelInstance->someValue = $row->someValue
  • someJson will be set using $modelInstance->set_someJson($row->someJson)