Найти или Создать с Красноречивым

Недавно я начал работать с Laravel и Eloquent, и мне было интересно, отсутствие возможности поиска или создания моделей. Вы всегда можете написать, например:

$user = User::find($id);
if (!$user) {
    $user = new User;
}

Однако нет ли лучшего способа найти или создать? В примере это кажется тривиальным, но для более сложных ситуаций было бы очень полезно либо получить существующую запись, либо обновить ее, либо создать новую.

Ответы

Ответ 1

Ниже приведен оригинальный ответ для: laravel-4

Уже существует метод findOrFail, доступный в Laravel, и когда этот метод используется, он выдает ModelNotFoundException при неудаче, но в вашем случае вы можете сделать это, создав метод в своей модели, например, если вы есть модель User, тогда вы просто поместите эту функцию в модель

// Put this in any model and use
// Modelname::findOrCreate($id);
public static function findOrCreate($id)
{
    $obj = static::find($id);
    return $obj ?: new static;
}

С вашего контроллера вы можете использовать

$user =  User::findOrCreate(5);
$user->first_name = 'Jhon';
$user->last_name = 'Doe';
$user->save();

Если пользователь с id od 5 является exixts, он будет обновлен, иначе будет создан новый пользователь, но id будет last_user_id + 1 (автоматически увеличивается).

Это другой способ сделать то же самое:

public function scopeFindOrCreate($query, $id)
{
    $obj = $query->find($id);
    return $obj ?: new static;
}

Вместо создания статического метода вы можете использовать scope в Модели, поэтому метод в Model будет scopeMethodName и вызовет Model::methodName(), как и в статическом методе, например

$user =  User::findOrCreate(5);

Обновление:

firstOrCreate доступен в Laravel 5x, ответ слишком стар, и он был указан для Laravel-4.0 в 2013.

В Laravel 5.3 метод firstOrCreate имеет следующее объявление:

public function firstOrCreate(array $attributes, array $values = [])

Это означает, что вы можете использовать его следующим образом:

User::firstOrCreate(['email' => $email], ['name' => $name]);

Существование пользователя будет проверяться только по электронной почте, но при его создании новая запись сохранит как электронную почту, так и имя.

Документы API

Ответ 2

В качестве альтернативы, в этом случае вы также можете использовать функцию Laravel и искать идентификатор в качестве атрибута, т.е.

$user = User::firstOrCreate(['id' => $id]);

Ответ 3

Модели Laravel 4 имеют встроенный findOrNew метод, который делает то, что вам нужно:

$user = User::findOrNew($id);

Ответ 4

В Laravel 5:
Существует два метода, которые вы можете использовать для создания моделей путем присвоения атрибутов: firstOrCreate и firstOrNew.
Метод firstOrCreate попытается найти запись базы данных, используя данные пары столбцов/значений. Если модель не может быть найдена в базе данных, запись будет вставлена ​​ с указанными атрибутами.
Метод firstOrNew, например firstOrCreate, попытается найти запись в базе данных, соответствующей данным атрибутам. Однако, если модель не найдена, экземпляр новой модели будет возвращен. Обратите внимание, что модель, возвращаемая firstOrNew, еще не сохраняется в базе данных. Чтобы сохранить его, вам нужно будет вручную сохранить его.

// Retrieve the flight by the attributes, or create it if it doesn't exist...
$flight = App\Flight::firstOrCreate(['name' => 'Flight 10']);

// Retrieve the flight by the attributes, or instantiate a new instance...
$flight = App\Flight::firstOrNew(['name' => 'Flight 10']);

Ответ 5

Найти или Создать на основе первичного ключа id

$user = User::findOrNew($id); // if exist then update else insert
$user->name= $data['full_name'];
$user->save();

Первый или Новый, основанный на непервичном ключе одиночный файл

// get the record where field_name=value else insert new record
$user = User::firstOrNew(['field_name'=>'value']); 
$user->name= $data['full_name'];
$user->save();

Сначала или Создать на основе непервичного ключа несколько поданных

// get the record where field_name1=value1 and field_name2=value2, else insert new record
$user = User::firstOrNew(['field_name1'=>'value1','field_name2'=>'value2']);
$user->name= $data['full_name'];
$user->save();

Ответ 6

Вы можете использовать firstOrCreate (он работает с Laravel 4.2)

$bucketUser = BucketUser::firstOrCreate([
    'bucket_id' => '1',
    'user_id'   => '2',
]);

возвращает найденный экземпляр или новый экземпляр.