How do I use Method Overloading in Laravel Controller? - php

I am trying to use method overloading feature in my laravel controller class. here is my methods
# Load Customer Balance View
public function createBalance()
{
return view('customer.balance');
}
# Load Customer Balance View
public function createBalance($CustomerID)
{
// show balance of the the defined customer
}
Here is my route -
// customer balance
Route::get('Customer/Balance', 'CustomerController#createBalance');
Route::get('Customer/Balance/{ID}', 'CustomerController#createBalance');
But it shows the error -
FatalErrorException in CustomerController.php line 45:
Cannot redeclare App\Http\Controllers\CustomerController::createBalance()
Any solution please ?

Consider use default parameters:
public function createBalance($CustomerID=null)
{
if ($CustomerID==null)
return view('customer.balance');
else
// show balance of the the defined customer
}
And change your route to:
Route::get('Customer/Balance/{CustomerID?}', 'CustomerController#createBalance');
Adding a "?" after the argument, Laravel understands you're passing an optional parameter.

You need to have different method names. This doesn't follow basic routing conventions either. The first createBalance method should probably be the index method.

I think createBalance() method alredy exist in your CustomerController so you should create new method or different name method and also change in route file with new method name.

Related

Laravel Model data not available in Controller

I'm new to Laravel. I might be making a basic mistake here but I've been trying and researching for a while, need some guidance here.
I have 2 routes:
Route::get('ordercontents/{ordercontent}', 'App\Http\Controllers\OrderContentsController#edit');
Route::get('ordercontents/delete/{ordercontents}', 'App\Http\Controllers\OrderContentsController#destroy');
Inside OrderContentsController.php I have the 2 functions, one to edit a record and another to delete it.
public function edit(\App\Models\Order_content $ordercontents)
{
dd($ordercontents); //the attributes will come out empty
$orderContentId = $ordercontents->id;
$ocs = getOrderContentDetails($orderContentId);
return view('ordercontents.edit')->with('ordercontents', $ocs);
}
public function destroy(\App\Models\Order_content $ordercontents)
{
$orderId = $ordercontents->order_id;
$ordercontents->delete();
return redirect('/new-ordercontent/' . $orderId)->with('success', 'Material removido da ordem de serviço!');
}
The model exists and is called Order_content.
Everything works well for the destroy function.
However, I'm struggling with the edit function.
If I do a dd($ordercontents); the attributes array of the object comes empty inside the edit function.
What am I missing? Thanks!
You have to make sure the name of the variable that is type-hinted in your method signature matches the route parameter for Route Model Binding:
"Laravel automatically resolves Eloquent models defined in routes or controller actions whose type-hinted variable names match a route segment name." - Laravel Docs
The method signature for edit can be adjusted to match the route parameter name:
public function edit(\App\Models\Order_content $ordercontent)
When these do not match you will have Dependency Injection happening so a new non-existing Model instance would be injected.
Laravel 8.x Docs - Routing- Route Model Binding - Implicit Binding

How to rename route key with model binding in PHP Laravel 8 (incorrect plurals)?

I have a Laravel 8 project where I have a model called FieldOfStudy, but the problem is that the plural of this class's name should be fields of study instead of field of studies. That causes a problem when creating an API endpoint with the following route:
Route::apiResource('fields-of-study', FieldOfStudyController::class);
The thing is, that I have a resource controller's method FieldOfStudyController::show() like this:
public function show(FieldOfStudy $fieldOfStudy)
{
dd($fieldOfStudy);
}
This will show me, that $fieldOfStudy contains a "blank" model, not the desired instance from the database. When I checked the route parameters, I found out, that the id of the model is stored as fields_of_study instead of field_of_study.
I tried to rename the parameter (didn't work - binding fails):
Route::apiResource('fields-of-study', FieldOfStudyController::class)->parameter('fields_of_study','field_of_study');
When I rename the parameter of the show() method, it works, but it's not really pretty:
public function show(FieldOfStudy $fieldsOfStudy) { }
How can I properly adjust my code to:
keep the URI in the correct plural (i.e. /fields-of-study),
keep the show() parameter name in the correct singular (i.e. $fieldOfStudy) and
don't mess the model-binding mechanism for typed parameters like show(FieldOfStudy $fieldOfStudy)?
Thank you :)
You can manipulate Laravel explicit binding:
RouteServiceProvider.php
public function boot()
{
Route::model('fields-of-study', FieldOfStudy::class);
}

Resource Controller methods with model as parameter not working

