mathematics([$column => $value], '+')) { return false; } $this->{$column} += $value; return $this->refresh(); } /** * @param string $column * @param int|float $value * @return ModelInterface|false * @throws */ public function decrement(string $column, int|float $value): bool|ModelInterface { if (!$this->mathematics([$column => $value], '-')) { return false; } $this->{$column} -= $value; return $this->refresh(); } /** * @param array $columns * @return ModelInterface|false * @throws */ public function increments(array $columns): bool|static { if (!$this->mathematics($columns, '+')) { return false; } foreach ($columns as $key => $attribute) { $this->$key += $attribute; } return $this; } /** * @param array $columns * @return ModelInterface|false * @throws */ public function decrements(array $columns): bool|static { if (!$this->mathematics($columns, '-')) { return false; } foreach ($columns as $key => $attribute) { $this->$key -= $attribute; } return $this; } /** * @param array $condition * @param array $attributes * @return bool|static * @throws */ public static function findOrCreate(array $condition, array $attributes): bool|static { $model = static::instance(); $connection = $model->getConnection()->beginTransaction(); try { /** @var static $select */ $select = $model::query()->where($condition)->first(); if ($select === null) { $select = $model::populate(array_merge($condition, $attributes)); if (!$select->save()) { throw new Exception('保存失败: ' . $model->getLastError()); } } $connection->commit(); return $select; } catch (\Throwable $throwable) { $connection->rollback(); return \Kiri::getLogger()->failure($throwable); } } /** * @param array $condition * @param array $attributes * @return bool|static * @throws */ public static function createOrUpdate(array $condition, array $attributes = []): bool|static { $model = static::instance(); $connection = $model->getConnection()->beginTransaction(); try { /** @var static $select */ $select = static::query()->where($condition)->first(); if (empty($select)) { $select = static::populate($condition); } $select->attributes = $attributes; if (!$select->save()) { throw new Exception('保存失败: ' . $model->getLastError()); } $connection->commit(); return $select; } catch (\Throwable $throwable) { $connection->rollback(); return \Kiri::getLogger()->failure($throwable); } } /** * @param string $name * @param array $arguments * @return Model|ActiveQuery */ public static function __callStatic(string $name, array $arguments): static|ActiveQuery { // TODO: Change the autogenerated stub if (method_exists(static::class, $name)) { return call_user_func(static::class . '::' . $name, ...$arguments); } else { return static::query()->{$name}(...$arguments); } } /** * @param $columns * @param $action * @return array|bool|int|string|null * @throws */ private function mathematics($columns, $action): int|bool|array|string|null { $condition = [$this->getPrimary() => $this->getPrimaryValue()]; $activeQuery = static::query()->where($condition); $create = SqlBuilder::builder($activeQuery)->mathematics($columns, $action); if (is_bool($create)) { return false; } return $activeQuery->buildCommand($create)->exec(); } /** * @param array $params * @return ModelInterface|bool * @throws */ public function update(array $params): static|bool { if (!$this->validator($this->rules()) || !$this->beforeSave($this)) { return FALSE; } $condition = []; $oldPrams = []; foreach ($this->_oldAttributes as $key => $attribute) { if (!array_key_exists($key, $params) || $params[$key] == $attribute) { $condition[$key] = $attribute; } else { $oldPrams[$key] = $this->_oldAttributes[$attribute]; } } return $this->updateInternal($oldPrams, $condition, $params); } /** * @param array $data * @return bool * @throws */ public static function inserts(array $data): bool { if (empty($data)) { return trigger_print_error('Insert data empty.', 'mysql'); } return static::query()->insert($data); } /** * @return bool * @throws */ public function delete(): bool { if (!$this->beforeDelete()) { return false; } if ($this->hasPrimary()) { $result = static::deleteByCondition(['id' => $this->getPrimaryValue()]); } else { $result = static::deleteByCondition($this->_attributes); } return $this->afterDelete($result); } /** * @return array * @throws */ public function toArray(): array { $data = $this->_attributes; foreach ($data as $key => $datum) { $method = 'get' . ucfirst($key) . 'Attribute'; if (!method_exists($this, $method)) { continue; } $data[$key] = $this->{$method}($datum); } return $this->withs($data); } /** * @param $data * @return array */ private function withs($data): array { $with = $this->getWith(); foreach ($with as $value) { $join = $this->withRelate($value); if ($join instanceof \Arrayable) { $join = $join->toArray(); } $data[$value] = $join; } return $data; } /** * @param ModelInterface|string $modelName * @param $foreignKey * @param $localKey * @return string * @throws */ private function _hasBase(ModelInterface|string $modelName, $foreignKey, $localKey): string { if (($value = $this->{$localKey}) === null) { throw new Exception("Need join table primary key."); } $relation = $this->getRelation(); $primaryKey = $modelName . $foreignKey . $value; if (!$relation->hasIdentification($primaryKey)) { $relation->bindIdentification($primaryKey, $modelName::query()->where([$foreignKey => $value])); } return $primaryKey; } /** * @param ModelInterface|string $modelName * @param $foreignKey * @param $localKey * @return HasOne|ActiveQuery * @throws */ public function hasOne(ModelInterface|string $modelName, $foreignKey, $localKey): HasOne|ActiveQuery { return new HasOne($this->_hasBase($modelName, $foreignKey, $localKey)); } /** * @param ModelInterface|string $modelName * @param $foreignKey * @param $localKey * @return ActiveQuery|HasCount * @throws */ public function hasCount(ModelInterface|string $modelName, $foreignKey, $localKey): ActiveQuery|HasCount { return new HasCount($this->_hasBase($modelName, $foreignKey, $localKey)); } /** * @param ModelInterface|string $modelName * @param $foreignKey * @param $localKey * @return ActiveQuery|HasMany * @throws */ public function hasMany(ModelInterface|string $modelName, $foreignKey, $localKey): ActiveQuery|HasMany { return new HasMany($this->_hasBase($modelName, $foreignKey, $localKey)); } /** * @param ModelInterface|string $modelName * @param $foreignKey * @param $localKey * @return ActiveQuery|HasMany * @throws */ public function hasIn(ModelInterface|string $modelName, $foreignKey, $localKey): ActiveQuery|HasMany { if (($value = $this->{$localKey}) === null) { throw new Exception("Need join table primary key."); } $relation = $this->getRelation(); $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); } /** * @param bool $result * @return bool */ public function afterDelete(bool $result): bool { return $result; } /** * @return bool * @throws Exception */ public function beforeDelete(): bool { return TRUE; } }