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]
);
Related
I have a regular User model. The system works fine when I use it. But now I am trying to create unit tests in the PHPUnit that integrated with Laravel.
I have a factory that creates a user:
$factory->define(App\User::class, function (Faker\Generator $faker) {
return [
'id' => $faker->randomNumber(9),
'email' => $faker->safeEmail,
'first_name' => $faker->firstNameMale,
'last_name' => $faker->lastName,
'password' => bcrypt(str_random(10)),
'remember_token' => str_random(10),
];
});
I changed the User to have integer ID as the primary key but it not defined as auto-increment.
So the factory create random number for the ID.
Also I have created the simple test:
public function test_id_is_visible() {
$user = factory(App\User::class)->create();
$this->actingAs($user);
$this->visit('/userprofile');
$this->see($user->id);
}
That test always fails, but it seems to be OK when I navigate to the page manually.
I have noticed that in the test the $user->id is always 0. Even it can't be 0 in the factory. I checked and Laravel insert the user correctly to the database and it have correct ID, but in the code I always get 0.
What can I do to get the correct value of the ID?
EDIT
Now I see that if I changes $user = factory(App\User::class)->create(); to $user = factory(App\User::class)->make(); the user instance holds a correct ID. But why create clears the ID?
Update for Laravel 5.8+ Make sure to set
public $incrementing = false;
on your model.
The problem happened because the ID is not defined as auto-increment.
More information you can found in:
https://stackoverflow.com/a/31350800/1725836
Even the question is for Laravel 4 it is still relevant for Laravel 5.2.
You can write your tests like this:
$users = factory(User::class, 5)->make();
$users->each(function ($item, $key) {
$item->id = ++$key;
});
Now each user will have an id, without the need to persist the models to database (using create() instead of make()).
public function test_id_is_visible() {
$user = factory(App\User::class)->make();
$user->id = 7;
$this->actingAs($user);
$this->visit('/userprofile');
$this->see($user->id);
}
User.php - pretty vanilla hasMany relationship:
public function transactions()
{
return $this->hasMany('App\Transaction');
}
UserTest.php:
public function testTransactionsAttribute()
{
$user = Auth::user();
// Verify logged in user is expected user.
$this->assertTrue($user->username == 'something');
// Pay something.
$transaction = $user->payMembershipFee();
// Verify transaction is in database
$this->seeInDatabase('transactions', ['amount' => 50, 'user_id' => $user->id]);
// Verify transaction belongsTo relationship
$this->assertTrue($transaction->user->username == 'something');
// Verify user hasMany relationship - fails
$this->assertTrue($user->transactions->count() > 0, 'The user should have at least one transaction associated.');
}
Here's where it gets interesting (I did not modify the database tables - just left PHPUnit and switched to Tinker):
$ php artisan tinker
Grab user (verified is same user created from test):
$user = App\User::first()
Copy/Paste assertion:
$user->transactions->count()
=> 1
Also, when I manually go through the steps locally - it works. So, it appears Laravel 5.2 is acting as expected. However, PHPUnit is not.
I'm wondering if it's possible I'm missing something in the way Laravel 5.2 and PHPUnit work with one another?
From outside the model (in the test itself, for example):
$user = $user->fresh();
From inside the model one cannot do something like:
$this = $this->fresh();
So, inside the method that creates the Transaction for the User:
public function createTransaction()
{
$transaction = new Transaction;
...
$transaction->save();
// Refresh the relationship specifically
$this->load('transactions');
// There is also fresh([])
// which is supposed to be able to accept multiple relationships
return $transaction;
}
https://laracasts.com/discuss/channels/testing/refresh-a-model
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.
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()
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.