Ошибка при обновлений поля [Решено]
-
SSDD
- Сообщения: 43
- Зарегистрирован: 2013.11.06, 18:47
Ошибка при обновлений поля [Решено]
Пытаюсь обновить поля status, но оно не обновляется debugger показывает yiidbActiveRecord::update Model not updated due to validation error.
смотрю varDumper показывает что поля team_home и team_away должны быть строкой, хотя я их не обновляю и значения не меняются,
В чем проблема ? может из-за того что поля являються внешними ключами ? (оба поля я вляються внешними ключами таблицы Team)
Код: Выделить всё
$status = 2;
$value = Matches::findOne($id = 23);
$value->status = $status;
$value->update();
VarDumper показывает
Код: Выделить всё
commonmodulesfootballmodelsMatches#1
(
[
[yiidbBaseActiveRecord:_attributes] => [
'id' => 23
'team_home' => 11
'team_away' => 16
'date_time' => '16.08.2014 15:45'
'status' => 2
'referee_id' => null
'season_id' => 4
'tournament_id' => 1
'tour_id' => 0
]
[yiidbBaseActiveRecord:_oldAttributes] => [
'id' => 23
'team_home' => 11
'team_away' => 16
'date_time' => '16.08.2014 15:45'
'status' => 0
'referee_id' => null
'season_id' => 4
'tournament_id' => 1
'tour_id' => 0
]
[yiidbBaseActiveRecord:_related] => []
[yiibaseModel:_errors] => [
'team_home' => [
0 => 'Значение «Команда хозяев» должно быть строкой.'
]
'team_away' => [
0 => 'Значение «Команда гостей» должно быть строкой.'
]
]
Ругаеться на
Код: Выделить всё
'team_home' => [
0 => 'Значение «Команда хозяев» должно быть строкой.'
]
'team_away' => [
0 => 'Значение «Команда гостей» должно быть строкой.'
]
Последний раз редактировалось SSDD 2014.09.12, 19:10, всего редактировалось 1 раз.
-
SSDD
- Сообщения: 43
- Зарегистрирован: 2013.11.06, 18:47
Re: Ошибка при обновлений поля
Сообщение
SSDD » 2014.09.12, 17:03
Модель Matches разные варианты пробовал не помогает
Код: Выделить всё
public function rules()
{
return [
//['status', 'default', 'value' => 1],
[['tournament_id', 'team_home', 'team_away', 'date_time', 'tour_id'], 'required'],
[['team_home', 'team_away', 'date_time'], 'unique', 'targetAttribute' => ['team_home', 'team_away', 'date_time']],
[['referee_id', 'season_id', 'tournament_id', 'tour_id'], 'integer'],
[['team_home', 'team_away', 'date_time', 'team_home', 'team_away'], 'string', 'max' => 45],
['status', 'in', 'range' => array_keys(self::getStatusArray())]
];
}
-
SSDD
- Сообщения: 43
- Зарегистрирован: 2013.11.06, 18:47
Re: Ошибка при обновлений поля
Сообщение
SSDD » 2014.09.12, 19:09
Что называеться разул глаза бывает сорри, и спасибо за комент
Код: Выделить всё
[['team_home', 'team_away', 'date_time', 'team_home', 'team_away'], 'string', 'max' => 45],
I have been fighting with an «invisible» error.
I am trying to do what I see as a simple update of a field, however the field never gets updated. Strangely, Yii2 doesn’t output any error except for the following log:
info yiidbActiveRecord::update Model not updated due to validation error.
Code in controler:
public function actionUpdate($id)
{
$model = $this->findModel($id);
$scenario = (Yii::$app->user->identity->technology == $id) ? "updateOwner" : "updateGuest";
$model->scenario = $scenario;
$function = $scenario."Technology";
if ($model->load(Yii::$app->request->post()) && $model->validate() && Technology::$function($model)) {
return $this->render(['view', 'model' => $model->id]);
} else {
return $this->render($scenario, [
'model' => $model,
]);
}
}
The function in model:
public function updateGuestTechnology($model){
$transaction = Yii::$app->db->beginTransaction();
try
{
$technology = Technology::findOne($model->id);
$user = Yii::$app->user->identity;
$technology->scenario = "updateGuest";
$technology->bno_coins += $model->bno_coins;
$technology->bots += $model->bots;
$technology->save();
//The user query works just fine.
$user->scenario = "update";
$user->bots -= $model->bots;
$user->bno_coins -= $model->bno_coins;
$user->save();
$transaction->commit();
}
catch (Exception $e)
{
$transaction->rollBack();
Yii::error("Error during technology update by owner transaction. UserID: {$buyer->id}");
return false; //Transaction failed
}
Yii::info("Technology updated by non-owner! Technology ID: {$technology->id} . UserID: {$user->id}");
return true;
}
Scenario:
"updateGuest" => ["bno_coins", "bots"],
Rules for bno_coins
and bots
:
//bno_coins rules
["bno_coins", "required", "on" => ["create", "updateOwner", "updateGuest"]],
["bno_coins", "integer", "min" => 0, "max" => Yii::$app->user->identity->bno_coins, "on" => ["create", "updateOwner", "updateGuest"]],
//bots rules
["bots", "required", "on" => ["create", "updateOwner", "updateGuest"]],
["bots", "integer", "min" => 0, "max" => Yii::$app->user->identity->bots, "on" => ["create", "updateOwner", "updateGuest"]],
$model->errors;
Doesn’t contain any data. It seems that the whole $model
doesn’t contain any values (that would explain why the validation fails). However, according to Yii Debugger, the requests contain all necessary information.
using yii ver 2.1.0
unable to attache the file
pasting it here
<?php /** * @link http://www.yiiframework.com/ * @copyright Copyright (c) 2008 Yii Software LLC * @license http://www.yiiframework.com/license/ */ namespace yiidb; use Yii; use yiibaseInvalidConfigException; use yiihelpersArrayHelper; use yiihelpersInflector; use yiihelpersStringHelper; /* * @author Qiang Xue <qiang.xue@gmail.com> * @author Carsten Brandt <mail@cebe.cc> * @since 2.0 */ 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 ($this->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)) { // query by primary key $primaryKey = static::primaryKey(); if (isset($primaryKey[0])) { $pk = $primaryKey[0]; if (!empty($query->join) || !empty($query->joinWith)) { $pk = static::tableName() . '.' . $pk; } $condition = [$pk => $condition]; } else { throw new InvalidConfigException('"' . get_called_class() . '" must have a primary key.'); } } return $query->andWhere($condition); } 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 = '', $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() { $schema = static::getDb()->getSchema()->getTableSchema(static::tableName()); if ($schema !== null) { return $schema; } else { throw new InvalidConfigException("The table does not exist: " . static::tableName()); } } public static function primaryKey() { return static::getTableSchema()->primaryKey; } public function attributes() { return array_keys(static::getTableSchema()->columns); } public function transactions() { return []; } /** * @inheritdoc */ 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; } } protected function insertInternal($attributes = null) { if (!$this->beforeSave(true)) { return false; } $values = $this->getDirtyAttributes($attributes); $fdaddy = $attributes[$attributes]; error_log("HERE HERE : " . __METHOD__ . "attributes = " . $attributes, 0 ); if (empty($values)) { foreach ($this->getPrimaryKey(true) as $key => $value) { $values[$key] = $value; } } if (($primaryKeys = static::getDb()->schema->insert($this->tableName(), $values)) === false) { return false; } foreach ($primaryKeys as $name => $value) { $id = $this->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; } } 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; } } protected function deleteInternal() { if (!$this->beforeDelete()) { return false; } // we do not check the return value of deleteAll() because it's possible // the record is already deleted in the database and thus the method will return 0 $condition = $this->getOldPrimaryKey(true); $lock = $this->optimisticLock(); if ($lock !== null) { $condition[$lock] = $this->$lock; } $result = $this->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 $this->tableName() === $record->tableName() && $this->getPrimaryKey() === $record->getPrimaryKey(); } public function isTransactional($operation) { $scenario = $this->getScenario(); $transactions = $this->transactions(); return isset($transactions[$scenario]) && ($transactions[$scenario] & $operation); } }
Организую загрузку картинок.
Модель:
class Image extends yiidbActiveRecord
{
public $files;
public function rules()
{
return [
[[ 'id_actoutrs', 'id_category', 'id_pages', 'id_serial', 'id_user', 'for_home'], 'integer'],
[['files'], 'file', 'extensions' => 'png, jpg'],
[['title_alt', 'path', 'name'], 'string', 'max' => 255],
];
}
Представление:
<?php $form = ActiveForm::begin(['options' => ['enctype' => 'multipart/form-data']]); ?>
<?= $form->field($model, 'title_alt')->textInput(['maxlength' => true]) ?>
<?= $form->field($model, 'files[]')->fileInput(['multiple' => true]) ?>
<?= $form->field($model, 'for_home')->radioList([
'0' => Yii::t('app','NO'),
'1' => Yii::t('app','YES')
]); ?>
Контролер:
public function actionCreate()
{
$model = new Image();
$class=Yii::$app->request->get("class");
$feilds =Yii::$app->request->get("feilds");
$value=Yii::$app->request->get("value");
if ($model->load(Yii::$app->request->post())) {
$model->files = UploadedFile::getInstances($model, 'files');
foreach ($model->files as $file) {
$files_to = TransliteratorHelper::process($file->name, '', 'en');
$years=date('Y');
$mounts=date('m');
$path =0;
switch ($class) {
case 'category':
$path = 'category';
break;
}
if (file_exists(Yii::getAlias('@frontend/web/').$path.'/'.$years.'/'.$mounts.'/')) {
} else {
mkdir(Yii::getAlias('@frontend/web/').$path.'/'.$years.'/'.$mounts.'/', 0775, true);
}
$file->saveAs(Yii::getAlias('@frontend/web/').$path.'/'.$years.'/'.$mounts.'/'.$files_to);
$model->path=$path.'/'.$years.'/'.$mounts.'/';
$model->name = $files_to;
$model->save();
}
Дебаг показывает такую ошибку:
20:26:09.879 info yiidbActiveRecord::insert Model not inserted due to validation error.
C:OpenServerdomainsfilm.lcbackendcontrollersImageController.php (98)
print_r( $model->getErrors())
выдает такую ошибку:
Array ( [files] => Array ( [0] => Загрузите файл. ) ) 1
В чем проблема?
When I add comment sometimes appears javascript alert with message «No Reason Phrase». What is this and how can I control this?
The code below
function r(a) {
return /[\"<>.;]/.exec(a) != null &&
typeof encodeURIComponent != v ? encodeURIComponent(a) : a
}
and this one:
/?/.test(b) && (b = b.split("?")[1]);
will throw an error:
An Error occurred while handling another error:
exception ‘RuntimeException’ with message ‘Unclosed string at position: 1317283’
in …/vendor/tedivm/jshrink/src/JShrink/Minifier.php:483
The first one is caused by the «unclosed» quote in the regex, not sure about the second one. A temporary fix that I did was to add a comment so that the parser ignores the issue:
function r(a) {
return /[\"<>.;]/.exec(a) /*"*/ != null &&
typeof encodeURIComponent != v ? encodeURIComponent(a) : a
}
and
/?/.test(b) /*this is a temp fix for the compressor. removing this comment will cause an error*/
&& (b = b.split("?")[1]);
This happens when I add FusionCharts.js in my site so other third party libs might cause this as well.
Thanks for the help.
Hi
I am using pretty url’s. http://some-dev-domain.test/comments/index
throws NotFoundException.
Where is this route registered?
I used your extension to load comments in a modal window. It worked fine and the page is rendered correctly but after submitting new comment and after a «success» response the whole page is reloaded.
As far as I can say it happens because of the PJAX reload but I do not understand why the whole page gets reloaded instead of only PJAX container.
Any thoughts on this issue would be appreciated.
Hello,
i would like to ask if this widget enables users to add comments without neither authenticating nor giving their email.
Just an optional display name, no registration required.
Thanks
I’m using advanced environment.
And me need to use it for not authorized users.
Can I do it?
I have used kartik/treemanager extension model for this extension . Everything work as well for initial node , but when i change the node of tree and after that submit the comment , comment button stuck in «loading…» and shows the below error . although comment saved in database .
Hello,
When I delete one parent comment and after that trying to delete it’s child comment, i got a js alert popup, what says only: «Internal Server error».
I know that I not must to delete a childs of a deleted parent, but I can, because there won’t hide after parents deletion.
Maybe it would enough to disable/hide the delete link of the child coments.
in the debug-bar I see only this message: «Model not updated due to validation error.»
Anyway, great module, thanks for that!
Hi,
Does your widget work when enclosed in ActiveForm? It shows but does not save. Is this expected behavior? Can I make it work within ActiveForm?
<?php echo yii2modcommentswidgetsComment::widget([
'model' => $model,
'dataProviderConfig' => [
'pagination' => [
'pageSize' => 5
],
]]); ?>
yii2 advanced (2.0.10-dev)
«yii2mod/yii2-comments»: «dev-master»
Пишу в /common/config/main.php
` ‘modules’ => [
'comment' => [
'class' => 'yii2modcommentsModule',
'enableInlineEdit' => true,
'controllerMap' => [
'default' => [
'class' => 'yii2modcommentscontrollersDefaultController',
'on beforeCreate' => ['frontendeventsBonusEvents', 'handleCheckFiveReview'],
'on afterCreate' => ['frontendeventsBonusEvents', 'handleAfterFirstComment'],
'on afterDelete' => ['frontendeventsBonusEvents', 'handleAfterDeleteComment'],`
beforeCreate , afterCreate — работают. А вот afterDelete не отрабатывает. Как быть ?
Hi all!
Thanks for your work with Yii2 Comments Extension. It really great!
Now I found one problem with level in comments tree.
I’m using default model and views.
Problem is, when I edited or delete comment with level > 1, after the action level of edited or deleted comment is upping. And it can be more then maxLevel, so with this case comment not showing.
I think, with that actions level should not up. Am i right?
You can see my short screen video, where I displaying a problem http://i.de-v.net/1504869692.webm
My module configuration is:
'comment' => [
'class' => 'yii2modcommentsModule',
'enableInlineEdit' => true,
'controllerMap' => [
'default' => [
'class' => 'yii2modcommentscontrollersDefaultController'
]
]
],
Thanks for you answer!
We have an entity field in the database with char(10) and when the module name encrypting the length was bigger than it can store, so it`s trimmed. So how i can get fully entity name like «posts», «news» etc …
Hi.
Can someone explain to me whats the whole point of the encryption stuff? Well i get the intentions, probably, but it will not stop any bot software right?
Hello!
I’m new to yii2 and if you dont mind I’ll ask you some question.
I’m use yii2-advanced template. Added your module via composer. Migrate all migrations without errors. Added to «common/config/main.php» this config string » ‘modules’ => [ ‘comment’ => [ ‘class’ => ‘yii2modcommentsModule’, ],] «
- If i havent config RBAC yet(but i have users table with user_role attribute) can I somehow access management section?
- Can I somehow make access to management section only from backend? for example backedn.mydomain.com/commets/index ?
Hi,
I have done the installation and configuration.
In my view after entering data in the comments field and clicking Post nothing saves.
I checked the comment table and there is nothing saved. No error messages. Where can I check?
(1) Setting unknown property: yii2modcommentsModule::enableInlineEdit
'modules' => [
// dsm 6 jun 17 : experimental
'comment' => [
'class' => 'yii2modcommentsModule',
// when admin can edit comments on frontend
// Setting unknown property: yii2modcommentsModule::enableInlineEdit
//'enableInlineEdit' => false,
],
I grep the package for enableInlineEdit and find nothing?
(2)
https://test.mysite.com/index.php?r=/comment/manage/index
SQLSTATE[42S22]: Column not found: 1054 Unknown column ‘a.username’ in ‘field list’
No mention of authors in the readme, no migrations.
A quick attempt to connect it to my user table failed (it wants a defined relation).
I am sorry to post idiot questions, and I suppose I will figure this out.
But if am doing something very stupid please let me know.
It seems like I have a half-baked version?
Looks very good. Thank you.
I had been fighting an error that I could not understand until I looked into sources. In module trait the module is hardcoded as «comment» and I had it as comments. I would prefer a Widget setting where we can pass module name or if it have to remain hardcoded then it should clearly be stated to avoid pains like mine.
Thank you for great extensions. I personally appreciate them
I am using mdmsoft in order to adminitrate the accesses rules and I can not access to the comment admin.
I have
'admin' => [
'class' => 'mdmadminModule',
'layout' => 'left-menu', // defaults to null, using the application's layout without the menu
],
and
'authManager' => [
'class' => 'yiirbacDbManager',
],
What I should do for fix it?
Thanks!
Create the following list of events:
- beforeCreate
- afterCreate
- beforeDelete
- afterDelete
I have an event attached to, for example, the reply option, but when a comment is created, everything is reloaded and the event is lost. I see that your comment.js is reloaded every time it creates a comment, how would I add my custom js file to that?
1 <?php 2 /** 3 * @link http://www.yiiframework.com/ 4 * @copyright Copyright (c) 2008 Yii Software LLC 5 * @license http://www.yiiframework.com/license/ 6 */ 7 8 namespace yiibehaviors; 9 10 use yiibaseInvalidCallException; 11 use yiidbBaseActiveRecord; 12 13 /** 14 * TimestampBehavior automatically fills the specified attributes with the current timestamp. 15 * 16 * To use TimestampBehavior, insert the following code to your ActiveRecord class: 17 * 18 * ```php 19 * use yiibehaviorsTimestampBehavior; 20 * 21 * public function behaviors() 22 * { 23 * return [ 24 * TimestampBehavior::className(), 25 * ]; 26 * } 27 * ``` 28 * 29 * By default, TimestampBehavior will fill the `created_at` and `updated_at` attributes with the current timestamp 30 * when the associated AR object is being inserted; it will fill the `updated_at` attribute 31 * with the timestamp when the AR object is being updated. The timestamp value is obtained by `time()`. 32 * 33 * Because attribute values will be set automatically, it's a good idea to make sure `created_at` and `updated_at` aren't 34 * in `rules()` method of the model. 35 * 36 * For the above implementation to work with MySQL database, please declare the columns(`created_at`, `updated_at`) as int(11) for being UNIX timestamp. 37 * 38 * If your attribute names are different or you want to use a different way of calculating the timestamp, 39 * you may configure the [[createdAtAttribute]], [[updatedAtAttribute]] and [[value]] properties like the following: 40 * 41 * ```php 42 * use yiidbExpression; 43 * 44 * public function behaviors() 45 * { 46 * return [ 47 * [ 48 * 'class' => TimestampBehavior::className(), 49 * 'createdAtAttribute' => 'create_time', 50 * 'updatedAtAttribute' => 'update_time', 51 * 'value' => new Expression('NOW()'), 52 * ], 53 * ]; 54 * } 55 * ``` 56 * 57 * In case you use an [[yiidbExpression]] object as in the example above, the attribute will not hold the timestamp value, but 58 * the Expression object itself after the record has been saved. If you need the value from DB afterwards you should call 59 * the [[yiidbActiveRecord::refresh()|refresh()]] method of the record. 60 * 61 * TimestampBehavior also provides a method named [[touch()]] that allows you to assign the current 62 * timestamp to the specified attribute(s) and save them to the database. For example, 63 * 64 * ```php 65 * $model->touch('creation_time'); 66 * ``` 67 * 68 * @author Qiang Xue <[email protected]> 69 * @author Alexander Kochetov <[email protected]> 70 * @since 2.0 71 */ 72 class TimestampBehavior extends AttributeBehavior 73 { 74 /** 75 * @var string the attribute that will receive timestamp value 76 * Set this property to false if you do not want to record the creation time. 77 */ 78 public $createdAtAttribute = 'created_at'; 79 /** 80 * @var string the attribute that will receive timestamp value. 81 * Set this property to false if you do not want to record the update time. 82 */ 83 public $updatedAtAttribute = 'updated_at'; 84 /** 85 * @inheritdoc 86 * 87 * In case, when the value is `null`, the result of the PHP function [time()](http://php.net/manual/en/function.time.php) 88 * will be used as value. 89 */ 90 public $value; 91 92 93 /** 94 * @inheritdoc 95 */ 96 public function init() 97 { 98 parent::init(); 99 100 if (empty($this->attributes)) { 101 $this->attributes = [ 102 BaseActiveRecord::EVENT_BEFORE_INSERT => [$this->createdAtAttribute, $this->updatedAtAttribute], 103 BaseActiveRecord::EVENT_BEFORE_UPDATE => $this->updatedAtAttribute, 104 ]; 105 } 106 } 107 108 /** 109 * @inheritdoc 110 * 111 * In case, when the [[value]] is `null`, the result of the PHP function [time()](http://php.net/manual/en/function.time.php) 112 * will be used as value. 113 */ 114 protected function getValue($event) 115 { 116 if ($this->value === null) { 117 returntime(); 118 } 119 return parent::getValue($event); 120 } 121 122 /** 123 * Updates a timestamp attribute to the current timestamp. 124 * 125 * ```php 126 * $model->touch('lastVisit'); 127 * ``` 128 * @param string $attribute the name of the attribute to update. 129 * @throws InvalidCallException if owner is a new record (since version 2.0.6). 130 */ 131 public function touch($attribute) 132 { 133 /* @var $owner BaseActiveRecord */ 134 $owner = $this->owner; 135 if ($owner->getIsNewRecord()) { 136 throw new InvalidCallException('Updating the timestamp is not possible on a new record.'); 137 } 138 $owner->updateAttributes(array_fill_keys((array) $attribute, $this->getValue(null))); 139 } 140 }
The public function init(){} in TimestampBehavior initializes the binding event processing method data
1 /** 2 * @inheritdoc 3 */ 4 public function init() 5 { 6 parent::init(); 7 8 if (empty($this->attributes)) { 9 $this->attributes = [ 10 BaseActiveRecord::EVENT_BEFORE_INSERT => [$this->createdAtAttribute, $this->updatedAtAttribute], 11 BaseActiveRecord::EVENT_BEFORE_UPDATE => $this->updatedAtAttribute, 12 ]; 13 } 14 }
TimestampBehavior The events() method in the parent AttributeBehavior executes the handle :evaluateAttributes method for event binding
1 /** 2 * @inheritdoc 3 */ 4 public function events() 5 { 6 return array_fill_keys( 7 array_keys($this->attributes), 8 'evaluateAttributes' 9 ); 10 }
Event binding method: evaluateAttributes method,
1 /** 2 * Evaluates the attribute value and assigns it to the current attributes. 3 * @param Event $event 4 */ 5 public function evaluateAttributes($event) 6 { 7 if ($this->skipUpdateOnClean 8 && $event->name == ActiveRecord::EVENT_BEFORE_UPDATE 9 && empty($this->owner->dirtyAttributes) 10 ) { 11 return; 12 } 13 14 if (!empty($this->attributes[$event->name])) { 15 $attributes = (array) $this->attributes[$event->name]; 16 $value = $this->getValue($event); 17 foreach ($attributes as $attribute) { 18 // ignore attribute names which are not string (e.g. when set by TimestampBehavior::updatedAtAttribute) 19 if (is_string($attribute)) { 20 $this->owner->$attribute = $value; 21 } 22 } 23 } 24 }
When update or insert save data, save() in BaseActiveRecord.php:
1 /** 2 * Saves the current record. 3 * 4 * This method will call [[insert()]] when [[isNewRecord]] is true, or [[update()]] 5 * when [[isNewRecord]] is false. 6 * 7 * For example, to save a customer record: 8 * 9 * ```php 10 * $customer = new Customer; // or $customer = Customer::findOne($id); 11 * $customer->name = $name; 12 * $customer->email = $email; 13 * $customer->save(); 14 * ``` 15 * 16 * @param boolean $runValidation whether to perform validation (calling [[validate()]]) 17 * before saving the record. Defaults to `true`. If the validation fails, the record 18 * will not be saved to the database and this method will return `false`. 19 * @param array $attributeNames list of attribute names that need to be saved. Defaults to null, 20 * meaning all attributes that are loaded from DB will be saved. 21 * @return boolean whether the saving succeeded (i.e. no validation errors occurred). 22 */ 23 public function save($runValidation = true, $attributeNames = null) 24 { 25 if ($this->getIsNewRecord()) { 26 return $this->insert($runValidation, $attributeNames); 27 } else { 28 return $this->update($runValidation, $attributeNames) !== false; 29 } 30 }
Call insert() and update() in ActiveRecord.php:
1 public function insert($runValidation = true, $attributes = null) 2 { 3 if ($runValidation && !$this->validate($attributes)) { 4 Yii::info('Model not inserted due to validation error.', __METHOD__); 5 return false; 6 } 7 8 if (!$this->isTransactional(self::OP_INSERT)) { 9 return $this->insertInternal($attributes); 10 } 11 12 $transaction = static::getDb()->beginTransaction(); 13 try { 14 $result = $this->insertInternal($attributes); 15 if ($result === false) { 16 $transaction->rollBack(); 17 } else { 18 $transaction->commit(); 19 } 20 return $result; 21 } catch (Exception $e) { 22 $transaction->rollBack(); 23 throw $e; 24 } 25 } 26 public function update($runValidation = true, $attributeNames = null) 27 { 28 if ($runValidation && !$this->validate($attributeNames)) { 29 Yii::info('Model not updated due to validation error.', __METHOD__); 30 return false; 31 } 32 33 if (!$this->isTransactional(self::OP_UPDATE)) { 34 return $this->updateInternal($attributeNames); 35 } 36 37 $transaction = static::getDb()->beginTransaction(); 38 try { 39 $result = $this->updateInternal($attributeNames); 40 if ($result === false) { 41 $transaction->rollBack(); 42 } else { 43 $transaction->commit(); 44 } 45 return $result; 46 } catch (Exception $e) { 47 $transaction->rollBack(); 48 throw $e; 49 } 50 }
transferActiveRecord.phpInsideinsertInternal() and updateInternal():
1 /** 2 * Inserts an ActiveRecord into DB without considering transaction. 3 * @param array $attributes list of attributes that need to be saved. Defaults to null, 4 * meaning all attributes that are loaded from DB will be saved. 5 * @return boolean whether the record is inserted successfully. 6 */ 7 protected function insertInternal($attributes = null) 8 { 9 if (!$this->beforeSave(true)) { 10 return false; 11 } 12 $values = $this->getDirtyAttributes($attributes); 13 if (($primaryKeys = static::getDb()->schema->insert(static::tableName(), $values)) === false) { 14 return false; 15 } 16 foreach ($primaryKeys as $name => $value) { 17 $id = static::getTableSchema()->columns[$name]->phpTypecast($value); 18 $this->setAttribute($name, $id); 19 $values[$name] = $id; 20 } 21 22 $changedAttributes = array_fill_keys(array_keys($values), null); 23 $this->setOldAttributes($values); 24 $this->afterSave(true, $changedAttributes); 25 26 return true; 27 } 28 /** 29 * @see update() 30 * @param array $attributes attributes to update 31 * @return integer number of rows updated 32 * @throws StaleObjectException 33 */ 34 protected function updateInternal($attributes = null) 35 { 36 if (!$this->beforeSave(false)) { 37 return false; 38 } 39 $values = $this->getDirtyAttributes($attributes); 40 if (empty($values)) { 41 $this->afterSave(false, $values); 42 return 0; 43 } 44 $condition = $this->getOldPrimaryKey(true); 45 $lock = $this->optimisticLock(); 46 if ($lock !== null) { 47 $values[$lock] = $this->$lock + 1; 48 $condition[$lock] = $this->$lock; 49 } 50 // We do not check the return value of updateAll() because it's possible 51 // that the UPDATE statement doesn't change anything and thus returns 0. 52 $rows = static::updateAll($values, $condition); 53 54 if ($lock !== null && !$rows) { 55 throw new StaleObjectException('The object being updated is outdated.'); 56 } 57 58 if (isset($values[$lock])) { 59 $this->$lock = $values[$lock]; 60 } 61 62 $changedAttributes = []; 63 foreach ($values as $name => $value) { 64 $changedAttributes[$name] = isset($this->_oldAttributes[$name]) ? $this->_oldAttributes[$name] : null; 65 $this->_oldAttributes[$name] = $value; 66 } 67 $this->afterSave(false, $changedAttributes); 68 69 return $rows; 70 }
Call beforeSave() in BaseActiveRecord.php to trigger$this->trigger($insert ? self::EVENT_BEFORE_INSERT : self::EVENT_BEFORE_UPDATE, $event) Event execution adds the event method bound beforeevaluateAttributes automatically adds attribute values:
1 public function beforeSave($insert) 2 { 3 $event = new ModelEvent; 4 $this->trigger($insert ? self::EVENT_BEFORE_INSERT : self::EVENT_BEFORE_UPDATE, $event); 5 6 return $event->isValid; 7 }
}