2015-04-27 4 views
30

все.как использовать created_at in laravel

Я новичок в laravel.

это мои вопросы:

это может пользовательские метки времени имя

const CREATED_AT = 'created'; 
const UPDATED_AT = 'updated'; 

это может отключить временные метки

public $timestamps = false; 

Я хочу использовать только created_at, как это сделать?

ответ

45

Красноречивый не обеспечивает такую ​​функциональность из коробки, но вы можете создать его самостоятельно, используя функцию обратного вызова creating события:

class User extends Eloquent { 

    public $timestamps = false; 

    public static function boot() 
    { 
     parent::boot(); 

     static::creating(function ($model) { 
      $model->created_at = $model->freshTimestamp(); 
     }); 
    } 

} 
+0

Я думаю, что это один из лучших способов взломать временные метки модели Eloquent. Это работает для меня на Laravel 5.1. – TodStoychev

+0

Pretty work! И сначала должен вызываться 'parent :: boot();'. –

+0

Это отличный ответ для одной модели. Для развязанного и многоразового решения я создал Observer на основе этого подхода. Благодаря! С наблюдателем http://stackoverflow.com/a/42822380/2188595 –

1

Моего решения для этого использует новый метод __construct.

См:

class MyModel extends Eloquent { 

    public $timestamps = false; 

    public function __construct(array $attributes = []) 
    { 
      parent::__construct($attributes); 

      $this->attributes['created_at'] = $this->freshTimestamp(); 
    } 
} 
13

Мое решение:

class CreatePostsTable extends Migration { 

    public function up() { 

     Schema::create('posts', function(Blueprint $table){ 

     $table->timestamp('created_at')->default(DB::raw('CURRENT_TIMESTAMP')); 
    }); 
} 

Это работает для меня

+0

есть ли какие-либо недостатки? –

2

Чтобы отключить только updated_at, вы можете переопределить метод Model :: setUpdatedAt(), как следующее:

public function setUpdatedAt($value) { 
    // Do nothing. 
} 

Конечно, если вы хотите сделать это для столбца created_at, это так же просто. И это работа для Laravel 5.1

+0

Я обнаружил, что он не работает для 5.1.7, потому что он обновляет временную метку также в обновлении Builder, вызывая 'return Arr :: add ($ values, $ column, $ this-> model-> freshTimestampString());' – JustAMartin

2

Подход с setUpdatedAt не работал с Laravel 5.1.7, потому что у него есть еще одно место, где обрабатывается updated_at.

Модель метод класса performUpdate вызывает метод класса Builder:

public function update(array $values) 
{ 
    return $this->query->update($this->addUpdatedAtColumn($values)); 
} 

, что приводит нас к

return Arr::add($values, $column, $this->model->freshTimestampString()); 

Я не уверен, почему Laravel обрабатывающего updated_at дважды - в performUpdate с $this->updateTimestamps(), а затем позже в Builder с $this->addUpdatedAtColumn($values).

С некоторой отладкой я обнаружил, что вы также должны обновить свою модель с помощью переопределения getUpdatedAtColumn. Сначала я боялся, что он попытается обновить несуществующее поле «null», но оказалось, что Arr::add достаточно умен, чтобы игнорировать нулевые ключи.

Таким образом, в вашем классе модели добавить эти:

Это должно быть достаточно, чтобы вывести из строя оба обновления.

+0

getDates() также должен быть переопределен, поэтому он не включает 'null': ' public function getDates() { $ defaults = [статический :: CREATED_AT]; return $ this-> timestamps? array_merge ($ this-> date, $ defaults): $ this-> date; } ' – hackel

+0

Это также приведет к обновлению отношений из-за всех вызовов getUpdatedAtColumn из классов отношений. – hackel

+0

Не могли бы вы привести пример этого @hackel? – kiradotee

30

Использование на вершине:

const UPDATED_AT = null; 

И поле 'created_at', вы можете использовать:

const CREATED_AT = null; 

UPDATE ДЛЯ Laravel 5.5.0 - 5.5.5

Это было нарушено in Laravel 5.5.0 (и исправлено снова in 5.5.5).

Если вы используете 5.5.x, убедитесь, что вы находитесь в самой новой версии.

Если по какой-то причине вы не можете быть на новейшей версии, вот обходной путь.

Установить общественность $ метки времени в ложь:

public $timestamps = false; 

И когда необходимо:

public function setCreatedAtAttribute($value) { 
    $this->attributes['created_at'] = \Carbon\Carbon::now(); 
} 

ИЛИ

public function setUpdatedAtAttribute($value) { 
    $this->attributes['updated_at'] = \Carbon\Carbon::now(); 
} 

Когда два поля "created_at" и "updated_at" являются вам, конечно, не нужно ничего делать;)

