I am (re-)learning Laravel and chose to do so via an excellent YouTube video in which we built a CRUD app. The app is mostly working very well but I have had a few problems with Laravel not "seeing" some routes until I moved them around in the web.php file.
This is my current web.php file, minus comments and routes used by a second controller:
<?php
use App\Models\Listing;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\UserController;
use App\Http\Controllers\ListingController;
//Show the full set of listings.
Route::get('/', [ListingController::class, 'index']);
//Manage listings belonging to the signed-in user
Route::get('/listings/manage', [ListingController::class, 'manage'])->middleware('auth');
//Show form to create job listing
Route::get('/listings/create', [ListingController::class, 'create'])->middleware('auth');
//Store new listing
Route::post('/listings', [ListingController::class, 'store'])->middleware('auth');
//Show form to edit job listing
Route::get('/listings/{listing}/edit', [ListingController::class, 'edit'])->middleware('auth');
//Submit completed edit form to database
Route::put('/listings/{listing}', [ListingController::class, 'update'])->middleware('auth');
//Delete listing from database
Route::delete('/listings/{listing}', [ListingController::class, 'destroy'])->middleware('auth');
//Show a single listing
Route::get('/listings/{listing}', [ListingController::class, 'show']);
My original web.php was exactly the same as this except that the '/listings/manage' route, currently the second in the list, was last. When that happened, every time I tried to invoke the /listings/manage route, the Clockwork browser extension indicated a 404 error and apparently indicated that it was trying to execute the show() method of the ListingController, rather than the manage() method. I was absolutely baffled by this and only eventually solved the problem by moving the /listings/manage route higher up in web.php.
On further testing, I'm finding that I now have the same problem when I'm trying to invoke the destroy() method to delete a listing from the database. Again, I get a 404 error and Laravel seems to be trying to execute the show() method if I am reading Clockwork correctly.
I really don't understand what is going on here with both cases. I could possibly solve the problem by moving the route that is trying to do the destroy() but I don't understand why I'm having the problems in the first place so I want to resolve that FIRST.
Can anyone enlighten me on this matter? I'm particularly curious how Laravel resolves the last three routes in the current web.php since they have the exact same URL, /listings/{listing}, so I'm wondering how it knows whether to invoke update(), destroy() or show().
UPDATE: To the anonymous individual who thought that the post he/she cited completely answered my question, it didn't. It didn't explain why the last three of my routes, which have an identical path, were apparently not the source of my problem. It also didn't give as complete a discussion of the possible solutions as some of the other answers I've obtained.
You have these to routes:
Route::get('/listings/{listing}',[ListingController::class, 'show']);
Route::get('/listings/manage', [ListingController::class, 'manage'])->middleware('auth')
laravel starts from first line of the script
and if requested path matches any route return it.
So suppose the request /listings/manage.
Laravel routing engine starts from first line of web.php .
First arrives to show method. Request matches it!!
The {listing} parameter could be anything even manage so routing engine stops here and return the show method. Not checking other routes to find more compatible route.
If you put the manage route at top of show so routing engine first arrives to it and matches to it and return it.
Laravel differs in the same routes by their request methods.
let's suppose the same path is defined in 3 routes but they have different request methods.(post,put,get).
The laravel get the path and match the request method and call that route.
Route::get('laravel/first',function(){});
Route::put('laravel/first',function(){});
Route::delete('laravel/first',function(){});
for more accuracy you may use the names of the routes. As:
Route::get('laravel/first',function(){})->name('getFirstData');
Route::delete('laravel/first',function(){})->name('deleteFirstData');
In carefully considering the answers I was given to my question, plus the older answers to similar questions, I've come up with a slightly different solution to my problem that seems to work fine. I'm posting it here now for two reasons:
To help others who may have difficulties along the same lines I had.
To get your feedback on this solution to see if it is reasonable or whether it should be avoided because of side-effects I don't see yet.
Here is my revised web.php with several routes added and several of the existing routes commented out:
<?php
use App\Models\Listing;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\UserController;
use App\Http\Controllers\ListingController;
//Show the full set of listings.
Route::get('/', [ListingController::class, 'index']); //default URL
Route::get('/listings/index', [ListingController::class, 'index']);
//Manage listings belonging to the signed-in user
Route::get('/listings/manage', [ListingController::class, 'manage'])->middleware('auth');
//Show form to create job listing
Route::get('/listings/create', [ListingController::class, 'create'])->middleware('auth');
//Store new listing
// Route::post('/listings', [ListingController::class, 'store'])->middleware('auth');
Route::post('/listings/store', [ListingController::class, 'store'])->middleware('auth');
//Show form to edit job listing
// Route::get('/listings/{listing}/edit', [ListingController::class, 'edit'])->middleware('auth');
Route::get('/listings/edit/{listing}', [ListingController::class, 'edit'])->middleware('auth');
//Submit completed edit form to database
// Route::put('/listings/{listing}', [ListingController::class, 'update'])->middleware('auth');
Route::put('/listings/update/{listing}', [ListingController::class, 'update'])->middleware('auth');
//Delete listing from database
// Route::delete('/listings/{listing}', [ListingController::class, 'destroy'])->middleware('auth');
Route::delete('/listings/destroy/{listing}', [ListingController::class, 'destroy'])->middleware('auth');
//Show a single listing
// Route::get('/listings/{listing}', [ListingController::class, 'show']);
Route::get('/listings/show/{listing}', [ListingController::class, 'show']);
I left the sequence of routes/functions the same but I could have changed it around as much as I like and still be confident that it would work. Basically, whenever the path had a parameter in it, I put the parameter last and preceded it with the name of the function that would be executing in the Controller. That ensured that every route (except '/') started with the Controller name, listings, followed by the function name, and possibly followed by a parameter if it was a specific listing, so that there could never be any confusion over which function the route was going to invoke.
Some routes didn't have to change at all because they already followed the pattern, namely /listings/manage and /listing/create. One route, '/', had a second route added for /listings/index because that's what is really being done; I just keep the '/' route as a reasonable default behaviour in case the user doesn't know what naming convention I am using for the routes and tries '/'.
Is that approach likely to bite me later in ways I haven't anticipated yet?
i just watch the way of calling the created view in web.php file
route::get('customer', function(){
return view('customer');
})
route::view('/',customer);`
both the method do the same work, is there is any difference between them in security ,are in some other way
If you working with Laravel then you want to do stuff for your controller (like getting a service data), should go with the option first. If you have to show a scene without doing stuff before being presented, you can go with another.
I'm wanting to create a website with laravel framework. I had made layout but now, have some zone i don't know how to set content for it. Ex: 2 zone of me are left-menu and cart (please view picture). My left-menu will get content from table: categories and cart will get content from package cart [Cart::content()].
It's on layout and of course, all page will have it. But i don't know how to give content of categories and cart() for it. Please help me
I think that you should to use View Composer.
https://laravel.com/docs/5.6/views#view-composers
Use Blade templates, as found here: https://laravel.com/docs/5.6/blade
Wherever in your page you want to print content, use the {{ $mycontent }} construct. You can also use confitionals and loop structures like #if and #foreach to loop through collections.
Then, in your controllers, you can just call the view and pass it content from your database or wherever you get it by doing something like:
return response()->view(“myView”, [“mycontent” => $content], $httpStatus);
You may opt for afterMiddleware if you want it on every page. Create a section on the master blade page (usually app.blade.php) and fill it in the middleware just like you would in any other controller. You can create a middleware by running php artisan create:middleware Cart. A file will be created at app/Http/Middleware/Cart.php.
Register the middleware in the app/Http/kernel.php file.
You may have to add a Auth::check() condition to avoid errors.
I'm trying to implement a very simple page tracking system with Laravel, just to know which pages are most accessed.
At first I thought of create a table with access date, request URL (from Request::path()) and user id, as simple as that.
But I'd have to show page titles on reports, and for that I need some way to translate the request URI to its page title. Any ideas for that? Is there a better way to accomplish this?
Currently I set page titles from Blade view files, through #section('title', ...).
Thank you in advance!
You can use Google Analytics to show pretty and very efficient reports. With the API, you can also customize the reports and (for example) show the pages titles.
If you want to develop it by yourself, I think that the best solution is to write an after filter that can be called after each page loading. One way of setting the title, in this case, is to use flash session variable (http://laravel.com/docs/session#flash-data) :
// routes.php
Route::group(array('after' => 'log'), function()
{
Route::get('users', 'UserController#index');
}
// filters.php
Route::filter('log', function() {
Log::create(array('title' => Session::get('title'), '...' => '...'));
}
// UserController.php
public function index()
{
Session::flash('title', 'Users Page');
// ...
}
// layout.blade.php
<head>
<title>{{ Session::get('title') }}</title>
...
I know this has already been answered but I would like to add that I've published a package that can be easily implemented to track page views for Laravel (if they are Eloquent ORM instances) in specific date ranges: last day, week, month or all time.
https://github.com/marcanuy/popularity
I am new to Laravel 4 and am having a hard time grasping routes. I have a frontend to my site and a backend. All the stuff that happens on the backend I want to have displayed under example.com/dashboard/.... I also want to use resourceful controllers. What do I need to setup in routes.php to have it so I can always refer to my users controller but have it all happen under dashboard in the URL?
Example:
I link to users/edit/1 but in the URL looks like example.com/dashboard/users/edit/1. Dashboard should have an index page (so example.com/dashboard actually shows a page) but all other URLs are appended to that.
I think this is covered pretty well in the Larvel 4 Documentation.
Unless I'm misunderstanding, this should get you the desired results for your example case:
Route::get('dashboard', 'DashboardController#index');
Route::get('dashboard/users/edit/{id}', 'UsersController#edit');
etc.
// edit
Alternatively, using a Closure callback, you could do something like this:
Route::get('dashboard/users/{var1}/{var2?}', function($var1, $var2 = null)
{
$controller = new UsersController;
return $controller->{$var1}($var2);
});
Which wouldn't require you to specify each and every route. Or, as I mentioned below in comments, you could use a Resource Controller if it suits your needs.