As in the basic Laracasts.com tutorial (Laracast 5.7 from scratch) I'm trying to use the following methods public function show(prototypes $prototypes) parameter to construct a view. However my view is created correctly but $prototypes is null.
The route works well(/prototypes/1/edit) and I ensured that a prototype object with the id 1 exists.
I found some older solution which stated to use something like (integer $id) as parameter but this leads to some more code. It should work like this:
Controller:
public function edit(prototypes $prototypes)
{
//
return view('prototypes.edit', compact('prototypes'));
}
According to Laracast From Scratch this should work.
Do you know how I could fix this?
What mechanism is behind this that the prototypes.edit method knows how to use the correct parameter?
For the Implicit Model Binding to works the injected variable name should match the route parameter name, in your case I think that your parameter name could be {prototype}, you can verify it by issuing the command php artisan route:list in the console.
If that is true you have to change the variable name to $prototype (please note the singular) in your controller function to match the parameter name {prototype}, like this:
public function edit(prototypes $prototype)
{
return view('prototypes.edit', compact('prototype'));
}
Update: BTW the laravel convention on Model's name is singular camel case, in your case your Model should be named Prototype not prototypes, i.e.:
public function edit(Prototype $prototype)
{
return view('prototypes.edit', compact('prototype'));
}
In order to inject the Prototypes model into the controller variable $prototypes, Laravel is expecting a matched name from the route to the input of the method. So in your routing, this:
/prototypes/1/edit
Needs to be
/prototypes/{prototypes}/edit
in order for the edit method to inject the correct instance of your prototypes model.

Two Controllers and 1 View in Laravel

I have one issue to solve about some calculations in Laravel 5.1, and until now the best solution that I found is to create Two different controllers, one to handle calculation for a specific item:
Route::get('company/convert/{note}','ScenarioController#NoteConvert');
And one for all items:
Route::get('company/convert','ScenarioController#AllNotesConvert');
Both will use render the same view.
My question is: Is a good practice to do this ?
In my head one good solution is to use just one route and receive 1 specific note or all of them in some variable through the request.
Something like:
$http.get('/company/convert/',data)
Where data will receive 1 or all notes that will be converted.
P.S.: I'm using AngularJS to call this routes.
If you prefer having one method in your controller you have to change your route a bit:
Route::get('company/convert/{note?}','ScenarioController#NoteConvert');
And your method would be something like
public function NoteConvert($note=null)
{
if ($note == null) {
// do all convertions
return view()
}
// single convertion
...
}
This way NoteConvert method will be the one that will handle multiple and single convertions.
Don't forget to remove
Route::get('company/convert','ScenarioController#AllNotesConvert');
It won't be necessary anymore
Edit:
https://laravel.com/docs/5.2/routing#parameters-optional-parameters
the best way for me, will be to passe an optional parameter in the url and check it on the controller.
i think your task is to produce the data of all items and specific data with filter using note argument in the view.
i reccomend you to create the route like this
Route::controller('company', 'ScenarioController');
then create a controller with two function like this
public function getIndex()
{
return view('convert');
}
here convert is name view blade .
public function postFilter($note)
{
$x= // do what you want
return view('convert', compact('x'));
}
then add a filter in the blade using a checkbox and make the form action url as
"company/filter/{note}".
this is the better practice i think.
refer implicit routing here. https://laravel.com/docs/5.1/controllers

How to create optional REST parameter in Laravel

I'd like my API to handle calls of the such:
/teams/colors
/teams/1/colors
The first would return all colors of all teams, the second would return colors of team 1 only.
How would I write a route rule for this in Laravel?
This should be simple using a laravel route.
Route::pattern('teamid', '[0-9]+');
Route::get('/teams/{teamid}/colors', 'controller#method');
Route::get('/teams/colors', 'controller#method');
Using the pattern, it lets you specify that a route variable must match a specific pattern. This would be possible without the pattern also.
I noticed you mentioned REST in the title. Note that my response is not using Laravel's restful routes system, but its normal routes system, but I'm sure this could be adapted to be restul, or work with the restful system.
Hope this helps.
Edit:
After a bit of looking around, you may be able to use this if you are using Route::resource or Route::controller.
Route::resource('teams', 'TeamsController');
Route::any('teams/{teamid}/colors', 'TeamsController#Method');
// Or to use a different route for post, get and so on.
Route::get('teams/{teamid}/colors', 'TeamsController#getMethod');
Route::post('teams/{teamid}/colors', 'TeamsController#postMethod');
Note: the resource word above can be replaced with ::controller.
*Note 2: I have not tested this and am unable to guarantee it would work, but it does seem possible.*
You may try something like this:
class TeamsController extends BaseController {
// GET : http://example.com/teams
public function getIndex()
{
dd('Colors of all teams');
}
// GET : http://example.com/teams/1/colors
public function getColorsById($id)
{
dd("Colors of team $id");
}
// This method will call the "getColorsById" method
public function missingMethod($parameter = array())
{
if(count($parameter) == 2) {
return call_user_func_array(array($this, 'getColorsById'), $parameter);
}
// You may throw not found exception
}
}
Declare a single route for both methods:
Route::controller('/teams', 'TeamsController');

Categories