Reputation: 1578
When updating my Post
model, I run:
$post->title = request('title');
$post->body = request('body');
$post->save();
This does not update my post. But it should according to the Laravel docs on updating Eloquent models. Why is my model not being updated?
save
succeeded was true
.Post
model:
class Post extends Model
{
protected $fillable = [
'type',
'title',
'body',
'user_id',
];
....
}
Post
controller:
public function store($id)
{
$post = Post::findOrFail($id);
// Request validation
if ($post->type == 1) {
// Post type has title
$this->validate(request(), [
'title' => 'required|min:15',
'body' => 'required|min:19',
]);
$post->title = request('title');
$post->body = request('body');
} else {
$this->validate(request(), [
'body' => 'required|min:19',
]);
$post->body = request('body');
}
$post->save();
return redirect('/');
}
Running dd($post->save())
returns true
.
Running
$post->save();
$fetchedPost = Post::find($post->id);
dd($fetchedPost);
shows me that $fetchedPost
is the same post as before without the updated data.
Upvotes: 40
Views: 74050
Reputation: 488
This happened to me and I figured out that I've applied DB::beginTransaction(); without DB::commit();
Upvotes: 0
Reputation: 1819
For anybody still struggling with this in 2024:
As others have already mentioned if you use a primaryKey other than id
you need to let your eloquent model know by overriding the default value:
protected $primaryKey = 'my_id';
now if you (like me) also changed the data type from integer to string you are probably still not able to save() the model correctly as you also need to let the eloquent model know about your data type change:
protected $keyType = 'string';
For good measure you should probably add
public $incrementing = false;
Good luck
Upvotes: 0
Reputation: 360
Something I've just experienced - if you have a typo in your attribute lets say you have ORDERDEADLINE but you spell it ORDEDEADLINE and assign the attribute and use save();
It doesn't throw an error you can catch but the process will stop and the object won't update either.
Upvotes: 0
Reputation: 113
You can not use $post->save()
to update
a record, YOU MUST USE $post->update()
. But note that laravel uses to firstly check if the model was retrieved by using Eloquent manner. There is a property public $exists
on each model instance. You use to switch it into true
.
public function store($id)
{
$post = Post::findOrFail($id);
$validated = [];
// Request validation
if ($post->type == 1) {
// Post type has title
$validated = $this->validate(request(), [
'title' => 'required|min:15',
'body' => 'required|min:19',
]);
} else {
$validated = $this->validate(request(), [
'body' => 'required|min:19',
]);
}
// ----------------------------------
$post->exists = true;
$success = $post->update($validated);
// ----------------------------------
return redirect('/');
}
Upvotes: 0
Reputation: 324
The issue stems from the database containing multiple results for the query involving Laravel Model.
What I'm trying to convey is that if you use methods like find, findOrFail, or any other query followed by ->first(), you'll obtain one of the records, but it's almost certain that there's at least one more record that matches the query. I understand my response might be somewhat delayed, but it could potentially assist others encountering the same problem.
To resolve this, consider adding additional criteria to your query to ensure that you receive only one result as a response. This step will help guarantee accurate outcomes.
Upvotes: 1
Reputation: 171
I have the same issue although there are try / catch
block in controller@action()
but there were no response, it just stops at $model->save();
there is no log entry either in apache error.log
or laravel.log
. I have just wrapped the save()
with try / cactch
as follows, that helped me to figure out the issue
try{
$model->save();
}
catch (\PDOException $e) {
echo $e->getMessage();
}
Upvotes: 3
Reputation: 320
If you using transactions.
Do not forget call DB::commit();
It must look like this:
try{
DB::beginTransaction();
// Model changes
$model->save();
DB::commit();
}catch (\PDOException $e) {
DB::rollBack();
}
Upvotes: 2
Reputation: 787
Check your table if primary key is not id ("column name should be in small letters only") if you have set column name with different key then put code in your Model like this
protected $primaryKey = 'Id';
So this might be one of the possible solution in your case also if your column name contains capital letters. Yes this worked for me fine, You should have column names in small letter, If you don't have then mention it in the model file, mainly for primaryKey by which your model will try to access database.
Upvotes: 3
Reputation: 21
For use save () method to update or delete if the database has a primary key other than "id". need to declare the attribute primaryKey = "" in the model, it will work
Upvotes: 2
Reputation: 93
You have to make sure that the instance that you are calling save()
on has the attribute id
Upvotes: 6
Reputation: 51
Running dd()
inside a DB::transaction
will cause a rollback, and the data in database will not change.
The reason being, that transaction will only save the changes to the database at the very end. Ergo, the act of running "dump and die" will naturally cause the script to cease and no therefore no database changes.
Upvotes: 4
Reputation: 2383
In my experience, if you select an Eloquent model from the db and the primary_key
column is not part of the fetched columns, your $model->save()
will return true but nothing is persisted to the database.
So, instead of doing \App\Users::where(...)->first(['email'])
, rather do \App\Users::where(...)->first(['id','email'])
, where id
is the primary_key
defined on the target table.
If the (sometimes micro-optimization) achieved by retrieving only a few columns is not really of importance to you, you can just fetch all columns by doing \App\Users::where(...)->first()
, in which case you do not need to bother about the name of the primary_key
column since all the columns will be fetched.
Upvotes: 0
Reputation: 1279
I had the same and turned out to be because I was filtering the output columns without the primary key.
$rows = MyModel::where('...')->select('col2', 'col3')->get();
foreach($rows as $row){
$rows->viewed = 1;
$rows->save();
}
Fixed with
$rows = MyModel::where('...')->select('primary_key', 'col2', 'col3')->get();
Makes perfect sense on review, without the primary key available the update command will be on Null.
Upvotes: 19
Reputation: 3950
I have been experiencing the same issue and found a workaround. I found that I was unable to save()
my model within a function called {{ generateUrl() }}
on my home.blade.php
template. What worked was moving the save()
call to the controller that return
s the home.blade.php
template. (IE, save()
ing before the view is return
ed, then only performing read operations within {{ generateUrl() }}
.)
I was (and am) generating a state
to put in a URL on page load:
<!--views/home.blade.php-->
<a href="{{ EveAuth::generateUrl() }}">Add Character</a>
Below is what did not work.
// Providers/EveAuth.php
function generateUrl()
{
$authedUser = auth()->user();
if (!$authedUser) {
return "#";
}
$user = User::find($authedUser->id);
$user->state = str_random(16);
$user->save();
$baseUrl = 'https://login.eveonline.com/oauth/authorize?state=';
return $baseUrl . $user->state;
}
This was able to find()
the User
from the database, but it was unable to save()
it back. No errors were produced. The function appeared to work properly... until I tried to read the User
's state
later, and found that it did not match the state
in the URL.
Here is what did work.
Instead of trying to save()
my User
as the page was being assembled, I generated the state
, save()
d it, then rendered the page:
// routes/web.php
Route::get('/', 'HomeController@index');
Landing at the root directory sends you to the index()
function of HomeController.php
:
// Controllers/HomeController.php
public function index()
{
$authedUser = auth()->user();
if ($authedUser) {
$user = User::find($authedUser->id);
$user->state = str_random(16);
$user->save();
}
return view('home');
}
Then, when generating the URL, I did not have to save()
the User
, only read from it:
// Providers/EveAuth.php
function generateUrl()
{
$authedUser = auth()->user();
$user = User::find($authedUser->id);
$baseUrl = 'https://login.eveonline.com/oauth/authorize?state=';
return $baseUrl . $user->state;
}
This worked! The only difference (as far as I see) is that I'm save()
ing the model before page assembly begins, as opposed to during page assembly.
Upvotes: -1
Reputation: 269
Check your database table if the 'id' column is in uppercase 'ID'. Changing it to lower case allowed my save() method to work.
Upvotes: 26
Reputation: 603
I had the same problem and changing the way I fetch the model solved it!
Was not saving even though everything was supposedly working just as you have mentioned:
$user = User::find($id)->first();
This is working:
$user = User::find($id);
Upvotes: 7
Reputation: 323
Try this
public function store($id,Request $request)
{
$post = Post::findOrFail($id);
// Request validation
if ($post->type == 1) {
// Post type has title
$request->validate([
'title' => 'required|min:15',
'body' => 'required|min:19',
]);
$post->update([
'title' => request('title');
'body' => request('body');
]);
} else {
$request->validate([
'body' => 'required|min:19',
]);
$post->update([
'body' => request('body');
]);
}
return redirect('/');
}
Upvotes: 0
Reputation: 771
Since Laravel 5.5 laravel have change some validation mechanism I guess you need to try this way.
public function store(Request $request, $id)
{
$post = Post::findOrFail($id);
$validatedData = [];
// Request validation
if ($post->type == 1) {
// Post type has title
$validatedData = $request->validate([
'title' => 'required|min:15',
'body' => 'required|min:19',
]);
} else {
$validatedData = $request->validate([
'body' => 'required|min:19',
]);
}
$post->update($validatedData);
return redirect('/');
}
Upvotes: 4