I'm working with Laravel 5.8 and I have added this code to my Controller:
public function denyRequest($id)
{
$findRequest = WithdrawWallet::find($id);
$findRequest->status = 'cancelled';
$findRequest->save();
return redirect()->back();
}
And here is route for this:
Route::get('{id}','Wallet\WalletController#denyRequest')->name('denyRequest');
Now I get this error:
ErrorException (E_WARNING) Creating default object from empty value
Which is referring to this:
So what's going really wrong here? How to fix this issue?
When you search for existing Withdraw Wallet with an id that doesnt exist, it will return null. and since you assign 'cancelled' as an object attribute on the variable, php will convert $findRequest to a default object (StdObject::class) to be able to assign the attribute to it.
One simple solution would be to use findOrFail() instead of find() wich will trigger an exception when the id doesnt exist in your DataBase and return a 404 response on the request.
$findRequest = WithdrawWallet::findOrFail($id);
$findRequest->status = 'cancelled';
$findRequest->save();
return redirect()->back();
another suggestion (if you have soft delete on on the model and the id exists in the database) is to use withTrashed()
$findRequest = WithdrawWallet::withTrashed()->findOrFail($id);
$findRequest->status = 'cancelled';
$findRequest->save();
return redirect()->back();
Replace find with findOrFail:
$findRequest = WithdrawWallet::findOrFail($id);
Related
My controller looks like this:
public function show($id)
{
$model = MyModel::with([
'model2.model3.model4:id,value',
...
]);
if (myCondition) {
unset($model->model2->model3->model4);
$model->model2->model3->model4 = Model4::where('value', 'Some Value')->first();
}
return $audit;
}
In certain condition I'd like to override the result from the query with another value from the Model4 to return the good data to the client.
But I want to know if there is another way with laravel to do that. Actually I have to use unset and then push the new content if I want to change the value of the model4 property. If I don't use unset the object isn't changed, the value new value assigned to model4 is ignored I don't know why I can't just write this line
$model->model2->model3->model4 = Model4::where('value', 'Some Value')->first();
So I want to know why I can't see changes in my json object when I don't use unset and I want to know if there is anotehr way to deal with laravel for my situation ?
You can simply use setRelation method.
if ($myCondition) {
$model->model2->model3->setRelation('model4', Model4::where(...)->first());
}
I'm trying to call save method on an object of a Model Complaints Model to update a specific resource in Database but when I send a POST request on api url it gives this error
BadMethodCallException: Method Illuminate\Database\Eloquent\Collection::save does not exist.
I also tried calling update method but same error.
Code for edit:
$complaint = Complaint::where('complaint_id', $request->input('id'))->get();
$complaint->title = $request->input('Complaint_Subject');
$complaint->description = $request->input('Complaint_Details');
$complaint->address = $request->input('Complaint_Address');
$complaint->update();
return [
'save_status' => "success"
];
the very first line is returning the response and correct response.
AND
also I'm trying to call delete or destroy method to delete the resource but it also gives the same error
BadMethodCallException: Method Illuminate\Database\Eloquent\Collection::delete does not exist.
or
BadMethodCallException: Method Illuminate\Database\Eloquent\Collection::destroy does not exist.
Code for delete:
$complaint = Complaint::where('complaint_id', $request->input('id'))->get();
$complaint->destroy($request->input('id'));
return [
'request_status' => 'success',
'complaint' => $complaint
];
here also the response is being returned correctly.
Note that the complaint_id is not Primary Key in the table so I cannot simply call Complaint::find($request->input('id')) I must have to cross check with this complaint_id column value to find the resource. I have been searching since yesterday but could not find any solution. How can I solve this problem. Thanks!!!
If your $complaint is a collection of output. So save didn't work for this if you change your code like $complaint = Complaint::where('complaint_id', $request->input('id'))->first(); Then save() will work.
just use first() instead of get()
Complaint::where('complaint_id', $request->id)->first()
In your query
$complaint = Complaint::where('complaint_id', $request->input('id'))->get();
it returns Associative Arrays
But if you use
$complaint = Complaint::where('complaint_id', $request->input('id'))->first();
it returns Indexed or Numeric Arrays. Then you have to use $complaint[0]->destroy($request->input('id')); or $complaint[1]->destroy($request->input('id')); and so one
I am trying to set new value to Model's property but it's not working. I am using dd() right after I set the new value but it keeps the old value.
$business->users()
->where('userable_id', $business->id)
->where('userable_type', 'App\Models\Business')
->first()->first_name = "New";
Try this instead:
$business->users()
->where('userable_id', $business->id)
->where('userable_type', 'App\Models\Business')
->first()->update(['first_name' => "New"]);
Direct object property assign like $model->attribute = 'foo'; affects only in-memory state and doesn't make changes in the database.
So you want to go either
$model->update(['attribute' => 'value']);
or
$model->attribute = 'value';
$model->save();
Reference
Update 1:
as I've written in the comments to my answer, first() might return null sometimes if no one model was found. I'd like to advice firstOrFail() instead.
Note, that there is no predefined handler for ModelNotFound exeption (thrown by firstOrFail()), so you'd like to handle such error manually in Handler class, otherwise you'll get default 404 Laravel page.
$business->users()
->where('userable_id', $business->id)
->where('userable_type', 'App\Models\Business')
->first()->update(['first_name' => 'New']);
To access a method/field right after the ->first() method is a very bad practice.
If no model is found, PHP will raise an error because you are trying to access method/property on a null value.
Use instead
$user = $business->users()
->where('userable_id', $business->id)
->where('userable_type', 'App\Models\Business')
->first();
$user->first_name = 'New';
$user->save();
// or, if 'first_name' is in your model $fillable array
$user->update(['first_name' => 'new' ]);
I need a little help and I can’t find an answer. I would like to replicate a row from one data table to another. My code is:
public function getClone($id) {
$item = Post::find($id);
$clone = $item->replicate();
unset($clone['name'],$clone['price']);
$data = json_decode($clone, true);
Order::create($data);
$orders = Order::orderBy('price', 'asc')->paginate(5);
return redirect ('/orders')->with('success', 'Success');
}
and i got an error :
"Missing argument 1 for
App\Http\Controllers\OrdersController::getClone()"
.
I have two models: Post and Order. After trying to walk around and write something like this:
public function getClone(Post $id) {
...
}
I got another error
Method replicate does not exist.
Where‘s my mistake? What wrong have i done? Maybe i should use another function? Do i need any additional file or code snippet used for json_decode ?
First of all, make sure your controller gets the $id parameter - you can read more about how routing works in Laravel here: https://laravel.com/docs/5.4/routing
Route::get('getClone/{id}','YourController#getClone');
Then, call the URL that contains the ID, e.g.:
localhost:8000/getClone/5
If you want to create an Order object based on a Post object, the following code will do the trick:
public function getClone($id) {
// find post with given ID
$post = Post::findOrFail($id);
// get all Post attributes
$data = $post->attributesToArray();
// remove name and price attributes
$data = array_except($data, ['name', 'price']);
// create new Order based on Post's data
$order = Order::create($data);
return redirect ('/orders')->with('success', 'Success');
}
By writing
public function getClone(Post $id)
you are telling the script that this function needs a variable $id from class Post, so you can rewrite this code like this :
public function getClone(){
$id = new Post;
}
However, in your case this does not make any sence, because you need and integer, from which you can find the required model.
To make things correct, you should look at your routes, because the url that executes this function is not correct, for example, if you have defined a route like this :
Route::get('getClone/{id}','YourController#getClone');
then the Url you are looking for is something like this :
localhost:8000/getClone/5
So that "5" is the actual ID of the post, and if its correct, then Post::find($id) will return the post and you will be able to replicate it, if not, it will return null and you will not be able to do so.
$item = Post::find($id);
if(!$item){
abort(404)
}
Using this will make a 404 page not found error, meaning that the ID is incorrect.
I am trying to bind a model that has composite key. Take a look, at first place I define my route:
Route::get('laptop/{company}/{model}', 'TestController#test');
Now, I define as I want to be resolved:
$router->bind('laptop', function ($company, $model) {
$laptop = ... select laptop where company=$company and ...;
return $laptop;
});
Now, I see how I am injecting the class in order to get the laptop in the controller: function into to test the resolution:
function test(Laptop $laptop){
return 'ok';
}
However, I am receiving the following error:
BindingResolutionException in Container.php line 839:
I assume that the error is caused by $router->bind('laptop' because it should matches a unique placeholder in the url ("company" or "model"). In my case I get lost because I need to matches both at the same time.
Note: I am not using db/eloquent layer. This problem is focused in the way on how to resolve route binding with multiples keys representing an unique object.
I am not sure if is it possible or if am I missing something. Thank you in advance for any suggestion.
Laravel does not support composite key in eloquent query.
You need to use query builder method of laravel to match against both values. ie: DB::select()->where()->where()->get();
Just put select and where conditions in above.
If you bind $router->bind('laptop', ...); then your route parameter should be Route::get('{laptop}', ...);. There is two possibility to query a laptop by model and company as you expected.
The safest way is query laptop on your controller:
Route::get('laptop/{company}/{model}', 'TestController#test');
In you TestController.php
function test(Laptop $laptop, $company, $model){
return $laptop->whereCompany($company)->whereModel($model)->first();
}
Another solution is allow slashes on your route parameter:
Route::get('laptop/{laptop}', 'TestController#test')->where('laptop', , '(.*)?');
and your binding function could be:
$router->bind('laptop', function ($laptop) {
$laptop = explode('/', $laptop);
$company = current($laptop);
$model = end($laptop);
if ((count($laptop) === 2) && ($result = App\Laptop::whereCompany($company)->whereModel($model)->first()) {
return $result;
}
return abort(404);
}