Having trouble with Model Bind - Laravel Breadcrumbs - laravel

Having trouble with Model Bind on davejamesmiller/laravel-breadcrumbs.
I'll try to be brief, but if you need more data just ask =D
This is my controller/action signature:
public function edit(Request $request, Vertical $vertical, UserMacro $macro)
And this is my BC for the corresponding route:
Breadcrumbs::register('macro-edit', function (Generator $breadcrumbs, $vertical, $macro) {
$breadcrumbs->parent('macro-index');
$breadcrumbs->push($macro->name, route('macro-edit', [$vertical->_id, $macro]));
});
I'm getting the string ID on $vertical and $macro, breaking on $macro->name. If I add Hints as the action have I get aType error.
Trying to get property of non-object (View: /.../resources/views/layouts/app.blade.php) (View: /.../resources/views/layouts/app.blade.php)
Type error: Argument 2 passed to DaveJamesMiller\Breadcrumbs\BreadcrumbsServiceProvider::{closure}() must be an instance of App\Vertical, string given, called in /.../vendor/davejamesmiller/laravel-breadcrumbs/src/BreadcrumbsGenerator.php on line 68 (View: /.../resources/views/layouts/app.blade.php) (View: /.../resources/views/layouts/app.blade.php)

I didn't analyze core code of library, so i don't know why controllers work, but breadcrumbs don't. Recipe to working model binding is use proper route naming convention.
Breadcrumbs::for('messages.show', function($trail, \App\Models\MassMessage $massMessage) {
$trail->parent('Index');
$trail->push('Show', route('messages.show', $massMessage));
});
Route::get('messages/{massMessage}', 'MessageController#show')->name('messages.show');
// error (controllers are fine)
Route::get('mass-mmessages/{massMessage}', 'MessageController#show')->name('messages.show');
// works both
The same problem is with resource route.
edit:
I was wrong. Controller also doesn't work. It not raise error but it pass empty Eloquent object. In my case i needed to change $massMessage variable's name into $message in both places and works fine, now.

Related

Laravel edit controller not having data

I am trying to make crud in laravel. While doing dd of data variable in edit function attributes array is getting null
Route
Route::resource('/gameSettings', GameSettingController::class);
Controller
public function edit(GameSetting $game_setting)
{
dd($game_settings);
return view('admin.game_setting.edit', compact('game_setting'));
}
Model
class GameSetting extends Model
{
use HasFactory;
protected $fillable = [
'coin_value',
'minimum_withdraw_amount'
];
}
Link
https://localhost:8000/admin/gameSettings/1/edit
dd($game_settings); giving null array attribute
I dont have enough rep to comment so I give an answer...
#lagbox is correct. Your route parameter should match exactly as the variable typehinted in the controller for your case change $game_setting to $gameSetting
if you want to use $game_setting change your route to
Route::resource('/gameSettings', GameSettingController::class, ['parameters' => ['gameSetting' => 'game_setting']]);
The variable that you have typehinted on the Controller method must match exactly the name of the route parameter you have defined. In this case the parameter would be named gameSetting most likely. If you don't match these then you have Dependency Injection happening which would give you a new, non-existing, instance of the model. If you match the name then you will get Route Model Binding and it will look up the model and give you that particular entity.
If you want to see what the route parameter is named, since you are using resource routing, you can run php artisan route:list from the command line and it will show you those 7 routes and how they are defined.

Laravel routing: is there a syntax to pass a fixed parameter to the handler function?

I am using Laravel 8 and currently I have the following route:
Route::match(['get'], '/{action}', '\App\Http\MyController#handleRequest');
In the MyController class I have a handlerRequest function which takes two parameters
public function handleRequest(Request $request, string $action)
{
// Generic request handling code for every action, both GET and POST
// This code is fairly long and I don't want it to be duplicated
}
This all works well until I want to add another route for a specific request:
Route::match(['post'], '/message-sent', '\App\Http\MyController#handleRequest');
In this case only the POST method is allowed on the specific action message-sent, however it does not work using the above configuration as Laravel does not pass "message-sent" as $action to the handleRequest function.
The error message is
Too few arguments to function App\Http\MyController::handleRequest(), 1 passed in /var/www/html/vendor/laravel/framework/src/Illuminate/Routing/ControllerDispatcher.php on line 48 and exactly 2 expected
What I want is the action "message-sent" is passed into the generic handler function as parameter but at the same time achieving the "special post-only setting" for this specific route.
I tried
Route::match(['post'], '/{message-sent}', '\App\Http\MyController#handleRequest');
as well without success.
After searching through the Laravel source code, I think I found the solution
Route::match(['post'], '/message-sent', '\App\Http\MyController#handleRequest')->defaults('action', 'message-sent');
would achieve the effect of sending a fixed parameter $action="message-sent" to the handler function.