+2

Очень элегантный! Лучший подход! – adrianthedev

+1

Может кто-нибудь объяснить это? Что он делает точно? – Anthony

+1

Я согласен с Энтони - для этого нужно больше объяснений. – shaneparsons

12

У меня есть лучший ответ от here за Laravel 5.2 or above.

U может использовать это в модельно

class User extends Model 
{ 
    public $timestamps = false; // disable all behaviour 
    public $timestamps = true; // enable all behaviour 
    public $timestamps = [ "created_at" ]; // enable only to created_at 
    public $timestamps = [ "updated_at" ]; // enable only to updated_at 
    public $timestamps = [ "created_at", "updated_at" ]; // same that true 
} 

Так, ваш вопрос, ответ -

public $timestamps = [ "created_at" ]; // enable only to created_at 
+1

Этот не работает на Laravel 5.1 – TodStoychev

+2

Это для Laravel 5.2 или + –

+2

Не используйте этот ответ, не изучая сам код поставщика. Это не работает, потому что оно все еще является предложением и еще не реализовано (сейчас 5.3). –

-1

Я использовал очень простой хак;)

класс MyClass расширяет модель {

const CREATED_AT = 'creation_date'; 
const UPDATED_AT = 'creation_date'; 

}

Я просто указал как на той же колонке :)

+3

Это приведет к тому, что столбец create_at будет перезаписан каждый раз, когда модель будет сохранена. Не делай это! (Это будет работать, если вы хотите только обновить столбец update_at.) – hackel

2

В версии 5.3 я просто сделал public $timestamps = false; и затем добавляли защищенный $ Fillable = [ 'created_at']. Примечание. Вы можете добавить все, что хотите, просто убедитесь, что оно соответствует таковому в вашей таблице. `

1

Решение, которое является простым, развязанным и многоразовым, заключается в использовании модели Observer. Идея состоит в том, чтобы зафиксировать событие creating и заполнить атрибут created_at. Этот метод может использоваться любым количеством моделей без необходимости повторять код или использовать неофициальные трюки. Самое главное, он очень похож на внутреннюю механику класса Model, что позволяет избежать неожиданных ошибок.

1) Создание SetCreatedAt наблюдателя в App\Observers:

namespace App\Observers; 

use Illuminate\Database\Eloquent\Model; 

class SetCreatedAt 
{ 
    /** 
    * Sets created_at when creating the model. 
    * 
    * @param Model $model 
    * @return void 
    */ 
    public function creating(Model $model) 
    { 
     $model->setCreatedAt($model->freshTimestamp()); 
    } 
} 

2) На App\Providers\AppServiceProvider внутри метода boot добавить следующую строку для каждой из моделей, которые вы хотите created_at будут созданы для:

/** 
* Bootstrap any application services. 
* 
* @return void 
*/ 
public function boot() 
{ 
    // Replace OrderLog with your model 
    OrderLog::observe(SetCreatedAt::class); 
} 

3) На ваших моделях единственное, что вам нужно сделать, - отключить отметки времени:

// Disable timestamps on the model 
public $timestamps = false; 

Протестировано с Laravel 5.3, но оно должно работать и с предыдущими версиями.

Удачи вам!

+0

Что такое OrderLog? это ваше название модели? – ClearBoth

+0

Если мне нужно несколько моделей для этого, я должен повторить наблюдение в ботинке с каждым из них? – ClearBoth

+1

@ClearBoth Да, OrderLog - всего лишь пример; замените его на вашу модель. Чтобы использовать в нескольких моделях, просто дублируйте строку 'YourModel :: наблюдать (SetCreatedAt :: class)' для каждой из ваших моделей. Я написал более подробный учебник здесь https://arianacosta.com/php/laravel/setting-created_at-timestamp-laravel/ –

0

В 5.4 проблема заключается в том, что он также не заполняет поле update_at даже после обновления (обновление Eloquent).

вместо добавить этот метод

public function setUpdatedAtAttribute($value) 
{ 
    // auto disable update_at in inserts 
} 
1

Я решил, добавив значение по умолчанию CURRENT_TIMESTAMP в моей базе данных для столбца created_at. И в моей модели я использую это ниже код

public $timestamps = false; 
protected $dates = ['created_at']; 

Я надеюсь, что этот метод работает во всех версиях laravel.

+0

Обратите внимание, что время вашей базы данных может отличаться на время apache/php. – ChrisDeDavidMindflowAU

0

Вы можете использовать значение по умолчанию для CURRENT_TIMESTAMP created поля в таблице MySQL и установить

public $timestamps = false; 

в вашей модели.

Смежные вопросы