<?php
namespace app\components;
use yii\base\Model;
use yii\db\ActiveQuery;
use yii\db\ActiveQueryInterface;
use yii\db\ActiveRecord;
class Eagerifier
{
/**
* @param $with
* @param Model[] $models
* @param bool $asArray
* @throws \yii\base\InvalidConfigException
*/
public static function populate($with, array &$models, $asArray = false)
{
$modelClass = '';
foreach ($models as $key => $model) {
$modelClass = $model->className();
break;
}
// From ActiveQuery::findWith()
$primaryModel = new $modelClass;
$relations = self::normalizeRelations($primaryModel, $with);
/* @var $relation ActiveQuery */
foreach ($relations as $name => $relation) {
if ($relation->asArray === null) {
// inherit asArray from primary query
$relation->asArray($asArray);
}
$relation->populateRelation($name, $models);
}
}
/**
* Adapted method from ActiveQuery
*
* @param ActiveRecord $model
* @param array $with
* @return ActiveQueryInterface[]
*/
private static function normalizeRelations($model, $with)
{
$relations = [];
foreach ($with as $name => $callback) {
if (is_int($name)) {
$name = $callback;
$callback = null;
}
if (($pos = strpos($name, '.')) !== false) {
// with sub-relations
$childName = substr($name, $pos + 1);
$name = substr($name, 0, $pos);
} else {
$childName = null;
}
if (!isset($relations[$name])) {
$relation = $model->getRelation($name);
$relation->primaryModel = null;
$relations[$name] = $relation;
} else {
$relation = $relations[$name];
}
if (isset($childName)) {
$relation->with[$childName] = $callback;
} elseif ($callback !== null) {
call_user_func($callback, $relation);
}
}
return $relations;
}
}