I've got a simple Laravel 5 site that I am working on (learning Laravel)
I have a link on my 'users' view to add a 'new user':
Create New User
My user Routes look like the following:
Route::get('/users', 'UserController#index');
Route::get('/user/{id}', 'UserController#edit');
Route::get('/user/create', 'UserController#create');
Route::get('/user/update', 'UserController#update');
Route::get('/user/delete/{id}', 'UserController#delete');
My UsersController has the following:
/**
* Display a listing of the resource.
*
* #return Response
*/
public function index()
{
$users = user::all();
return view('user.index',compact('users'));
}
/**
* Show the form for creating a new resource.
*
* #return Response
*/
public function create()
{
$userroles = userrole::all();
return view('user.create', compact('userroles'));
}
When I click the link - I get the following error:
Trying to get property of non-object (View: C:\xampp\htdocs\mysite\resources\views\user\edit.blade.php)
I cannot figure out why it is trying to load edit.blade.php
I have tried just putting the following in my create view and it still doesn't render.
#extends('app')
#section('content')
Test
#endsection
I'm not sure why the routing is being so bizarre.
Any ideas?
Put the create (and update) route before the edit route in your routes file. Laravel 1st stumbles on the edit route and treats the create as id.
You can test it by doing a dd($id) in your edit method in the controller.
Related
Fairly new to laravel 8 with some experience with laravel 7. I'm trying to add some additional pages to the default dashboard nav menu. however after adding the code, as I expect it to be, I get this error:
Symfony\Component\Routing\Exception\RouteNotFoundException
Route [accounts.index] not defined. (View: /home/some/path/resources/views/navigation-menu.blade.php)
So here is what I have done code wise:
in web.php i have the following route:
Route::middleware(['auth:sanctum', 'verified'])
->get('/accounts', [AccountController::class, 'index'])
->name('accounts');
I have a controller /app/Http/Controllers/AccountController.php as follows:
<?php
namespace App\Http\Controllers;
use App\Models\Account;
use Illuminate\Support\Facades\View;
class AccountController extends Controller
{
//
public function index() {
$accounts = Account::all();
return View::make('pages.accounts.index')->with('accounts', $accounts);
}
/**
* Show the form for creating a new resource.
*
* #return Response
*/
public function create()
{
return View::make('pages.accounts.create');
}
/**
* Store a newly created resource in storage.
*
* #return Response
*/
public function store()
{
//
}
/**
* Display the specified resource.
*
* #param int $id
* #return Response
*/
public function show($id)
{
//
}
/**
* Show the form for editing the specified resource.
*
* #param int $id
* #return Response
*/
public function edit($id)
{
//
}
/**
* Update the specified resource in storage.
*
* #param int $id
* #return Response
*/
public function update($id)
{
//
}
/**
* Remove the specified resource from storage.
*
* #param int $id
* #return Response
*/
public function destroy($id)
{
//
}
}
I have a Model /app/Models/Account.php:
<?php
namespace App\Models;
use Eloquent;
class Account extends Eloquent
{
}
I also have blade templates for this page which i wont list for brevity as don't think this matters with the issue and at this point if I navigate to {url}/accounts the accounts index page is shown as intended.
However now I want to move this functionality into the jetstream dashboard so I can cut down on some development time and theme it similar to the default laravel concept.
The first thing I need is to add a new nav item next to Dashboard so I amended the default navigation-menu.blade.php file (/resources/views/navigation-menu.blade.php) by copying what it uses for dashboard and updating:
...
<!-- Navigation Links -->
<div class="hidden space-x-8 sm:-my-px sm:ml-10 sm:flex">
<x-jet-nav-link href="{{ route('dashboard') }}" :active="request()->routeIs('dashboard')">
{{ __('Dashboard') }}
</x-jet-nav-link>
</div>
<div class="hidden space-x-8 sm:-my-px sm:ml-10 sm:flex">
<x-jet-nav-link href="{{ route('accounts.index') }}" :active="request()->routeIs('accounts.index')">
{{ __('Accounts') }}
</x-jet-nav-link>
</div>
</div>
...
It is at this point when reloading the page throws the error. Anyone know what is causing this? I initially tried without using .index as this is the default anyway right?
I have also tried to follow a few tuts on doing this ((https://eheidi.dev/blog/creating-a-multi-user-to-do-application-with-laravel-jetstream-2p1k)) but I get the same error when i reload my page after editing the navigation-manu.blade.php file so I'm at a loss. I'm developing this on ubuntu 20.04
thanks
Craig
*** EDIT ***
I have updated my route to be a resource for better use moving forward.
Route::middleware(['auth:sanctum', 'verified'])
->resource('/accounts', [AccountController::class, 'index'])
->name('accounts.index');
Tested this without the amend in navigation-menu.blade.php and all still worked added back the amends and same error.
*** EDIT 2 ***
I have I think narrowed this down to what should be in the navigation-menu file and the web routes file. I have further amended my web.php code as per point 2 of an answer below by Chadrack:
Route::middleware(['auth:sanctum', 'verified'])
->resource('/accounts', AccountController::class)
->only( ['index', 'create', 'store', 'update'])
->name('index', 'accounts');
The snippet I added to the navigation-menu.blade.php is:
<div class="hidden space-x-8 sm:-my-px sm:ml-10 sm:flex">
<x-jet-nav-link href="{{ route('accounts') }}" :active="request()->routeIs('accounts')">
{{ __('Accounts') }}
</x-jet-nav-link>
</div>
This is still throwing the error, also if i add .index to route function ( route('accounts.index') ) I still get an error (either Route [accounts.index] not defined or Route [accounts] not defined
*** EDIT 3 ***
I repeated the initial tutorial I had tried and failed with (https://eheidi.dev/blog/creating-a-multi-user-to-do-application-with-laravel-jetstream-2p1k) but as with my issue here after i have added the x-jet nav-link section to the blade template and added the route, when i reload i get the same error (with the new defined route) Route [dashboard-todo] not defined. So if the issue I get is the same for both options then I must be missing something here? As pointed out before I have tried every combination of route type. It works using the url [url]/accounts until I add the link into the nav-bar. The Dashboard does work when no changes are made to the navigation-menu.blade.php
you need to call your route using it's name.
in your definition you are define the route with the name accounts while you are calling a route named by accounts.index
replace your route
Route::middleware(['auth:sanctum', 'verified'])
->get('/accounts', [AccountController::class, 'index'])
->name('accounts');
By
Route::middleware(['auth:sanctum', 'verified'])
->get('/accounts', [AccountController::class, 'index'])
->name('accounts.index');
// note this
Your route name is accounts and you called accounts.index, it will not work, you have two possibilities to fix them.
replace :
Route::middleware(['auth:sanctum', 'verified'])->get('/accounts', [AccountController::class, 'index'])->name('accounts')
by :
Route::middleware(['auth:sanctum', 'verified'])
->get('/accounts', [AccountController::class, 'index'])
->name('accounts.index')
You can also use resources as method :
Route::middleware(['auth:sanctum', 'verified'])->resource('/accounts', AccountController::class)->only(['index', 'create','store',update]);
So just in case anyone else had this issue, I managed to fix it as follows:
First i used the following in web.php:
Route::middleware(['auth:sanctum', 'verified'])->resource('/accounts', \App\Http\Controllers\AccountController::class);
Note no name element and the full path to the controller (in addition to it being in a use at the top of web.api.
I then ran the following to clear my routes:
php artisan route:clear
I was then able to use the following in navigation-menu.blade.php:
<x-jet-nav-link href="{{ route('accounts.index') }}" :active="request()->routeIs('accounts.index')">
{{ __('Accounts') }}
</x-jet-nav-link>
Note I call accounts.index here. Now when i go onto my dashboard I see the new menu item and can visit the page as required. I am now also able to add the other pages from this resource (ie create, edit, destroy).
Of note I'm not sure if i need the full path in the route, found this on another post on SO and now it is working as I expected I don't wish to upset the apple-cart.
thanks
Craig
I have a main site and an admin control panel.
I want to have different 404 pages for each version.
How should I do this? I currently have the following code in my app/Exceptions/Handles.php file:
/**
* Render an exception into an HTTP response.
*
* #param \Illuminate\Http\Request $request
* #param \Exception $exception
* #return \Illuminate\Http\Response
*/
public function render($request, Exception $exception)
{
if($exception instanceof \Symfony\Component\HttpKernel\Exception\NotFoundHttpException)
{
$view = $request->is('admin/*') ? 'acp.errors.404' : 'errors.404' ;
return response()->view($view, [], 404);
}
return parent::render($request, $exception);
}
But I use the package spatie/laravel-permission and get the following error;
Trying to get property 'role' of non-object (View: F:\Development\RPR\site\resources\views\layouts\acp.blade.php) (View: F:\Development\RPR\site\resources\views\layouts\acp.blade.php)
I use in acp.blade.php auth()->user()->role, to get the user role, which just works fine without any exception. How should I fix this?
Here are two ways to accomplish different 404 views depending on the route. Both will allow you to have these error pages:
/resources/views/acp/errors/404.blade.php
/resources/views/errors/404.blade.php
The directories will be checked in order until a view is found, which means you can selectively add custom error views and fall through to the default when none exist. If the route did not match, then it will not look for a custom error page.
Option 1
Override registerErrorViewPaths() inside app/Exceptions/Handler.php:
/**
* Register the error template hint paths.
*
* #return void
*/
protected function registerErrorViewPaths()
{
parent::registerErrorViewPaths();
if (request()->is('admin/*')) {
View::prependNamespace(
'errors',
realpath(base_path('resources/views/acp/errors'))
);
}
}
Option 2
Create a ViewServiceProvider:
php artisan make:provider ViewServiceProvider
Register your provider in config/app.php:
'providers' => [
// ...
App\Providers\ViewServiceProvider::class,
],
Edit the boot method of your provider:
/**
* Bootstrap services.
*
* #return void
*/
public function boot()
{
if (request()->is('admin/*')) {
View::prependNamespace(
'errors',
realpath(base_path('resources/views/acp/errors'))
);
}
}
For the second part of the question, auth()->user() is only available when the session middleware has run. If the 404 was caused by the route not existing, then the request does not go through the web middleware and unfortunately sessions and auth information will not be available. However, if the 404 was caused by a ModelNotFoundException triggered inside a controller, then the web middleware probably did run and you can access the user.
Inside your error view you have to check if the user is signed in:
#guest
<p>Hello, guest</p>
#else
<p>Hello, {{ auth()->user()->name }}</p>
#endguest
If this is not good enough for your use case, then you might want to try Route::fallback(), which allows you to define a controller for serving 404 pages and does run web middleware.
I'm starting my first Laravel project (first MVC / OOPHP project infact) and could use some help with routes.
I followed the guide at https://medium.com/employbl/easily-build-administrator-login-into-a-laravel-5-app-8a942e4fef37 to add a check if user is admin when loading a page. It works for normal view routes, e.g.
Route::get('/admin/something', 'AdminController#admin_something')
->middleware('is_admin')
->name('admin');
But I now have a resource route and get an error when I add the two -> lines to the route. So this works with no auth:
Route::resource('thingies', 'ThingyController');
But with this:
Route::resource('thingies', 'ThingyController')
->middleware('is_admin')
->name('admin');
I get the error Symfony \ Component \ Debug \ Exception \ FatalThrowableError (E_RECOVERABLE_ERROR)
Too few arguments to function Illuminate\Routing\PendingResourceRegistration::name(), 1 passed in /var/www/routes/web.php on line 24 and exactly 2 expected
What do I need to do differently to add this auth to a resource route?
The is_admin() function from the tutorial:
const ADMIN_TYPE = 'admin';
const DEFAULT_TYPE = 'default';
public function isAdmin() {
return $this->type === self::ADMIN_TYPE;
}
And the middleware:
namespace App\Http\Middleware;
use Closure;
class IsAdmin
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if(auth()->user()->isAdmin()) {
return $next($request);
}
return redirect('home');
}
}
You can't name your route "admin" with ->name('admin'); at the end of your resource route because it concerns all CRUD routes in one statement and Laravel build-in system has already named them.
You're on the good way, just delete the last line like so, it should works :
Route::resource('thingies', 'ThingyController')
->middleware('is_admin');
You cannot give a 'name' to a resource route. but you can give names to each method in the resource controller separately.
to do so name() function required 2 parameters.
method name
name for that method route.
,
Route::resource('thingies', 'ThingyController')
->middleware('is_admin')
->name('create', 'admin.create');
I am working on a school project. while working on a schools detail page I am facing an issue with the URL. My client needs a clean URL to run AdWords. My school detail page URL: http://edlooker.com/schools/detail/4/Shiksha-Juniors-Ganapathy. But he needs it like http://edlooker.com/Shiksha-Juniors-Ganapathy. If anyone helps me out it will be helpful, thanks in advance.
You need to define this route after all routes in your web.php (if laravel 5.x) or in routes.php (if it is laravel 4.2).
Route::get('{school}','YourController#getIndex');
And your controller should be having getIndex method like this,
public function getIndex($school_name)
{
print_r($school_name);die; // This is just to print on page,
//otherwise you can write your logic or code to fetch school data and pass the data array to view from here.
}
This way, you don't need to use the database to get URL based on the URL segment and you can directly check for the school name in the database and after fetching the data from DB, you can pass it to the school details view. And it will serve your purpose.
Check Route Model Binding section in docs.
Customizing The Key Name
If you would like model binding to use a database column other than id when retrieving a given model class, you may override the getRouteKeyName method on the Eloquent model:
/**
* Get the route key for the model.
*
* #return string
*/
public function getRouteKeyName()
{
return 'slug';
}
In this case, you will have to use one front controller for all requests and get data by slugs, for example:
public function show($slug)
{
$page = Page::where('slug', $slug)->first();
....
}
Your route could look like this:
Route::get('{slug}', 'FrontController#show');
My problem is concerned with:
a blog homepage called via the ArticlesController#index function
the individual blog post pages called via ArticlesController#show function, and
the comment form to be embedded into the individual blog post pages that would post to blog/{blog}/comment and would invoke the CommentsController#store method
I have the following routes of concern defined in my routes.php file:
Route::resource ('blog', 'ArticlesController');
Route::resource ('blog/{blog}/comment', 'CommentsController');
The ArticlesController is set to call the auth middleware for all functions except index() and show($id):
public function __construct()
{
$this->middleware('auth', ['except' => 'index', 'show']);
}
When I attempt to access the individual blog post pages without the comment form, it works as expected and allows me to access the homepage and individual post pages without authentication.
Whereas when I have the comment form embedded into the individual post pages, it allows me to access the homepage but demands me to authenticate before I could access the individual post pages.
Can anyone tell me why it behaves so even though my CommentsController is a separate entity and it is not invoking the auth middleware?
The except argument should be an array
public function __construct()
{
$this->middleware('auth', ['except' => ['index', 'show']]);
}
Updated per comment
If you look at the code for the middleware method if is looking for an array.
/**
* Register middleware on the controller.
*
* #param string $middleware
* #param array $options
* #return void
*/
public function middleware($middleware, array $options = [])
{
$this->middleware[$middleware] = $options;
}
As to why it worked before, who knows. I imagine that at some point along the chain of methods Laravel is converting a string to an array and that is why it worked.
You might want to consider writing a test for your controller. That way you are not dependent on any particular moment of how it is working. You know it works the way you intended and that nothing you do changes the expected result.