Yii2技术问询:仅新增记录时设当前日期为默认值,编辑不覆盖
Hey there! Since your handle is yii2__, I'm guessing you're working with the Yii2 framework here. Let's solve this problem: you want a date field to automatically set to the current date only when creating a new record, and leave it completely untouched when editing the record later. Here are a few solid approaches to make this happen:
Approach 1: Use Scenarios + Default Rules in the Model
Yii2's scenario system is perfect for distinguishing between create and update actions. Define scenarios for your model, then apply the default value rule only to the create scenario:
// Inside your model class public function scenarios() { $scenarios = parent::scenarios(); // Include the date field in the create scenario $scenarios['create'] = ['your_other_fields', 'created_at']; // Exclude the date field from the update scenario $scenarios['update'] = ['your_other_fields']; return $scenarios; } public function rules() { return [ // Your other validation rules... [['created_at'], 'default', 'value' => function ($model, $attribute) { // Return current date in your desired format return date('Y-m-d H:i:s'); // Alternatively, use a DateTime object if your field expects it: // return new \DateTime(); }, 'on' => 'create'], ]; }
How it works: When you create a new record, the create scenario triggers the default value rule, auto-filling the current date. When editing, the update scenario skips this rule entirely, so the original date stays intact.
Approach 2: Override the beforeSave() Method
This is a more direct approach—tap into the model's beforeSave() hook to check if we're inserting a new record, then set the date only in that case:
public function beforeSave($insert) { if (parent::beforeSave($insert)) { // Only set the date if this is a new record if ($insert) { $this->created_at = date('Y-m-d H:i:s'); // If you want the database to handle the timestamp (avoids server-db time mismatch): // $this->created_at = new \yii\db\Expression('NOW()'); } // For updates, do nothing—keep the existing value return true; } return false; }
Pro tip: Using \yii\db\Expression('NOW()') lets your database generate the timestamp, which is great if your app server and database are in different time zones.
Approach 3: Database-Level Default + Model Guardrails
You can set a default value directly in your database table as a fallback, then make sure your model doesn't overwrite it during edits.
For MySQL, update your table structure like this:
ALTER TABLE your_table MODIFY COLUMN created_at DATETIME DEFAULT CURRENT_TIMESTAMP;
Then, in your model, either exclude the field from update scenarios (like Approach 1) or skip it in beforeSave() (like Approach 2). This way, even if your code misses something, the database will set the date on creation automatically.
Quick Note for Forms
If you're using a form for updates, make sure to either:
- Not render the
created_atfield at all, or - Set it as read-only/disabled (e.g.,
<?= $form->field($model, 'created_at')->textInput(['readonly' => true]) ?>)
This prevents users from accidentally modifying the date, though the backend logic is the real safeguard.
内容的提问来源于stack exchange,提问作者yii2__

