Find or Create with Eloquent - php

I have recently started working with Laravel and Eloquent, and was wondering about the lack of a find or create option for models. You could always write, for example:
$user = User::find($id);
if (!$user) {
$user = new User;
}
However, is there not a better way to find or create? It seems trivial in the example, but for more complex situations it would be really helpfully to either get an existing record and update it or create a new one.

Below is the original accepted answer for: Laravel-4
There is already a method findOrFail available in Laravel and when this method is used it throws ModelNotFoundException on fail but in your case you can do it by creating a method in your model, for example, if you have a User model then you just put this function in the model
// Put this in any model and use
// Modelname::findOrCreate($id);
public static function findOrCreate($id)
{
$obj = static::find($id);
return $obj ?: new static;
}
From your controller, you can use
$user = User::findOrCreate(5);
$user->first_name = 'John';
$user->last_name = 'Doe';
$user->save();
If a user with id of 5 exists, then it'll be updated, otherwise a new user will be created but the id will be last_user_id + 1 (auto incremented).
This is another way to do the same thing:
public function scopeFindOrCreate($query, $id)
{
$obj = $query->find($id);
return $obj ?: new static;
}
Instead of creating a static method, you can use a scope in the Model, so the method in the Model will be scopeMethodName and call Model::methodName(), same as you did in the static method, for example
$user = User::findOrCreate(5);
Update:
The firstOrCreate is available in Laravel 5x, the answer is too old and it was given for Laravel-4.0 in 2013.
In Laravel 5.3, the firstOrCreate method has the following declaration:
public function firstOrCreate(array $attributes, array $values = [])
Which means you can use it like this:
User::firstOrCreate(['email' => $email], ['name' => $name]);
User's existence will be only checked via email, but when created, the new record will save both email and name.
API Docs

Alternatively, in this case you can also use Laravel's function and search for id as an attribute, i.e.
$user = User::firstOrCreate(['id' => $id]);

Find or New based on primary key id
$user = User::findOrNew($id); // if exist then update else insert
$user->name= $data['full_name'];
$user->save();
First or New based on non-primary key single filed
// get the record where field_name=value else insert new record
$user = User::firstOrNew(['field_name'=>'value']);
$user->name= $data['full_name'];
$user->save();
First or New based on non-primary key multiple filed
// 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();

In Laravel 5:
There are two methods you may use to create models by mass assigning attributes: firstOrCreate and firstOrNew.
The firstOrCreate method will attempt to locate a database record using the given column / value pairs. If the model can not be found in the database, a record will be inserted with the given attributes.
The firstOrNew method, like firstOrCreate will attempt to locate a record in the database matching the given attributes. However, if a model is not found, a new model instance will be returned. Note that the model returned by firstOrNew has not yet been persisted to the database. You will need to call save manually to persist it:
// 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']);

Laravel 4 models have a built-in findOrNew method that does what you need:
$user = User::findOrNew($id);

