I'm trying to update a row in a particular table, laravel does not shows any error but value is not updating in database.
this is my update method code:
function update(Request $request){
$product=product::find($request['Id']);
$product->productName=$request['name'];
$product->description=$request['desc'];
$product->discount=$request['discount'];
$product->inventory=$request['inventory'];
$product->save();
return response()->json(['message'=>$product->productName],200);
}
I'm successfully getting all the data and I've checked that my changing the value of response json
the variable $product->productName also shows updated value as it is present after save() method but nothing changes in database.
The problem is with this piece of code as I have checked my model i.e product and its working fine as $product has value.
By default Laravel is protecting all models from mass-assignment vulnerability. So you have to specify either a $fillable (which fields can be modified) or $guarded (which fields can not be modified) property.
In your case add this to the model:
protected $fillable = [
'productName',
'description',
'discount',
'inventory',
];
Are you not trying to update this record?
Why are you using save() method, why not use update() since you are trying to set the given product with new set of values?:
$product->update();
So you can finally have (suggesting a check on if a product exists and if the update was successful - you can disregard it if you like):
function update(Request $request)
{
if(!$product=product::find($request['Id']))
{
return response()->json('Product does not exist', 404);
}
$product->productName=$request['name'];
$product->description=$request['desc'];
$product->discount=$request['discount'];
$product->inventory=$request['inventory'];
if($product->update())
{
return response()->json(['message'=>$product->productName],200);
}
return response()->json('Something went wrong', 500);
}
Hope it helps :)
Related
Everything works great in CRUD, except for update.
My Controller:
public function update(Request $request, $id)
{
$post = Post::findOrFail($id);
$post->update($request->all());
return redirect('/posts');
}
To answer this you need to know if that id is coming through properly.
Do a dump($id); This will show you if it's null or something unexpected.
I'd then wrap the $post in logic to rule out nulls or bad data.
Technically if you are doing a post from the front your id will usually be
$request->id this being sent from a hidden input on the front.
I'd also use a first() because everything coming to this function should already be created and not be null since you're populating this from the database.
$post = Post::where('id', $request->id)->first();
Next do a dump on $post dump($post); this will show you the post info.
If you don't have any post info you have trouble and will require more troubleshooting.
Then you can just do your save process, I personally like to to do a 1 to 1 save to make sure all values from the request are being properly handled. So it would be..
$post->column_name = $request->input_name;
$post->save();
return back()->with ('status', 'Record Updated!');
Then on the front you can display that status from session to show it was updated.
One caveat using mass update is that you should make sure that the fields you are updating are fillable in the model.
You need check your model at the first it should be something like this:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Crud extends Model
{
protected $fillable = [
'first_name', 'lastame', 'id',
];
}
then you have to use
dd('$post')
to see what you have then you can create your update like this:
public function update(Request $request, $id)
{
$post = Post::findOrFail($id);
$post->update($request->all());
return redirect('/posts')->with('success', 'Data is successfully updated');;
}
I'm new to laravel, and I've picked up the basic workflow of creating, updating and deleting database entries using migrations, models and controllers. But now I'm trying to do the same with a subscriptions table that has a subscriberId and a followeeId in it. Both of these fields reference different ids of the same table (users). This kind of task seem to require some finetuning. And I'm stuck.
Here's my code with some comments.
Subscriptions Table
Schema::create('subscriptions', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('subscriberId');
$table->unsignedBigInteger('followeeId');
$table->foreign('subscriberId')->references('id')->on('users');
$table->foreign('followeeId')->references('id')->on('users');
});
Previously, I've used another approach to foreign ids, namely the one with the $table->foreignId('user_id')->constrained() pattern, but in this particular case I need to make sure that the two foreign ids reference different users, so I went for a more verbose option.
User Model
public function subscriptions()
{
return $this->hasMany(Subscription::class, 'subscriberId');
}
Here I've added the second parameter. This seems to work.
Subscription Model
class Subscription extends Model
{
use HasFactory;
protected $fillable = [
'subscriberId',
'followeeId'
];
public function subscriberId()
{
return $this->belongsTo(User::class, 'id', 'subscriberId');
}
public function followeeId()
{
return $this->belongsTo(User::class, 'id', 'followeeId');
}
}
Here I pass additional parameters, too, although in this case I'm not so sure if these are the correct ones. But this is my best guess. If I'm not mistaken, the second parameter of the belongsTo relation is inferred from the model that is being passed in, not the model of the parent class as is the case with the hasMany relation. So in this case that would be 'id' of the users table, which would be the default here anyway, but I need the third parameter, so I explicitly state the second parameter as well. Again, I'm not sure about this combination, but that's what I was able to make of the docs. I've also used other combinations of additional parameters, and even tried getting rid of these two public functions altogether, but that won't work either.
Now, here's the controller. If I do this:
$user->subscriptions()->get();
I do get the subscriptions I want. But if I do this instead:
$user->subscriptions()->create([
'subscriberId' => 1,
'followeeId' => 2
]);
I get the 500 error. I've also tried another approach:
$newSub = new Subscription;
$newSub->subscriberId = 1;
$newSub->followeeId = 2;
$newSub->save();
return $newSub;
But still no success. I still get the 500 error when I try to save()
Please help me out.
Solution
I should have used
public $timestamps = false
in the Subscription model, and I also misunderstood the docs. The correct combo is
User Model
public function subscriptions()
{
return $this->hasMany(Subscription::class, 'subscriberId');
}
and
Subscription Model
public function subscriberId()
{
return $this->belongsTo(User::class, 'subscriberId');
}
public function followeeId()
{
return $this->belongsTo(User::class, 'followeeId');
}
I am trying to make a testcase within laravel.
I have a fake User model (which dosent exists in DB), and creating it using faker->make,
and a real Role model which exists in DB,
these two have a many-to-many relationship
in my testcase, i am going to associate them like here :
public function testAccess()
{
$user = factory(\App\User::class)->make();
$supervisionControllerRole = \App\Role::where('name', 'supervision_controller')->first();
$user->roles->add($supervisionControllerRole);
}
since i dont want to save the relation in database, i am using add() instead of attach():
$user->roles()->attach($supervisionControllerRole->id);
//resulting database modification.
Problem
my problem is, when i am trying to get the relation from the model its ok.
var_dump($user->roles->first());
but when i am trying to get the relation Within The Model, it dosent works.
like here in my User Model:
public function hasRole($roleName)
{
$role_id = Cache::tags(['role_id'])->remember($roleName, 24*3600, function () use ($roleName) {
return \App\Role::where('name', $roleName)->first()->id;
});
return $this->roles()->where('role_id', $role_id)->exists();
}
It will returns false and trying $this->roles->count() results 0
from inside of the model.
My definitions
in User model:
public function roles()
{
return $this->belongsToMany("App\Role", "role_user")->whereNull("deleted_at")->using("App\RoleUser");
}
User Factory:
$factory->define(User::class, function (Faker $faker) {
return [
'id' => $faker->randomNumber(),
'name' => $faker->name,
'email' => $faker->unique()->safeEmail,
'email_verified_at' => now(),
'password' => Str::random(80), // password
'remember_token' => Str::random(10),
];
});
Whenever you call a relationship with parentheses, such as
return $this->roles()->where('role_id', $role_id)->exists();
^^
you're accessing a Builder query instance which will return info from the database. But your data is not in the database, so of course it won't find anything when it looks there.
When you directly add() the relationship (vs attach()), you're inserting into a Collection instance, which as you know doesn't affect the database. This information is saved on the model only and stored in memory. Hence when you do
var_dump($user->roles->first());
it finds the information since it's already in memory. (You should also be able to call $user->roles->count() here and get a non-zero value.)
And since it's in a relationship of the model vs a direct attribute, I don't even think it would update the database if you were to save() the model.
You can use the contains method to perform the first step if you are not storing in the database:
return $this->roles->contains($role_id);
Laravel 5.7
Hello I have been looking through stack overflow and have tried many possible answers and have come to no conclusions.
I am updating a simple integer value in a patron table through simple checks and it is not updating the database. I have tried using save() and update() methods on the model.
There are no errors or exceptions that show up and the save() and update() methods return true.
code:
Controller Class Using the model and updating data:
$patron_coupon = PatronCoupons::where('owner',$patron_id)->where('coupon_id',$active_coupon['coupon_id'])->first();
if($patron_coupon->current_uses > $active_coupon['max_uses'])
$patron_coupon->current_uses = $active_coupon['max_uses'];
// if i echo $patron_coupon->current_uses here, it will show that this value has changed ( good )
$patron_coupon->current_uses = $active_coupon['max_uses'] - $patron_coupon->times_used;
if($patron_coupon->current_uses < 0)
$patron_coupon->current_uses = 0;
// this doesnt work
$patron_coupon->save();
// this doesnt work either
$patron_coupon->update($patron_coupon->toArray());
// if i echo current_uses here, the value goes back to what it was before being set.
Model Class:
class PatronCoupons extends Model
{
protected $table = 'patron_coupons';
protected $primaryKey = 'owner';
public $timestamps = false;
protected $fillable = ['times_used','current_uses','settings_version'];
}
Migration File:
Schema::create('patron_coupons', function (Blueprint $table) {
$table->string('owner'); // patron id that 'owns' this coupon
$table->unsignedInteger('coupon_id'); // id of this coupon
$table->unsignedInteger('current_uses')->default(0); // the amount of uses this patron has for this coupon
$table->unsignedInteger('settings_version')->nullable();// last settings version fetch
$table->unsignedInteger('times_used')->default(0); // amount of times this coupon has been used
});
Please help, I've been banging my head on my desk for hours !!!!!
You can try any of the following:
Try using static update function instead
PatronCoupons::update([
// updates here
]);
Remove your vendor folder and composer.lock file. Then run composer install to refresh your vendor file
get record
$patronCoupons = PatronCoupons::find($id);
$patronCoupons->update([
'times_used' => 'value',
'current_uses' => 'value',
'settings_version' => 'value'
]);
if your post data with the same input name then directly use
$post = $request->all();
$patronCoupons = PatronCoupons::find($id);
$patronCoupons->update($post);
Make sure that you put this code in the form because of which the error occurs
'enctype' => 'multipart/form-data'
It's pretty straightforward as it's the most basic thing but I don't know what I'm missing:
Having a model called Site
I'm using Eloquent ORM, so when I call (in a controller)
$oSite = Site::find(1)
and then
var_dump($oSite);
It returns a value of NULL.
But when I check the database, the table 'sites' actually contains the following item:
id: 1
user_id: 1
name: test
In my Site model I have the following code:
use Illuminate\Database\Eloquent\ModelNotFoundException;
Class Site extends Eloquent {
protected $table = 'sites';
protected $fillable = ['user_id', 'name'];
}
Instead, if I gather the item with the following:
$oSite = DB::table('sites')
->where('id', 1)
->first();
It works and I get the correct register.
What I'm doing wrong? Which part of the documentation I didn't get?
EDIT:
Model code can be checked above.
Controller:
use Illuminate\Support\Facades\Redirect;
class SiteManagementController extends BaseController {
...
public function deleteSite()
{
if (Request::ajax())
{
$iSiteToDelete = Input::get('siteId');
$oSite = Site::find($iSiteToDelete);
return var_dump($oSite);
}
else
{
return false;
}
}
}
EDIT 2: (SOLVED)
Real reason why wasn't working:
I had originally in my model code the following:
use Illuminate\Database\Eloquent\SoftDeletingTrait;
use Illuminate\Database\Eloquent\ModelNotFoundException;
Class Site extends Eloquent {
protected $table = 'sites';
use SoftDeletingTrait;
protected $dates = ['deleted_at'];
protected $fillable = ['user_id', 'name'];
}
Problem was I added a 'deleted_at' column after I started the project and when I applied migrations, I didn't have softdeleting enabled.
Obviously, I did a second error, forgetting to enable 'deleted_at' to be nullable, hence all inserts went had a wrong timestamp (0000-00-00 ...).
Fix:
Made nullable 'deleted_at' column.
Set all wrong 'deleted_at' timestamps to NULL.
Check you are getting Input::get('siteId') correctly. if you are getting it then try to convert it into integer i.e
$iSiteToDelete = intval(Input::get('siteId'));
You're not returning your model.
var_dump prints output and returns nothing.
do this instead:
dd($oSite); // stands for var_dump and die - a helper method
and even better, simply return the model:
return $oSite; // will be cast to JSON string
In my case I was using a custom query with the DB facade. I neglected to skip records that have a deleted_at in my DB query. When showing all the records, it worked with IDs that had already been deleted, so methods like find that if they were considering the deleted_at, did not find the record.
Layer eight.
For the future if you encounter a similar problem you can check what SQL queries laravel is sending to the database.
Todo so just enable query logging by using DB facade:
\DB::enableQueryLog();
Before sending request to database.
Then after using find() or get() you can get all requests by:
\DB::getQueryLog();
You can getQueryLog into dd() function and see what database queries were made.