Customise the "method is not supported for this route" error handling in Laravel

Route::post('order', 'OrderController#store')->name('order');
When I browse to the URL http://127.0.0.1:8000/order it shows the error:
The GET method is not supported for this route. Supported methods: POST.
Which is the correct.
But I want to redirect user to home page instead of showing this error.
First of all note that what you are trying to do seems like an anti-pattern for Laravel. Accessing a route with the wrong method should be denied!
I currently do not know about altering the default way of handling the wrong method error and I wouldn't advise to do that. But you can work around it:
Patching
Method 1
Keep your routes file clean but alter the original route line and add some lines to the beggining of the controller method
Route::match(['get', 'post'], 'order', [OrderController::class, 'store'])->name('order');
public function store(Request $request)
{
if ($request->isMethod('get')) {
return to_route('home');
}
// ...
Method 2
Keep your controller clean, but add a line to your routes file
Route::get('order', fn () => to_route('home'));

laravel 5.8 edit function with model instance

public function edit(EduLevel $eduLevel)
{
dd($eduLevel->name);
return view('adm.edulevel.edit',compact('eduLevel'));
}
Route::resource('edulevel','EduLevelController'); //web.php
with resource route
how to get eduLevel to view with model instance laravel. in previous i call with parme parameter id and use find() method to get data..
from this sample - https://itsolutionstuff.com/post/laravel-58-crud-create-read-update-delete-tutorial-for-beginnersexample.html
I don't understand the question but I will just guess that you have a route that accepts a parameter that you you expect it to be the model inside your function.
You need to create a route like this one:
Route::get('/edit/{eduLevel}', 'SomeController#edit');
Notice the same name for the variable, this is important otherwise you will get only the id, slug or whatever.
Make sure your path name also have the same name for route segment name.
so your route path should be like this.
Route::get('/edit/{variablename}', 'ControllerName#edit');
your controller function logic should be like this.
public function edit(EduLevel $variablename)
{
return view('adm.edulevel.edit',compact('variablename'));
}
So make sure your variable name in route and in controller function
should be same.
For more information, you can read Route Model Binding in laravel
I am having the same problem (almost).
I wanted to call a controller method in the view. So I should pass the model from controller to view.
How to pass model from controller to view?
I found this [Laravel 5 call a model function in a blade view but using ->withModel($model); to pass the model from controller to view and {{$model->someFunction()}} to call the method in the view is not working.
Any advice please?

Laravel 4 route-model binding exceptions doesn't work despite docs and examples

I read a lot about Laravel4 Route-model binding (L4 docs, tutorials, etc.) but still exceptions (i.e. the model is not found) don't work for me
These are my basic files
routes.php:
Route::model('game', 'Game', function(){
// override default 404 behavior if model not found, see Laravel docs
return Redirect::to('/games');
});
...
Route::get('/games/edit/{game}', 'GamesController#edit');
GamesController.php
class GamesController extends BaseController {
...
public function edit(Game $game){
return View::make('/games/edit', compact('game'));
}
}
Pretty straight, but I get this error: Argument 1 passed to GamesController::edit() must be an instance of Game, instance of Illuminate\Http\RedirectResponse given
If I type http://mysite.dev/games/edit/1 all is fine (model with ID = 1 exists)
If I type http://mysite.dev/games/edit/12345 (no model with that ID) the ugly error above is triggered instead of the redirect I specified
I also looked at this (the bottom part where a Redirect closure is suggested: that is just what I am doing!) but no way to make it work: laravel 4 handle not found in Route::model
What's wrong with it? Please any help?
Thanks in advance
In Route::model you declare which variable will be a model instance, you shouldn't use it to do a redirection that way. Instead of that, specify that $game is of type Game and then work with your routes:
Route::model('game', 'Game');
...
Route::get('/games/edit/{game}', 'GamesController#edit');
Then if you access to /games/edit/3 GamesController::edit will receive an instance of Game class whose id=3
I ended up by setting a general "Not Found" error catcher, like this:
// routes.php
App::error(function(Symfony\Component\HttpKernel\Exception\NotFoundHttpException $e) {
return Response::make('Not Found', 404);
});
...
Route::model('game', 'Game');
...
Route::get('/games/edit/{game}', 'GamesController#edit');
What I understand is that if I want a custom redirect and not a general 404 page (i.e. take the user to games' list if model not found), I CAN'T use the route-model-binding
In other words, I have to use Route::get('/games/edit/{id}', 'GamesController#edit'); and then do my application logic inside the 'edit' method:
public function edit($id){
$game = Game::findOrFail($id);
// if fails then redirect to custom page, else go on saving
}
I'm very new to Laravel, but as far as I can see this has nothing to do with the closure, but with the use of "Redirect::to" inside that closure. Using "App::abort( 404 );" works.

Resources