diff --git a/Base/Model.php b/Base/Model.php index 3aba07d..630b2fb 100644 --- a/Base/Model.php +++ b/Base/Model.php @@ -95,7 +95,7 @@ abstract class Model extends Component implements ModelInterface, ArrayAccess, T /** * @var array */ - private array $_with = []; + protected array $_with = []; /** diff --git a/HasCount.php b/HasCount.php index 270dea8..285d201 100644 --- a/HasCount.php +++ b/HasCount.php @@ -5,6 +5,7 @@ namespace Database; use Database\Traits\HasBase; use Exception; +use Kiri; /** * Class HasCount @@ -19,7 +20,8 @@ class HasCount extends HasBase */ public function get(): array|ModelInterface|null { - return $this->_relation->count($this->reKey()); + $relation = Kiri::getDi()->get(Relation::class); + return $relation->count($this->name); } } diff --git a/HasMany.php b/HasMany.php index 7687a22..ea68f3a 100644 --- a/HasMany.php +++ b/HasMany.php @@ -11,6 +11,7 @@ namespace Database; use Database\Traits\HasBase; use Exception; +use Kiri; /** * Class HasMany @@ -27,6 +28,7 @@ class HasMany extends HasBase */ public function get(): array|Collection|null { - return $this->_relation->get($this->reKey()); + $relation = Kiri::getDi()->get(Relation::class); + return $relation->get($this->name); } } diff --git a/HasOne.php b/HasOne.php index f3d7de9..613a4e7 100644 --- a/HasOne.php +++ b/HasOne.php @@ -11,6 +11,7 @@ namespace Database; use Database\Traits\HasBase; use Exception; +use Kiri; /** * Class HasOne @@ -26,6 +27,7 @@ class HasOne extends HasBase */ public function get(): array|ModelInterface|null { - return $this->_relation->first($this->reKey()); + $relation = Kiri::getDi()->get(Relation::class); + return $relation->first($this->name); } } diff --git a/Model.php b/Model.php index ef7896c..0e697b5 100644 --- a/Model.php +++ b/Model.php @@ -110,7 +110,7 @@ class Model extends Base\Model if (empty($attributes)) { return $logger->addError(FIND_OR_CREATE_MESSAGE, 'mysql'); } - + /** @var static $select */ $select = static::query()->where($condition)->first(); if (!empty($select)) { @@ -279,7 +279,7 @@ class Model extends Base\Model */ private function withRelates($relates): array { - foreach ($this->getWith() as $val) { + foreach ($this->_with as $val) { $relates[$val] = $this->withRelate($val); } return $relates; @@ -287,13 +287,13 @@ class Model extends Base\Model /** - * @param string $modelName + * @param ModelInterface|string $modelName * @param $foreignKey * @param $localKey * @return HasOne|ActiveQuery * @throws Exception */ - public function hasOne(string $modelName, $foreignKey, $localKey): HasOne|ActiveQuery + public function hasOne(ModelInterface|string $modelName, $foreignKey, $localKey): HasOne|ActiveQuery { if (($value = $this->{$localKey}) === null) { throw new Exception("Need join table primary key."); @@ -301,18 +301,23 @@ class Model extends Base\Model $relation = $this->getRelation(); - return new HasOne($modelName, $foreignKey, $value, $relation); + $primaryKey = $modelName . $foreignKey . $value; + if (!$relation->hasIdentification($primaryKey)) { + $relation->bindIdentification($primaryKey, $modelName::query()->where([$foreignKey => $value])); + } + + return new HasOne($primaryKey, $relation); } /** - * @param $modelName + * @param ModelInterface|string $modelName * @param $foreignKey * @param $localKey * @return ActiveQuery|HasCount * @throws Exception */ - public function hasCount($modelName, $foreignKey, $localKey): ActiveQuery|HasCount + public function hasCount(ModelInterface|string $modelName, $foreignKey, $localKey): ActiveQuery|HasCount { if (($value = $this->{$localKey}) === null) { throw new Exception("Need join table primary key."); @@ -320,18 +325,23 @@ class Model extends Base\Model $relation = $this->getRelation(); - return new HasCount($modelName, $foreignKey, $value, $relation); + $primaryKey = $modelName . $foreignKey . $value; + if (!$relation->hasIdentification($primaryKey)) { + $relation->bindIdentification($primaryKey, $modelName::query()->where([$foreignKey => $value])); + } + + return new HasCount($primaryKey); } /** - * @param $modelName + * @param ModelInterface|string $modelName * @param $foreignKey * @param $localKey * @return ActiveQuery|HasMany * @throws Exception */ - public function hasMany($modelName, $foreignKey, $localKey): ActiveQuery|HasMany + public function hasMany(ModelInterface|string $modelName, $foreignKey, $localKey): ActiveQuery|HasMany { if (($value = $this->{$localKey}) === null) { throw new Exception("Need join table primary key."); @@ -339,17 +349,22 @@ class Model extends Base\Model $relation = $this->getRelation(); - return new HasMany($modelName, $foreignKey, $value, $relation); + $primaryKey = $modelName . $foreignKey . $value; + if (!$relation->hasIdentification($primaryKey)) { + $relation->bindIdentification($primaryKey, $modelName::query()->where([$foreignKey => $value])); + } + + return new HasMany($primaryKey); } /** - * @param $modelName + * @param ModelInterface|string $modelName * @param $foreignKey * @param $localKey * @return ActiveQuery|HasMany * @throws Exception */ - public function hasIn($modelName, $foreignKey, $localKey): ActiveQuery|HasMany + public function hasIn(ModelInterface|string $modelName, $foreignKey, $localKey): ActiveQuery|HasMany { if (($value = $this->{$localKey}) === null) { throw new Exception("Need join table primary key."); @@ -357,7 +372,12 @@ class Model extends Base\Model $relation = $this->getRelation(); - return new HasMany($modelName, $foreignKey, $value, $relation); + $primaryKey = $modelName . $foreignKey . json_encode($value, JSON_UNESCAPED_UNICODE); + if (!$relation->hasIdentification($primaryKey)) { + $relation->bindIdentification($primaryKey, $modelName::query()->whereIn($foreignKey, $value)); + } + + return new HasMany($primaryKey); } /** diff --git a/Relation.php b/Relation.php index 21ea593..55644ce 100644 --- a/Relation.php +++ b/Relation.php @@ -30,6 +30,15 @@ class Relation extends Component return $this; } + /** + * @param string $identification + * @return bool + */ + public function hasIdentification(string $identification): bool + { + return isset($this->_query[$identification]) && $this->_query[$identification] instanceof ActiveQuery; + } + /** * @param string $name * @return ActiveQuery|null diff --git a/Traits/HasBase.php b/Traits/HasBase.php index 2e1489d..07a2ef7 100644 --- a/Traits/HasBase.php +++ b/Traits/HasBase.php @@ -12,13 +12,17 @@ namespace Database\Traits; use Database\ModelInterface; use Database\Collection; use Database\Relation; -use Exception; +use Kiri; /** * Class HasBase * @package Database * * @include Query + * + * @method first($name) + * @method all($name) + * @method count($name) */ abstract class HasBase implements \Database\Traits\Relation { @@ -30,39 +34,18 @@ abstract class HasBase implements \Database\Traits\Relation * @var ModelInterface */ protected mixed $model; - + + protected mixed $value = 0; - - /** @var Relation $_relation */ - protected Relation $_relation; - + /** * HasBase constructor. - * @param ModelInterface $model - * @param string $primaryId - * @param $value - * @param Relation $relation - * @throws Exception + * @param string $name */ - public function __construct(mixed $model, public string $primaryId, $value, Relation $relation) + public function __construct(public string $name) { - if (!class_exists($model)) { - throw new Exception('Model must implement ' . $model); - } - if (!in_array(ModelInterface::class, class_implements($model))) { - throw new Exception('Model must implement ' . $model); - } - if (is_array($value)) { - if (empty($value)) $value = []; - $_model = $model::query()->whereIn($primaryId, $value); - } else { - $_model = $model::query()->where(['t1.' . $primaryId => $value]); - } - - $this->value = is_array($value) ? json_encode($value, JSON_UNESCAPED_UNICODE) : $value; - $this->_relation = $relation->bindIdentification(md5($model . '_' . $primaryId . '_' . $this->value), $_model); - $this->model = $model; + ; } /** @@ -73,33 +56,21 @@ abstract class HasBase implements \Database\Traits\Relation public function __call($name, $arguments) { if (!method_exists($this, $name)) { - $key = $this->model . '_' . $this->primaryId . '_' . $this->value; - $this->_relation->getQuery($this->reKey())->$name(...$arguments); + $relation = Kiri::getDi()->get(Relation::class); + $relation->getQuery($this->name)->$name(...$arguments); } else { call_user_func([$this, $name], ...$arguments); } return $this; } - - /** - * @return string - */ - protected function reKey(): string - { - return md5($this->model . '_' . $this->primaryId . '_' . $this->value); - } - - + /** * @param $name * @return mixed */ public function __get($name): mixed { - if (empty($this->value)) { - return null; - } return $this->get(); } }