123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800 |
- <?php
- namespace yii\db;
- use Yii;
- use yii\base\InvalidArgumentException;
- use yii\base\InvalidConfigException;
- use yii\helpers\ArrayHelper;
- use yii\helpers\Inflector;
- use yii\helpers\StringHelper;
- class ActiveRecord extends BaseActiveRecord
- {
-
- const OP_INSERT = 0x01;
-
- const OP_UPDATE = 0x02;
-
- const OP_DELETE = 0x04;
-
- const OP_ALL = 0x07;
-
- public function loadDefaultValues($skipIfSet = true)
- {
- foreach (static::getTableSchema()->columns as $column) {
- if ($column->defaultValue !== null && (!$skipIfSet || $this->{$column->name} === null)) {
- $this->{$column->name} = $column->defaultValue;
- }
- }
- return $this;
- }
-
- public static function getDb()
- {
- return Yii::$app->getDb();
- }
-
- public static function findBySql($sql, $params = [])
- {
- $query = static::find();
- $query->sql = $sql;
- return $query->params($params);
- }
-
- protected static function findByCondition($condition)
- {
- $query = static::find();
- if (!ArrayHelper::isAssociative($condition)) {
-
- $primaryKey = static::primaryKey();
- if (isset($primaryKey[0])) {
- $pk = $primaryKey[0];
- if (!empty($query->join) || !empty($query->joinWith)) {
- $pk = static::tableName() . '.' . $pk;
- }
-
- $condition = [$pk => is_array($condition) ? array_values($condition) : $condition];
- } else {
- throw new InvalidConfigException('"' . get_called_class() . '" must have a primary key.');
- }
- } elseif (is_array($condition)) {
- $aliases = static::filterValidAliases($query);
- $condition = static::filterCondition($condition, $aliases);
- }
- return $query->andWhere($condition);
- }
-
- protected static function filterValidAliases(Query $query)
- {
- $tables = $query->getTablesUsedInFrom();
- $aliases = array_diff(array_keys($tables), $tables);
- return array_map(function ($alias) {
- return preg_replace('/{{([\w]+)}}/', '$1', $alias);
- }, array_values($aliases));
- }
-
- protected static function filterCondition(array $condition, array $aliases = [])
- {
- $result = [];
- $db = static::getDb();
- $columnNames = static::filterValidColumnNames($db, $aliases);
- foreach ($condition as $key => $value) {
- if (is_string($key) && !in_array($db->quoteSql($key), $columnNames, true)) {
- throw new InvalidArgumentException('Key "' . $key . '" is not a column name and can not be used as a filter');
- }
- $result[$key] = is_array($value) ? array_values($value) : $value;
- }
- return $result;
- }
-
- protected static function filterValidColumnNames($db, array $aliases)
- {
- $columnNames = [];
- $tableName = static::tableName();
- $quotedTableName = $db->quoteTableName($tableName);
- foreach (static::getTableSchema()->getColumnNames() as $columnName) {
- $columnNames[] = $columnName;
- $columnNames[] = $db->quoteColumnName($columnName);
- $columnNames[] = "$tableName.$columnName";
- $columnNames[] = $db->quoteSql("$quotedTableName.[[$columnName]]");
- foreach ($aliases as $tableAlias) {
- $columnNames[] = "$tableAlias.$columnName";
- $quotedTableAlias = $db->quoteTableName($tableAlias);
- $columnNames[] = $db->quoteSql("$quotedTableAlias.[[$columnName]]");
- }
- }
- return $columnNames;
- }
-
- public function refresh()
- {
- $query = static::find();
- $tableName = key($query->getTablesUsedInFrom());
- $pk = [];
-
- foreach ($this->getPrimaryKey(true) as $key => $value) {
- $pk[$tableName . '.' . $key] = $value;
- }
- $query->where($pk);
-
- $record = $query->one();
- return $this->refreshInternal($record);
- }
-
- public static function updateAll($attributes, $condition = '', $params = [])
- {
- $command = static::getDb()->createCommand();
- $command->update(static::tableName(), $attributes, $condition, $params);
- return $command->execute();
- }
-
- public static function updateAllCounters($counters, $condition = '', $params = [])
- {
- $n = 0;
- foreach ($counters as $name => $value) {
- $counters[$name] = new Expression("[[$name]]+:bp{$n}", [":bp{$n}" => $value]);
- $n++;
- }
- $command = static::getDb()->createCommand();
- $command->update(static::tableName(), $counters, $condition, $params);
- return $command->execute();
- }
-
- public static function deleteAll($condition = null, $params = [])
- {
- $command = static::getDb()->createCommand();
- $command->delete(static::tableName(), $condition, $params);
- return $command->execute();
- }
-
- public static function find()
- {
- return Yii::createObject(ActiveQuery::className(), [get_called_class()]);
- }
-
- public static function tableName()
- {
- return '{{%' . Inflector::camel2id(StringHelper::basename(get_called_class()), '_') . '}}';
- }
-
- public static function getTableSchema()
- {
- $tableSchema = static::getDb()
- ->getSchema()
- ->getTableSchema(static::tableName());
- if ($tableSchema === null) {
- throw new InvalidConfigException('The table does not exist: ' . static::tableName());
- }
- return $tableSchema;
- }
-
- public static function primaryKey()
- {
- return static::getTableSchema()->primaryKey;
- }
-
- public function attributes()
- {
- return array_keys(static::getTableSchema()->columns);
- }
-
- public function transactions()
- {
- return [];
- }
-
- public static function populateRecord($record, $row)
- {
- $columns = static::getTableSchema()->columns;
- foreach ($row as $name => $value) {
- if (isset($columns[$name])) {
- $row[$name] = $columns[$name]->phpTypecast($value);
- }
- }
- parent::populateRecord($record, $row);
- }
-
- public function insert($runValidation = true, $attributes = null)
- {
- if ($runValidation && !$this->validate($attributes)) {
- Yii::info('Model not inserted due to validation error.', __METHOD__);
- return false;
- }
- if (!$this->isTransactional(self::OP_INSERT)) {
- return $this->insertInternal($attributes);
- }
- $transaction = static::getDb()->beginTransaction();
- try {
- $result = $this->insertInternal($attributes);
- if ($result === false) {
- $transaction->rollBack();
- } else {
- $transaction->commit();
- }
- return $result;
- } catch (\Exception $e) {
- $transaction->rollBack();
- throw $e;
- } catch (\Throwable $e) {
- $transaction->rollBack();
- throw $e;
- }
- }
-
- protected function insertInternal($attributes = null)
- {
- if (!$this->beforeSave(true)) {
- return false;
- }
- $values = $this->getDirtyAttributes($attributes);
- if (($primaryKeys = static::getDb()->schema->insert(static::tableName(), $values)) === false) {
- return false;
- }
- foreach ($primaryKeys as $name => $value) {
- $id = static::getTableSchema()->columns[$name]->phpTypecast($value);
- $this->setAttribute($name, $id);
- $values[$name] = $id;
- }
- $changedAttributes = array_fill_keys(array_keys($values), null);
- $this->setOldAttributes($values);
- $this->afterSave(true, $changedAttributes);
- return true;
- }
-
- public function update($runValidation = true, $attributeNames = null)
- {
- if ($runValidation && !$this->validate($attributeNames)) {
- Yii::info('Model not updated due to validation error.', __METHOD__);
- return false;
- }
- if (!$this->isTransactional(self::OP_UPDATE)) {
- return $this->updateInternal($attributeNames);
- }
- $transaction = static::getDb()->beginTransaction();
- try {
- $result = $this->updateInternal($attributeNames);
- if ($result === false) {
- $transaction->rollBack();
- } else {
- $transaction->commit();
- }
- return $result;
- } catch (\Exception $e) {
- $transaction->rollBack();
- throw $e;
- } catch (\Throwable $e) {
- $transaction->rollBack();
- throw $e;
- }
- }
-
- public function delete()
- {
- if (!$this->isTransactional(self::OP_DELETE)) {
- return $this->deleteInternal();
- }
- $transaction = static::getDb()->beginTransaction();
- try {
- $result = $this->deleteInternal();
- if ($result === false) {
- $transaction->rollBack();
- } else {
- $transaction->commit();
- }
- return $result;
- } catch (\Exception $e) {
- $transaction->rollBack();
- throw $e;
- } catch (\Throwable $e) {
- $transaction->rollBack();
- throw $e;
- }
- }
-
- protected function deleteInternal()
- {
- if (!$this->beforeDelete()) {
- return false;
- }
-
-
- $condition = $this->getOldPrimaryKey(true);
- $lock = $this->optimisticLock();
- if ($lock !== null) {
- $condition[$lock] = $this->$lock;
- }
- $result = static::deleteAll($condition);
- if ($lock !== null && !$result) {
- throw new StaleObjectException('The object being deleted is outdated.');
- }
- $this->setOldAttributes(null);
- $this->afterDelete();
- return $result;
- }
-
- public function equals($record)
- {
- if ($this->isNewRecord || $record->isNewRecord) {
- return false;
- }
- return static::tableName() === $record->tableName() && $this->getPrimaryKey() === $record->getPrimaryKey();
- }
-
- public function isTransactional($operation)
- {
- $scenario = $this->getScenario();
- $transactions = $this->transactions();
- return isset($transactions[$scenario]) && ($transactions[$scenario] & $operation);
- }
- }
|