You can use firstOrCreate (It's working with Laravel 4.2)
$bucketUser = BucketUser::firstOrCreate([
'bucket_id' => '1',
'user_id' => '2',
]);
returns found instance or new instance.

Related

i have problem with save data laravel 8 have

i make this query
public function scopeSelection($query){
return $query -> select('abbr', 'name', 'direction', 'active');
}
and this function for save data but nothing save in my database
public function store(LanguageRequest $request)
{
try {
Language::created($request->except(['_token']));
return redirect()->route('admin.languages')->with(['success' => 'success']);
} catch (\Exception $ex) {
return redirect()->route('admin.languages')->with(['error' => 'error']);
}
}
To insert a new record into the database, you should instantiate a new model instance and set attributes on the model. Then, call the save method on the model instance:
$language = new Language();
$language->iso = $request->iso;
$language->save();
In this example, we assign the iso field from the incoming HTTP request to the iso attribute of the App\Models\Language model instance. When we call the save method, a record will be inserted into the database. The model's created_at and updated_at timestamps will automatically be set when the save method is called, so there is no need to set them manually.
Alternatively, you may use the create method (not created) to "save" a new model using a single PHP statement. The inserted model instance will be returned to you by the create method:
use App\Models\Language;
$language= Language::create([
'iso' => 'enGB',
]);
However, before using the create method, you will need to specify either a fillable or guarded property on your model class. These properties are required because all Eloquent models are protected against mass assignment vulnerabilities by default. To learn more about mass assignment, please consult the mass assignment documentation.

Can't update table in Laravel 5.4 using Elequent query

I am using Laravel 5.4. I made a function for two (insert and update).
When id is not found it will hit insert otherwise it will hit the update method.
Everything is working well but the update elequent query is not updating the table. The method is for angularjs http.post method
Controller function:
public function postUserJson(Request $req)
{
//return "check". $req->input('id');
if ($req->input('id')=='') {
$user = new User();
$user->UserName = $req->input('username');
$user->Password = $req->input('password');
$user->save();
return "inserted";
} else {
$check= User::find($req->input('id'));
// $check->ID = $req->input('id');
$check->UserName = $req->input('username');
$check->Password = $req->input('password');
$check->save();
return "updated".$check;
}
}
This (return "updated".$check;) code return in console:
updated{"ID":13,"UserName":"sadek","Password":"456"}
Previous username was sade. After editing i got the edited name with sadek after save() method. But when i refresh it show sade
How can i update a table ?
you are sending data in json formate. your query string is not same. see
"UserName" != username
Password != password
make sure about this.
Eloquent provides a method for handling all of the logic you have above, it is called updateOrCreate()
From the docs:
You may also come across situations where you want to update an existing model or create a new model if none exists. Laravel provides an updateOrCreate method to do this in one step. Like the firstOrCreate method, updateOrCreate persists the model, so there's no need to call save()
$flight = App\Flight::updateOrCreate(
['departure' => 'Oakland', 'destination' => 'San Diego'],
['price' => 99]
);

Creating an Eloquent Object with relation included

I'm pretty much new to opps and laravel both
So, to insert the values into my users and profiles table which hav OneToOne relationship, Here is how my store() method looks like
public function store(Requests\StoreNewUser $request)
{
// crate an objct of user model
$user = new \App\User;
// now request and assign validated input to array of column names in user table
$user->first_name = $request->input('first_name');
$user->last_name = $request->input('last_name');
$user->email = $request->input('email');
$user->password = $request->input('password');
/* want to assign request input to profile table's columns in one go
*/
$user->profile()->user_id = $user->id; // foreign key in profiles table
$user->profile()->mobile_no = $request->input('mobile');
dd($user); // nothing related to profile is returned
}
I'm creating the new record, hence dd() never returns anything related to profile table.
Is this Because the $user object is not including relationship by default?
If yes Can i create the $user object which includes the associated relations in User Model ?
Or do i have to create two separate objects of each table and save() the data But then what is the significance of push() method ?
EDIT 1
P.S. yes, the relationships are already defined in User & Profile model
You may try something like the following. At first save the parent model like this:
$user = new \App\User;
$user->first_name = $request->input('first_name');
// ...
$user->save();
Then create and save the related model using something like this:
$profile = new \App\Profile(['mobile_no' => $request->input('mobile')]);
$user->profile()->save($profile);
Also make sure you have created the profile method in User model:
public function profile()
{
return $this->hasOne('App\Profile');
}
I thought i'd update this answer and make it applicable to Laravel 5 onwards. I'll use #The Alpha answer as a basis.
$profile = new \App\Profile(['mobile_no' => $request->input('mobile')]);
$user->profile()->associate($profile); // You can no longer call 'save' here
$user->profile()->save();
The reason for this is you can no longer call save on the belongsTo relation (or any other), this now returns an instance of Illuminate\Database\Query\Builder.
The clean way to do it now would be having on your User Class file:
public function profile()
{
return $this->hasOne(App\Profile::class);
}
and in your User Controller, the following store method:
public function store(Requests\StoreNewUser $request)
{
$user = App\User::create(
$request->only(
[
'first_name',
'last_name',
'email'
]
)
);
$user->password = Illuminate\Support\Facades\Hash::make($request->password);
//or $user->password = bcrypt($request->password);
$user->profile()->create(
[
'mobile_no' => $request->mobile;
]
);
dd($user);
}
I didn know if u were saving plain text password to you database or using a mutator on password attribute, anyhow the suggested above is a good practice I think
Is this Because the $user object is not including relationship by default? If yes Can i create the $user object which includes the associated relations in User Model ?
Yes you should create the relationship, they're not included by default.
In your User model you'd want to do something like this:
public function profile()
{
return $this->hasOne('App\Profile'); // or whatever your namespace is
}
This would also require you to have a Profile model created.
This would definitely answer your questions regarding inserting related models: http://laravel.com/docs/5.1/eloquent-relationships#inserting-related-models
As The Alpha mentioned, and you also eluded to, I think you need to save your user model first then you can add via relationship.

Model relations not working when using queryBuilder methods in Laravel

How can I use Laravel Relations while using Query Builders ?
$Cars = User::find(1)->car; // works well and returns all cars
$User = User::where('username' , 'John')->get();
$Cars = $User->car; // doesn't work.
Any help.
thanks
Solved
$User = User::where('username' , 'John')->get();
Should Be
$User = User::where('username' , 'John')->first(); // to get an object instead of array
The ::find() method will return an instance of your model, which allows you to access relations and such that are setup on the model.
The ->get() method will return an Illuminate\Database\Eloquent\Collection of results, even if there is only 1 row selected from the database.
Using the collection you can then loop through the results
$collection->each(function($model)
{
// You can now access $model->cars
});
Alternativly you may use the ->first(), ->last() and ::find() methods to return a single instance of your model which allows you to directly access relations.
$model = Model::where('foo', 'bar')->first(); // Returns first row from the database
$model->cars // Is now accessable
Assuming you already have your Cars class all you have to do is to add method to your User class.
//add this method to your User class
public function cars()
{
//since you'll be using many to many
//you might use `user_cars` as pivotal table
return $this->belongsToMany('Cars', 'user_cars', 'cars', 'cars');
}
You may call it using:
User::find(1)->cars()->get();

How to get last insert id in Eloquent ORM laravel

I am performing a database operation with "Eloquent ORM in Laravel". I just want to take the last insert id (not the maximum id) in the database.
I searched to get last insert id in laravel Eloquent ORM, I got following link (Laravel, get last insert id using Eloquent) that is refer to get last insert id from following function "$data->save()".
But I need to get
"Model::create($data)";
My Query:
GeneralSettingModel::create($GeneralData);
User::create($loginuserdata);
How can I retrieve the last inserted id?
Like the docs say: Insert, update, delete
"You may also use the create method to save a new model in a single
line. The inserted model instance will be returned to you from the
method. However, before doing so, you will need to specify either a
fillable or guarded attribute on the model, as all Eloquent models
protect against mass-assignment.
After saving or creating a new model that uses auto-incrementing IDs,
you may retrieve the ID by accessing the object's id attribute:"
$insertedId = $user->id;
So in your sample:
$user = User::create($loginuserdata);
$insertedId = $user->id;
then on table2 it is going to be
$input['table2_id'] = $insertedId;
table2::create($input);
**** For Laravel ****
$user = new User();
$user->name = 'John';
$user->save();
//Getting Last inserted id
$insertedId = $user->id;
You could wrap your data in the insertGetId() method like this
$id = DB::table('table')->insertGetId( $data );
In this case the array $data would look something like this
$data = [ 'field' => 'data' , 'field' => 'data' ];
and if you’re using the DB façade you could just append the lastInsertID() method to your query.
$lastInsertedID = DB::table('table')->insert( $data )->lastInsertId();
$lastId = User::create($loginuserdata)->id;
As others said bfore me you may retrieve id by using
$model->id;
but only if you are using standard naming convention for eloquent. If you want to use other name for primaryKey column, eg:
class Users extends Model{
$primaryKey = 'userid';
}
you may retrieve last inserted id by calling
$model->userid;
It is described in: https://laravel.com/docs/master/eloquent#eloquent-model-conventions where one can find:
Eloquent will also assume that each table has a primary key column
named id. You may define a $primaryKey property to override this
convention.
In addition, Eloquent assumes that the primary key is an incrementing
integer value, which means that by default the primary key will be
cast to an int automatically. If you wish to use a non-incrementing or
a non-numeric primary key you must set the public $incrementing
property on your model to false.
You may do it as,
public function store(Request $request,ModelName $obj)
{
$lastInsertedId = $obj->create($request->all())->id;
}
Hope this will help you.
This is my try:
$model_ins = Model::orderBy('id', 'desc')->take(1)->first();
And use $model_ins->id.
This code works with Laravel 5.3:
$upstatus = User::create($status);
return response()->json($upstatus);
User pages/site I was call data.id
This is an eloquent model:
$user = new Reports();
$user->email= 'david#example.com';
$user->save();
$lastInsertId = $user->id;
A solution using Query Builder:
$lastInsertId = DB::table('reports')->insertGetId(['email' => 'david#example.com']);
$user = (new user)->create($request->all()) ;
\Session::flash('message', 'Thanks , Your record No (' .$user->id . ') has been Successfully added');
This is my solution. I return the inserted object and get its ID or any other property.
This is an easier way that works on all of the ways that you inserted:
DB::getPdo()->lastInsertId()

Categories