В моем приложении есть публикуемые объявления с моделью Announcement, вот схема:
Schema::create('announcements', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('message');
$table->text('message_details');
$table->string('author');
$table->string('status');
$table->timestamp('published_at')->nullable();
$table->timestamps();
});
У меня также есть AnnouncementObserver, чтобы наблюдать за изменениями модели.
Я подумал, что для установки published_at я мог бы использовать событие updated следующим образом:
/**
* Handle the announcement "updated" event.
*
* @param \App\Announcement $announcement
* @return void
*/
public function updated(Announcement $announcement)
{
$changes = $announcement->getChanges();
if ($changes['status'] === 'published') {
$announcement->published_at = Carbon::now();
}
Log::notice("An announcement was updated: {$announcement->title} by: " . auth()->user()->full_name);
}
Однако это не обновилось published_at. Я не делал этого при обновлении, потому что не видел способа определить, действительно ли изменилось значение.
Я усложняю здесь?
Из отзывов
/**
* Handle the announcement "creating" event.
*
* @param \App\Article $announcement
* @return void
*/
public function updating(Announcement $announcement)
{
if ($announcement->isDirty(['status'])) {
$new_status = $announcement->getDirty('status');
if ($new_status == 'published') {
dd('weng');
}
}
}
Однако это не совсем работает...
Основываясь на данных ответах, вот что у меня получилось...
/**
* Handle the announcement "creating" event.
*
* @param \App\Announcement $announcement
* @return void
*/
public function updating(Announcement $announcement)
{
// Set published_at when published
if ($announcement->isDirty('status') && $announcement->status === 'published') {
$announcement->published_at = now();
}
// Set published_at to null when unpublished
if ($announcement->isDirty('status') && $announcement->status !== 'published') {
$announcement->published_at = null;
}
}
Таким образом, при изменении статуса публикации published_at становится NULL.
Просто примечание: наличие статуса опубликовано немного избыточно, если у вас уже есть поле publish_at. Просто проверьте, не пусто ли поле publish_at, если вы хотите запрашивать только опубликованные объявления.
@BramVerstraten Если у OP больше двух статусов.
Привет, ребята, раньше у меня было просто опубликованное поле с 3 статусами и я использовал updated_at, но пользователь спросил, что это может быть в порядке, когда они были впервые опубликованы, а не обновлены.






Что вы можете сделать, так это изменить его обратно на updating и проверить, было ли изменено объявление с помощью $announcement->isDirty(). Этот метод вернет значение true, если один или несколько атрибутов объекта изменились с тех пор, как его атрибуты были извлечены из базы данных.
можно ли сделать if ($announcement->isDirty('status') === 'value')?
Вы можете использовать его следующим образом: if ( $announcement->isDirty(['message_details','status']) ) Это проверяет, изменился ли один из двух заданных атрибутов, и если это так, он возвращает true. Строка ('status'), как вы, также возможна и проверяет один измененный атрибут. (Документация)
Учитывая это, можете ли вы проверить, что грязный атрибут является заданным значением?
@JesseOrange, если это должно быть status, вы можете сделать это: if ( $announcement->isDirty( 'status' ) && $announcement->status === 'the_value_you_want' ).
Причина, по которой published_at не обновилась, заключается в том, что вы не вызвали save() модель.
При этом было бы лучше, если бы вы применили это изменение в методе updating() своего AnnouncementObserver. Вы можете сделать это, используя метод isDirty(), а затем проверив значение самого экземпляра:
public function updating(Announcement $announcement)
{
if ($announcement->isDirty('status') && announcement->status === 'published') {
$announcement->published_at = now();
}
}
Поскольку событие updating запускается после save()/updated(), но до фактического сохранения данных, вам не нужно вызывать save() самостоятельно.
Итак, я слишком усложнял, просто было немного неправильно пытаться сделать это в контроллере.
@JesseOrange Нет, это пойдет в твой класс AnnouncementObserver .
О, да, я знаю, я просто объяснял свои доводы в пользу использования Observer. Я также не понимал, что вы можете получить доступ к грязным, как к обычному массиву...
@JesseOrange Да, можешь. Я обновил код, чтобы сделать его проще, поэтому вам на самом деле не нужно проверять массив, вы просто проверяете, не является ли значение грязным, а затем проверяете, что это за значение.
Чтобы гарантировать, что был обновлен статус, вы также добавили бы isDirty('status')?
@JesseOrange Да, это была оплошность с моей стороны, ха-ха.
Честно говоря, я никогда не думал о том, как работает грязный метод, но, глядя на него, теперь все понятно, почему существует массив с именем original.
@JesseOrange Это ответило на ваш вопрос или вам все еще нужна помощь в решении проблемы?
Вы хотите, чтобы дата менялась каждый раз, когда производится обновление, если
status=== «опубликовано» или только в первый раз?