This commit is contained in:
2023-04-01 17:11:47 +08:00
parent 2aec2afc59
commit cd94d2dc57
7 changed files with 67 additions and 61 deletions
+1 -1
View File
@@ -95,7 +95,7 @@ abstract class Model extends Component implements ModelInterface, ArrayAccess, T
/** /**
* @var array * @var array
*/ */
private array $_with = []; protected array $_with = [];
/** /**
+3 -1
View File
@@ -5,6 +5,7 @@ namespace Database;
use Database\Traits\HasBase; use Database\Traits\HasBase;
use Exception; use Exception;
use Kiri;
/** /**
* Class HasCount * Class HasCount
@@ -19,7 +20,8 @@ class HasCount extends HasBase
*/ */
public function get(): array|ModelInterface|null public function get(): array|ModelInterface|null
{ {
return $this->_relation->count($this->reKey()); $relation = Kiri::getDi()->get(Relation::class);
return $relation->count($this->name);
} }
} }
+3 -1
View File
@@ -11,6 +11,7 @@ namespace Database;
use Database\Traits\HasBase; use Database\Traits\HasBase;
use Exception; use Exception;
use Kiri;
/** /**
* Class HasMany * Class HasMany
@@ -27,6 +28,7 @@ class HasMany extends HasBase
*/ */
public function get(): array|Collection|null public function get(): array|Collection|null
{ {
return $this->_relation->get($this->reKey()); $relation = Kiri::getDi()->get(Relation::class);
return $relation->get($this->name);
} }
} }
+3 -1
View File
@@ -11,6 +11,7 @@ namespace Database;
use Database\Traits\HasBase; use Database\Traits\HasBase;
use Exception; use Exception;
use Kiri;
/** /**
* Class HasOne * Class HasOne
@@ -26,6 +27,7 @@ class HasOne extends HasBase
*/ */
public function get(): array|ModelInterface|null public function get(): array|ModelInterface|null
{ {
return $this->_relation->first($this->reKey()); $relation = Kiri::getDi()->get(Relation::class);
return $relation->first($this->name);
} }
} }
+34 -14
View File
@@ -110,7 +110,7 @@ class Model extends Base\Model
if (empty($attributes)) { if (empty($attributes)) {
return $logger->addError(FIND_OR_CREATE_MESSAGE, 'mysql'); return $logger->addError(FIND_OR_CREATE_MESSAGE, 'mysql');
} }
/** @var static $select */ /** @var static $select */
$select = static::query()->where($condition)->first(); $select = static::query()->where($condition)->first();
if (!empty($select)) { if (!empty($select)) {
@@ -279,7 +279,7 @@ class Model extends Base\Model
*/ */
private function withRelates($relates): array private function withRelates($relates): array
{ {
foreach ($this->getWith() as $val) { foreach ($this->_with as $val) {
$relates[$val] = $this->withRelate($val); $relates[$val] = $this->withRelate($val);
} }
return $relates; return $relates;
@@ -287,13 +287,13 @@ class Model extends Base\Model
/** /**
* @param string $modelName * @param ModelInterface|string $modelName
* @param $foreignKey * @param $foreignKey
* @param $localKey * @param $localKey
* @return HasOne|ActiveQuery * @return HasOne|ActiveQuery
* @throws Exception * @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) { if (($value = $this->{$localKey}) === null) {
throw new Exception("Need join table primary key."); throw new Exception("Need join table primary key.");
@@ -301,18 +301,23 @@ class Model extends Base\Model
$relation = $this->getRelation(); $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 $foreignKey
* @param $localKey * @param $localKey
* @return ActiveQuery|HasCount * @return ActiveQuery|HasCount
* @throws Exception * @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) { if (($value = $this->{$localKey}) === null) {
throw new Exception("Need join table primary key."); throw new Exception("Need join table primary key.");
@@ -320,18 +325,23 @@ class Model extends Base\Model
$relation = $this->getRelation(); $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 $foreignKey
* @param $localKey * @param $localKey
* @return ActiveQuery|HasMany * @return ActiveQuery|HasMany
* @throws Exception * @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) { if (($value = $this->{$localKey}) === null) {
throw new Exception("Need join table primary key."); throw new Exception("Need join table primary key.");
@@ -339,17 +349,22 @@ class Model extends Base\Model
$relation = $this->getRelation(); $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 $foreignKey
* @param $localKey * @param $localKey
* @return ActiveQuery|HasMany * @return ActiveQuery|HasMany
* @throws Exception * @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) { if (($value = $this->{$localKey}) === null) {
throw new Exception("Need join table primary key."); throw new Exception("Need join table primary key.");
@@ -357,7 +372,12 @@ class Model extends Base\Model
$relation = $this->getRelation(); $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);
} }
/** /**
+9
View File
@@ -30,6 +30,15 @@ class Relation extends Component
return $this; 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 * @param string $name
* @return ActiveQuery|null * @return ActiveQuery|null
+14 -43
View File
@@ -12,13 +12,17 @@ namespace Database\Traits;
use Database\ModelInterface; use Database\ModelInterface;
use Database\Collection; use Database\Collection;
use Database\Relation; use Database\Relation;
use Exception; use Kiri;
/** /**
* Class HasBase * Class HasBase
* @package Database * @package Database
* *
* @include Query * @include Query
*
* @method first($name)
* @method all($name)
* @method count($name)
*/ */
abstract class HasBase implements \Database\Traits\Relation abstract class HasBase implements \Database\Traits\Relation
{ {
@@ -30,39 +34,18 @@ abstract class HasBase implements \Database\Traits\Relation
* @var ModelInterface * @var ModelInterface
*/ */
protected mixed $model; protected mixed $model;
protected mixed $value = 0; protected mixed $value = 0;
/** @var Relation $_relation */
protected Relation $_relation;
/** /**
* HasBase constructor. * HasBase constructor.
* @param ModelInterface $model * @param string $name
* @param string $primaryId
* @param $value
* @param Relation $relation
* @throws Exception
*/ */
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) public function __call($name, $arguments)
{ {
if (!method_exists($this, $name)) { if (!method_exists($this, $name)) {
$key = $this->model . '_' . $this->primaryId . '_' . $this->value; $relation = Kiri::getDi()->get(Relation::class);
$this->_relation->getQuery($this->reKey())->$name(...$arguments); $relation->getQuery($this->name)->$name(...$arguments);
} else { } else {
call_user_func([$this, $name], ...$arguments); call_user_func([$this, $name], ...$arguments);
} }
return $this; return $this;
} }
/**
* @return string
*/
protected function reKey(): string
{
return md5($this->model . '_' . $this->primaryId . '_' . $this->value);
}
/** /**
* @param $name * @param $name
* @return mixed * @return mixed
*/ */
public function __get($name): mixed public function __get($name): mixed
{ {
if (empty($this->value)) {
return null;
}
return $this->get(); return $this->get();
} }
} }