routing forms and related models - laravel

This a beginners question about how to set up the route and controllers for a simple management system in Laravel 4.2.
Lets say I have a 'person' model (contains 'name' and 'email'). I also have a 'books' model that belongs to 'person' (contains 'title' and 'author', 'person_id').
To create a new person, the route to the form is:
example.com/persons/create
I would like the route for associating a new book to a person to be something like:
example.com/persons/22/books/create
Currently my routes are set up like this:
Route::resource('persons', 'PersonsController');
Route::resource('books', 'BooksController');
My person model contains the function:
public function books(){
return $this->hasMany('Book');
}
My book model contains the function:
public function persons(){
return $this->belongsTo('Person');
}
Where have I gone wrong? What have I missed?

From docs:
To "nest" resource controllers, use "dot" notation in your route declaration
Route::resource('persons.books', 'BooksController');
To get a list of registered route paths, you can use console command php artisan routes

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.

How will I identify resource default url in laravel?

I am running this command for model, migration, resource controller.
`php artisan make:model QuestionAnswer -mc -r` ..
Laravel give me in Resource Controller
public function show(QuestionAnswer $questionAnswer) {
// return $questionAnswer;
}
public function edit(QuestionAnswer $questionAnswer) {
// return $questionAnswer;
}
public function update(Request $request, QuestionAnswer $questionAnswer){
// return $questionAnswer;
}
if I write in web.php
Route::resource('question-answer','QuestionAnswerController'); or
Route::resource('questionAnswer','QuestionAnswerController'); or
Route::resource('question_answer','QuestionAnswerController'); laravel resolve route model binding...
that means....
Example as a
public function edit(QuestionAnswer $questionAnswer)
{
return $questionAnswer;
}
$questionAnswer return object for this url {{route('admin.question-answer.edit',$questionAnswer->id)}}
but if I write in web.php Route::resource('faq','QuestionAnswerController');
laravel can not resolve route model binding...
that means.. $questionAnswer return null for this url {{route('admin.faq.edit',$questionAnswer->id)}}
also in show and update function $questionAnswer; return null...
for working as a faq url.. i need change in edit function variable($faq) . or Route::resource('faq','QuestionAnswerController')->parameters(['faq' => 'questionAnswer']);I
But These three url questionAnswer,question-answer,question_answer by default work...
I check it on "laravel/framework": "^6.0" (LTS)
Question
is there possible way to find out what exact url I will write ? .. like question-answer.. or is there any command line ...
after running auth command .. php artisan route:list command give us all route list.. and when I make model Category laravel create table name categories and follow grammar rules
Actually Laravel has got Naming Convection Rules In its core.
These Convictions make it to default binding database_tables to model, model to controllers ....
if you want, you can tell your custom parameters but if you dont, The Laravel uses its own default and searching for them.
for example: if you have a model named bar, laravel look for a table named plural bars . and if you dont want this behave, you can change this default by overriding the *Models* $table_name` attribute for your custom parameter.
There are some Name Convection Rules Like :
tables are plural and models are singular : its not always adding s (es) in trailing.
sometimes it acts more complicate. like : model:person -> table: people
pivot table name are seperate with underline and should be alphabetic order: pivot between fooes and bars table should be bar_foo (not foo_bar)
table primary key for Eloquent find or other related fucntion suppose to be singular_name_id : for people table : person_id
if there are two-words name in model attribute, all of these are Alias :
oneTwo === one_two == one-two
check this out:
class Example extends Model{
public function getFooBarAttribute(){
return "hello";
}
}
all of this return "hello" :
$example = new Example();
$example->foo_bar();
$example->fooBar();
// $example->foo-bar() is not working because - could be result of lexical minus
there is a page listing laravel naming conventions :
https://webdevetc.com/blog/laravel-naming-conventions/
Name Conventions : is The Language Between The Laravel and Developer
it made it easy to not to explicitly mention everything
like Natural Language we can eliminate when we think its obvious.
or we can mention if its not (like ->parameter(...)).
How will I know I need to write question-answer this ? by default it works... when i write faq i need to change in edit function variable($faq) .
How will I know by default url (question-answer) will work ..when php
artisan route:list command give us all route list.. and when I make
model Category laravel create table name categories and follow grammar
rules
think about i will create 20 model ,migration & controller by cmd... i will not change edit,show and update function variable ...how i will know the default url for 20 model and controller ?
Laravel is an opinionated framework. It follows certain conventions
Let us understand a route parts
Route::match(
['PUT', 'PATCH'],
'/question-answer/{questionAnswer}',
[QuestionAnswerController::class, 'update']
)->name('question-answers.update')
In the above route:
1st argument: ['PUT', 'PATCH'] are the methods which the route will try to match for an incoming request
2nd argument: '/question-answer/{questionAnswer}' is the url wherein
/question-answer is say the resource name and
{questionAnswer} is the route parameter name
3rd argument: [QuestionAnswerController::class, 'update'] is the controller and the action/method which will be responsible to handle the request and provide a response
When you create a model via terminal using
php artisan make:model QuestionAnswer -mc -r
It will create a resource controller for the 7 restful actions and take the method parameter name for show, edit, update and delete routes as camel case of the model name i.e. $questionAnswer
class QuestionAnswerController extends Controller
{
public function show(QuestionAnswer $questionAnswer){}
public function edit(QuestionAnswer $questionAnswer){}
public function update(Request $request, QuestionAnswer $questionAnswer){}
public function delete(QuestionAnswer $questionAnswer){}
}
Which means if you don't intend to change the parameter name in the controller methods then you can define the routes as below to get the benefit of implicit route model binding
//Will generate routes with resource name as questionAnswer
//It would not be considered a good practice
Route::resource('questionAnswer', QuestionAnswerController::class);
//OR
Route::resource('question-answer', QuestionAnswerController::class)->parameters([
'question-answer' => 'questionAnswer'
]);
//OR
Route::resource('foo-bar', QuestionAnswerController::class)->parameters([
'foo-bar' => 'questionAnswer'
]);
RFC 3986 defines URLs as case-sensitive for different parts of the URL. Since URLs are case sensitive, keeping it low-key (lower cased) is always safe and considered a good standard.
As you can see, you can name the url resource anything like foo-bar or question-answer instead of questionAnswer and yet keep the route parameter name as questionAnswer to match the Laravel convention when generating controller via php artisan make:model QuestionAnswer -mc -r and without having to change the parameter name in controller methods.
Laravel is an opinionated framework which follows certain conventions:
Route parameter name ('questionAnswer') must match the parameter name in controller methods ($questionAnswer) for implicit route model binding to work
Controller generated via artisan commands, have parameter name as camelCase of the model name
Routes generated via Route::resource('posts', PostController::class) creates routes with resource name equal to the first argument of the method and route parameter name as the singular of the first argument
Route::resource() provides flexibility to use a different name for route resource name and route parameter name
Read more at Laravel docs:
https://laravel.com/docs/8.x/controllers#restful-naming-resource-route-parameters
https://laravel.com/docs/8.x/controllers
https://laravel.com/docs/8.x/routing#route-model-binding
If you want to know how the php artisan make:model works you can study the code in vendor/laravel/framework/src/Illuminate/Foundation/Console/ModelMakeCommand.php and have a look at the various stubs these commands use to generate the files.
For almost all artisan commands you will find the class files with code in
vendor/laravel/framework/src/Illuminate/Foundation/Console and the stubs used by the commands to generate files in vendor/laravel/framework/src/Illuminate/Foundation/Console/stubs folder.
If you study these command classes properly then you will get an idea of the various conventions Laravel follows when generating files via the artisan commands
I think its becuse of dependency injection which you used in youre method.
Try this
public function edit($id)
{
// return $questionAnswer;
return view('backend.faq.edit',get_defined_vars());
}

Crud Generator with Laravel

Since 2 weeks I work in a projet of devlopment of a application. I must creat many CRUD and it may take many times. Now I want to know if I can use a free crud generator laravel.If yes, which generator?
Need your Help please.
Command:
php artisan make:model User -mrc
RESTful Resource controller
A RESTful resource controller sets up some default routes for you and even names them.
Route::resource('users', 'UsersController');
Gives you these named routes:
Verb Path Action Route Name
GET /users index users.index
GET /users/create create users.create
POST /users store users.store
GET /users/{user} show users.show
GET /users/{user}/edit edit users.edit
PUT|PATCH /users/{user} update users.update
DELETE /users/{user} destroy users.destroy
And you would set up your controller something like this (actions = methods)
class UsersController extends BaseController {
public function index() {}
public function show($id) {}
public function store() {}
}
You can also choose what actions are included or excluded like this:
Route::resource('users', 'UsersController', [
'only' => ['index', 'show']
]);
Route::resource('monkeys', 'MonkeysController', [
'except' => ['edit', 'create']
]);
RESTful Resource Controller documentation
Implicit controller
An Implicit controller is more flexible. You get routed to your controller methods based on the HTTP request type and name. However, you don't have route names defined for you and it will catch all subfolders for the same route.
Route::controller('users', 'UserController');
Would lead you to set up the controller with a sort of RESTful naming scheme:
class UserController extends BaseController {
public function getIndex()
{
// GET request to index
}
public function getShow($id)
{
// get request to 'users/show/{id}'
}
public function postStore()
{
// POST request to 'users/store'
}
}
Implicit Controller documentation
It is good practice to use what you need, as per your preference. I personally don't like the Implicit controllers, because they can be messy, don't provide names and can be confusing when using php artisan routes. I typically use RESTful Resource controllers in combination with explicit routes.
Laravel already provides CRUD operation see: laravel.com/docs/5.8/controllers#resource-controllers
Laravel resource routing assigns the typical "CRUD" routes to a controller with a single line of code. For example, you may wish to create a controller that handles all HTTP requests for "photos" stored by your application. Using the make:controller Artisan command, we can quickly create such a controller:
php artisan make:controller PhotoController --resource
[EDIT 1]
Or you can choose for example: Laravel-Backpack/CRUD which comes with an Admin panel and others things like that.
[EDIT 2]
Also you can refer this Laravel blog to choose a generator:
https://laravel-news.com/13-laravel-admin-panel-generators
[EDIT 3]
Again on Laravel Blog you can see that Laravel is constantly evolving a new Artisan command have been added see:
laravel-news.com/laravel-resources-artisan-command

How to call method dynamically on routes on Laravel?

I'm a newbie with this and I need some help.
I'm developing some kind of music library and let's say I don't want to make a route for each artist so I have made this one:
Route::get('/{artist_name}', 'Artist_controller#{artist_name}');
I get the value of {artist_name} from my view and the route works, for instance, the artist_name may be John and the url generated is localhost:8000/John. But when it comes to look for the class in the controller it doesn't work. I have a class named John in my controller, but I keep getting this error when I try to access:
BadMethodCallException
Method [{artist_name}] does not exist.
So I guess the route isn't taking the value of {artist_name}. What I intend is the route to be processed like:
Route::get('/John', 'Artist_controller#John');
But as I said, I don't want to create a specific route for an artist.
I'd appreciate any kind of help. Thank You
There is no need to create a dynamic method for each artist. You could have one generic method in your controller that handles retrieving the proper artist information from the database and pass it to the view.
routes file:
Route::get('artists/{artist_id}', 'ArtistsController#show');
ArtistsController.php
class ArtistsController extends Controller
{
public function show($artist_id)
{
$artist = Artists::find($artist_id);
return view('artists.show', ['artist' => $artist]);
}
}
So if the user hits the following URL http://localhost/artists/4 the artist id of 4 will be passed to the show method and it will dynamically looks for an artist with that ID and pass an object of artist to your view.
Of course you are not limited to IDs in your URLs. You can use the name if it was unique and your code will be as the following.
routes file:
Route::get('artists/{artist_name}', 'ArtistsController#show');
ArtistsController.php
class ArtistsController extends Controller
{
public function show($artist_name)
{
$artist = Artist::where('name', $artist_name);
return view('artists.show', ['artist' => $artist]);
}
}
I suggest you read this documentation for more information about routing.
You can not have dynamic method (controller action) in a controller class. Instead you should define a method and pass the route parameter to that action.
In your route (web.php) file:
Route::get('/{artist_name}', 'ArtistController#artist');
then in ArtistController.php:
public function artist ($artist_name) {
// do stuff based on $artist_name
}
To get more info read these 2 documentation pages. Controller and Routing.

Laravel - Route::resource vs Route::controller

I read the docs on the Laravel website, Stack Overflow, and Google but still don't understand the difference between Route::resource and Route::controller.
One of the answers said Route::resource was for crud. However, with Route::controller we can accomplish the same thing as with Route::resource and we can specify only the needed actions.
They appear to be like siblings:
Route::controller('post','PostController');
Route::resource('post','PostController');
How we can choose what to use? What is good practice?
RESTful Resource controller
A RESTful resource controller sets up some default routes for you and even names them.
Route::resource('users', 'UsersController');
Gives you these named routes:
Verb Path Action Route Name
GET /users index users.index
GET /users/create create users.create
POST /users store users.store
GET /users/{user} show users.show
GET /users/{user}/edit edit users.edit
PUT|PATCH /users/{user} update users.update
DELETE /users/{user} destroy users.destroy
And you would set up your controller something like this (actions = methods)
class UsersController extends BaseController {
public function index() {}
public function show($id) {}
public function store() {}
}
You can also choose what actions are included or excluded like this:
Route::resource('users', 'UsersController', [
'only' => ['index', 'show']
]);
Route::resource('monkeys', 'MonkeysController', [
'except' => ['edit', 'create']
]);
API Resource controller
Laravel 5.5 added another method for dealing with routes for resource controllers. API Resource Controller acts exactly like shown above, but does not register create and edit routes. It is meant to be used for ease of mapping routes used in RESTful APIs - where you typically do not have any kind of data located in create nor edit methods.
Route::apiResource('users', 'UsersController');
RESTful Resource Controller documentation
Implicit controller
An Implicit controller is more flexible. You get routed to your controller methods based on the HTTP request type and name. However, you don't have route names defined for you and it will catch all subfolders for the same route.
Route::controller('users', 'UserController');
Would lead you to set up the controller with a sort of RESTful naming scheme:
class UserController extends BaseController {
public function getIndex()
{
// GET request to index
}
public function getShow($id)
{
// get request to 'users/show/{id}'
}
public function postStore()
{
// POST request to 'users/store'
}
}
Implicit Controller documentation
It is good practice to use what you need, as per your preference. I personally don't like the Implicit controllers, because they can be messy, don't provide names and can be confusing when using php artisan routes. I typically use RESTful Resource controllers in combination with explicit routes.
For route controller method we have to define only one route. In get or post method we have to define the route separately.
And the resources method is used to creates multiple routes to handle a variety of Restful actions.
Here the Laravel documentation about this.
i'm using Laravel 8 in my project
and in my route file web.php
i add this route
Route::controller(SitesController::class)->group(function() {
Route::get('index', 'index')->name('index');
}
in the Route::controller group we pass controller name we will use
inside the group we define the route we'll use as below syntax
Route::method-used('prefix in the URL', 'function used in the specified controller ')->name(); if the name not used in your code just delete it

Resources