I'm wondering how the caller script calls the following codes in Laravel.
Route::get('/', function () {
// return view('welcome');
return redirect('public');
});
Auth::routes();
Route::get('/home', 'HomeController#index');
Route::get('/download', 'routinesController#download');
You may check the web.php, or api.php in routes folder to see what I mean. This may not actually specific to Laravel but to programming as well. I just want to understand the script how it calls them.
Its called a Facade php pattern
If you open a Illuminate\Support\Facades\Facade it contains all the magic behind how it gets invoke in Laravel.
So simple way to understand is laravel use App container for it.
I hope it make sense
Related
I've been trying to learn Laravel by myself and some features are bugging my mind. I'm trying to display a simple login form with just inputs and a button, so should I use function create and return a view or just declare Route::view on web.php to show a blade form?
OBS: I noticed that if the blade expect any data, I have to go through a controller, but since this won't use it that would not be a problem.
Keep in mind I'm just trying to learning the best and professional way possible.
This is how I would code on the AuthController:
public function create() {
return view('auth.login');
}
VS
And this is how I would declared on web.php:
Route::controller(AuthController::class)->group(function () {
Route::view('/login', 'auth.login')->name('login')->middleware('guest');
}
If your route only needs to return a view, you may use the Route::view method.
So that's dependent on
1-what you do.
2- the purpose of the view.
3-complexity of your app.
4- data that you can pass to the view.
5- the best practice that seniors wrote.
you will capture the best practices by practice, build projects and see what professional engineers do
In your case you should use controller to hanle the authentication
see
https://laravel.com/docs/9.x/routing
https://laravel.com/docs/9.x/views
https://laravel.com/docs/9.x/blade
As Abdallah said, it depends.
You can start this way, if your controller have no other logic than returning the view, delete the controller and simply return the view in your route file:
Route::view('/login', 'auth.login')->name('login')->middleware('guest');
If then you need a parameter, but no other logic than passing it into your view, you can use a function:
Route::get('/login/{someParameter}', function () {
return view('auth.login', compact('someParameter');
})->name('login')->middleware('guest');
Then you might need some more logic, at this point you may want to create a controller to handle it:
Route::get('/login/{someParameter}', [AuthController::class, 'myMethod'])->name('login')->middleware('guest');
Then you might need some extra "guest only" pages as register. You may want to do some grouping:
Route::middleware('guest')->group(function () {
Route::get('/login', [AuthController::class, 'myMethod'])->name('login');
Route::get('/register', [RegisterController::class, 'myMethod'])->name('register');
});
Those are only some example of what you can do with routes.
You can refactor your route file as your project grows and try to learn more function of the routing of Laravel that may or may not help you as the time goes.
I would also suggest to follow the naming convention for the routes. Then you won't have to much trouble refactoring the route file if you don't have to change the name.
I started creating a REST API using the lumen framework and wanted to set up a particular behaviour for my GET /user route. Behaviour is the following:
If the request come from an authenticated user (using auth middleware), the method getAllFields from UserController is called and return all the data from the user
If it's not the case, the method get from UserController is called and return some of the data from the user
It seems logic to me to just write it like that in my web.php using a simple middleware:
<?php
$router->group(['middleware' => 'auth'], function () use ($router) {
$router->get('/user/{id}', [
'uses' => 'UserController#getAllFields'
]);
});
$router->get('/user/{id}', [
'uses' => 'UserController#get'
]);
But for some reason, even if the middleware is correct, I always get the response of the second route declaration (that call get()). I precise that if I remove the second route declaration, the one in the middleware work as expected.
Have someone an idea how I can achieve something similar that work?
Router will check if your request matches to any declared route. Middleware will run AFTER that match, so You cannot just return to router and try to find another match.
To fallow Laravel and Routes pattern - You should have single route that will point to method inside controller. Then inside that You can check if user is logged or not and execute getAllFields() from that controller. It will be not much to rewrite since You are currently using UserController in both routes anyway.
web.php
$router->get('/user/{id}', 'UserController#get');
UserController.php
public function get()
{
return auth()->check() ? YourMethodForLogged() : YourMethodForNotLogged();
}
Or if there is not much logic You can keep this in single method.
Also it is good idea to fallow Laravels REST standards (so use show instead of get, "users" instead of "user" etc - read more https://laravel.com/docs/7.x/controllers)
web.php
$router->get('/users/{user}', 'UserController#show');
UserController.php
public function show(User $user)
{
if (auth()->check()) {
//
} else {
//
}
}
To summary - for your needs use Auth inside controller instead of middleware.
To check if user is logged You can use Facade Auth::check() or helper auth()->check(), or opposite Auth::guest() or auth()->guest().
If you are actually using Lumen instead of full Laravel then there is not auth helper by default (You can make own or use package like lumen-helpers) or just keep it simple and use just Facades instead (if You have then enabled in Lumen).
Read more https://laravel.com/docs/7.x/authentication and https://lumen.laravel.com/docs/7.x/authentication
This pattern is against the idea of Laravel's routing. Each route should be defined once.
You can define your route without auth middleware enabled and then define your logic in the controller.
Any help why this is not working ,I am using Laravel 5.5.23 version ,this is are my routes :
<?php
Route::get('/', function () {
return view('welcome');
});
Route::resource('threads','ThreadController');
Auth::routes();
Route::get('/home', 'HomeController#index')->name('home');
Route::get('threads','ThreadController#index');
Route::get('threads/{channel}','ThreadController#index');
Route::get('threads/create','ThreadController#create');
Route::get('threads/{channel}/{thread}','ThreadController#show');
Route::post('threads','ThreadController#store');
Route::post('/threads/{channel}/{thread}/replies','ReplyController#store');
Route::get('/logout' , 'Auth\LoginController#logout');
This is the ThreadController ,just the relevant methods actually :
public function __construct()
{
$this->middleware('auth')->except(['index','show']);
}
public function index($channel = null)
{
if($channel){
//do something
}
else{
$threads=Thread::latest()->get();
}
return view('threads.index',compact('threads'));
}
The problem is when I try to access /threads/someChannel it returns not found ,so this is the problematic route : Route::get('threads/{channel}','ThreadController#index'); ,all other routes are working ,any idea why this one is not working ?
The Route::resource('threads','ThreadController') call is defining 7 routes with the prefix threads. Some of the routes you are defining yourself are being masked by this. Check php artisan route:list to see what routes the Route::resource call registers for you first. First come first serve when it comes to matching routes.
/threads/someChannel is going to match the route defined by the resource call:
GET /threads/{thread} ThreadController#show
Since you don't have the definition for show which is relevant to have, I would assume you have Implicit Model Binding happening. It is trying to bind that model to that parameter and it can't find it in the database by that ID and is causing a 404 because of it.
I'm fairly new to Laravel, so this question may obvious to some.
In the case of running checks per HTTP request, for example User Authentication. Is there a better, more efficient or simple correct way to run these checks. From my initial research it would seem that this could be accomplished using either MiddleWare, eg.
public function __construct()
{
$this->middleware('auth');
}
It also seems like it would be possible using routing groups, eg.
Route::group(['middleware' => 'auth'], function () {
Route::get('/', function () {
// Uses Auth Middleware
});
Route::get('user/profile', function () {
// Uses Auth Middleware
});
});
Is there any benefits of doing this either of these two ways? Apart from the obvious benefit of not having to put $this->middleware('auth'); in every controller auth would need to be checked.
Thanks
Edit..
After taking on your advice I attempted to utilities the route grouping to control my Auth MiddleWare. But this has seemed to have broken my site.
Route::group(['middleware' => 'auth'], function () {
Route::auth();
Route::get('/home', 'HomeController#index');
Route::get ( '/redirect/{provider}', 'SocialAuthController#redirect' );
Route::get ( '/callback/{provider}', 'SocialAuthController#callback' );
});
Am I missing something obvious?
You are almost there, just remove the Route::auth():
Route::group(['middleware' => 'auth'], function () {
Route::get('/home', 'HomeController#index');
//add more Routes here
});
The suggested options did not work for me but when I checked the laravel documentation, I found this:
Route::middleware(['web'])->group(function () {
//Your routes here
});
It works for me. Laravel 8.*
There is no real difference, personally i use groups for the standard middleware and put exceptions in the construct
Using Route group is easy for maintenance/modification , other wise you will have to remember each controller where you are using certain middle ware, of course this not a concern in a small medium sized application, but this will be hard in a large application where is lots of controller and references to middle ware.
So, to keep this short, how does laravel know what to do in the default controller when it sees the method 'showWelcome' ?
in routes there is
Route::get('/', function() { return View::make('hello'); });
which is fine, but how does it now to act on showWelcome.. where is that set in configs? could it be named something else?
If you're going by the default install of Laravel 4 (at the current time), the showWelcome method isn't actually fired on the HomeController controller for this route. However, the method would return the same thing as the route.
You could fire this method by changing to route to the following:
Route::get('/', 'HomeController#showWelcome');