Service provider only for certain routes - Laravel - php

I'm building a page builder in laravel. The frontend renders "blocks" that are added to a page in my admin. I figured that the best way to make sure these blocks are available everywhere I need them is to load them in a View Composer which works great;
View::composer('*', function ($view) {
$blocks = Page::where('url', url()->current());
return view()->with(['blocks', $blocks]);
});
However, this attempts to load blocks for frontend routes and for admin routes. Is there any way to make sure they're only loaded for routes on the frontend?
I've split my routes in to separate files like this;
// lets me use an admin.php for my admin routes, instead of web.php
$this->mapAdminRoutes();
protected function mapAdminRoutes()
{
Route::prefix('admin')
->middleware('admin')
->namespace($this->namespace)
->group(base_path('routes/admin.php'));
}
I did find this question when googling
Binding a Laravel service provider on specific routes
but that still loads the service provider on all routes - just defers the view composer (which works for that OPs performance concerns).

A middleware is better for this type of things, as you can apply it to whichever route/group of routes you want.

Related

Laravel 8 Auth middleware protected route failing

I am building my first Laravel app with the Metronic 8 Laravel theme. It uses Breeze for authentication. I changed a couple of things around - created a welcome page for non-logged-in users, and moved the main template that was the index to an auth protected "/dashboard". The problem is that it still tries to load the dashboard Blade template, regardless of authentication, resulting in an error.
Route
Route::get('/dashboard', function () {
return view('dashboard');
})->middleware(['auth'])->name('dashboard');
Here's Authenticate, where it should redirect non-authenticated users to the login page.
protected function redirectTo($request)
{
if (! $request->expectsJson()) {
return route('login');
}
}
When I'm not logged in and navigate to the dashboard URL, it attempts to load the dashboard Blade template, which calls a menu function that checks the user permissions for menu items. Unfortunately, since there is no user, the application blows up from passing a null value to a method expecting a user array/object.
Any ideas on where to look for the problem? It seems to me that the auth middleware should redirect to the login page before trying to load the Blade template when not logged in.
I would put the middleware at the beginning of the route like this, though I'm sure it's not causing the problem-
Route::middleware(['auth'])->get('/dashboard', function () {
return view('dashboard');
})->name('dashboard');
Aside from that, please provide some information on the error itself like what the error is about/what is says..etc...
First of all, make sure you have a login named route defined in your routes/web.php file. It should look something like:
Route::get('/login', '<controller>#<method>')->name('login');
The important bit is ->name('login') so that the Authenticate middleware can correctly identify the route to redirect to. Change <controller>#<method> appropriately to route to the login method of your app.
Wakil's answer is irrelevant and actually opposite of the documentation. Your syntax is correct.
I figured out the issue. Keen Themes put a call to a method to build an array of menu items in the web routes file. That was making the call to the offending code. After I wrapped that in an auth check the error was fixed, and everything works as expected.

Can we use two Laravel project one for web services & another for Backend admin panel with single database

I have a doubt that can i use two Laravel project that is one for web services and another one for backend admin panel separately with single database.How much it will fast if i use separately.
and If i use both in single Laravel project will any problem in term of speed and data loading.
Please anyone elaborate this.
Yes, you could setup multiple Laravel / PHP applications to share the same database. However, that's probably not what you want to do.
Looks like you are concerned about having the same database being used for your private and public interfaces. As long you setup your authentication properly, there is no problem in doing that.
In your routes files, for ex. web.php, make sure to protect any routes that access private data with the auth middleware.
For ex.:
// Public Routes
...
// Ex. Home...
Route::get('/', function () {
return view('home');
});
// Private Routes
Route::group(['prefix' => 'app', 'middleware' => 'auth'], function () {
// My private routes here...
});
I also recommend having separate controllers for public and private routes. This way, when you are creating a new "public" route, it will point to a method in a "public" controller. And when creating a new "private" route, it will point to a method in a "private" controller. This is not necessary, but it helps separating your private and public logic / data.
When it comes to performance, it won't be an issue as long you index your tables properly.

Laravel Forwarding Route To Another Route File

I'm building enterprise modular Laravel web application but I'm having a small problem.
I would like to have it so that if someone goes to the /api/*/ route (/api/ is a route group) that it will go to an InputController. the first variable next to /api/ will be the module name that the api is requesting info from. So lets say for example: /api/phonefinder/find
In this case, when someone hit's this route, it will go to InputController, verifiy if the module 'phonefinder' exists, then sends anything after the /api/phonefinder to the correct routes file in that module's folder (In this case the '/find' Route..)
So:
/api/phonefinder/find - Go to input controller and verify if phonefinder module exists (Always go to InputController even if its another module instead of phonefinder)
/find - Then call the /find route inside folder Modules/phonefinder/routes.php
Any idea's on how to achieve this?
Middlewares are designed for this purpose. You can create a middleware by typing
php artisan make:middleware MiddlewareName
It will create a middleware named 'MiddlewareName' under namespace App\Http\Middleware; path.
In this middleware, write your controls in the handle function. It should return $next($request); Dont change this part.
In your Http\Kernel.php file, go to $routeMiddleware variable and add this line:
'middleware_name' => \App\Http\Middleware\MiddlewareName::class,
And finally, go to your web.php file and set the middleware. An example can be given as:
Route::middleware(['middleware_name'])->group(function () {
Route::prefix('api')->group(function () {
Route::get('/phonefinder', 'SomeController#someMethod');
});
});
Whenever you call api/phonefinder endpoint, it will go to the Middleware first.
What you are looking for is HMVC, where you can send internal route requests, but Laravel doesn't support it.
If you want to have one access point for your modular application then you should declare it like this (for example):
Route::any('api/{module}/{action}', 'InputController#moduleAction');
Then in your moduleAction($module, $action) you can process it accordingly, initialize needed module and call it's action with all attached data. Implement your own Module class the way you need and work from there.
Laravel doesn't support HMVC, you can't have one general route using other internal routes. And if those routes (/find in your case) are not internal and can be publicly accessed then also having one general route makes no sense.

Laravel 5.6 404 event

I've been going round in circles on this.
We wrote a CMS system in Laravel 3 using a bundle.
Time has come to develop a new one using latest Lavarel 5.6 and that mean packages.
We want to be able to define our own routes in web.php but everything that is not defined is picked up by the CMS package routes file so it can check if there is a page defined in the CMS and return the correct view.
In L3 this we did:
Event::override('404', function() {
...magic
In laravel 5.6 you can't do this so i've tried all sorts of:
Route::any('/{any}', function ($url = false) {
})->where('any', '.*');
But the issue is Laravel loads all the routes files in memory and the /{any} route overrides any of the routes defined in web.php, regardless of the order the service providers are loaded and we want to allow routes to be defined but to mop up anything that is not already defined.
In L4 it looks like you used to be able to do this:
App::missing(function($e) {
But again that's not possible in L5
I could possibly run it though an exception handler, but I want this to work in the package so its easily installable, and I haven't been able to make this work either!
Any help would be appreciated.
// other routes redirected to login
Route::get('/{any}', function () {
return redirect('/login');
})->where('any', '.*s');
try this route

Best practice for creating administrator interface in Laravel 4

I would like to create an administrator interface for my Laravel project, which is completely separated from the user side.
For example, in Yii framework I can make a module and this will ensure full separation from the user side. Inside a module I can use separate folder structure etc.
This is really a broad question and one answer can't cover everything about best practice for admin controllers or back end management but there are some basic concepts for building an Admin Panel:
// Keep all of your admin routes inside something like this
Route::group(array('prefix'=> 'admin', 'before' => 'auth.admin'), function() {
// Show Dashboard (url: http://yoursite.com/admin)
Route::get('/', array('uses' => 'Admin\\DashBoardController#index', 'as' => 'admin.home'));
// Resource Controller for user management, nested so it needs to be relative
Route::resource('users', 'Admin\\UserController');
});
// Other routes (Non-Admin)
Route::get('login', array('uses' => 'AuthController#showLogin' 'as' => 'login'));
By using a prefix you may separate all admin routes whose url will be prefixed with admin so, if you have a users controller for user management in back end then it's url will be prefixed with admin, i.e. site.com/admin/users. Also using a before filter you may add an authentication for all admin controllers in one place, that means, to access all of your admin controllers user must be logged in and the filter could be something like this:
Route::filter('auth.admin', function($route, $request, $args){
// Check if the user is logged in, if not redirect to login url
if (Auth::guest()) return Redirect::guest('login');
// Check user type admin/general etc
if (Auth::user()->type != 'admin') return Redirect::to('/'); // home
});
For, CRUD (Create, Read, Update, Delete) use a resourceful controller, for example, the UserController in an example of resourceful route declaration.
Use repository classes (Repository Pattern) for decoupling of dependencies, read this article.
Always use a named route, i.e. array('as' => 'routename', 'uses' => 'SomeController#method'), this is an example of naming a route. Named routes are easy to refer, i.e. return Redirect::route('admin.home') will redirect to site.com/admin because we have used admin.home in as to assign the name for that route.
Keep admin controllers in a separate folder and use a namespace for example, Admin\\DashBoardController#index controller should be in app/controllers/admin and your DashBoardController controller should look like this:
<?php namespace Admin;
class DashBoardController extends \BaseController {
public function index()
{
//...
}
}
There are more but it's enough to start with, read articles online and must read the documentation.
If you are familiar with composer you can import in packages (aka modules)
There is a widely available module with multi level interface already called Sentry 2.0:
https://github.com/cartalyst/sentry
You could also make your own if needed if the one I propose is too complex.
There is even a "laravel-ready" version of sentry.
I use the same directory structure that you would like to use on most (if not all) my Laravel projects. Basically, I keep admin views and admin controllers separate from the front-end ones.
Examples:
Controllers:
app/controllers/admin/Admin*Name*Controller.php
app/controllers/site/*Name*Controller.php
Views:
app/views/admin/some_folder/index.blade.php
app/views/site/some_folder/index.blade.php
I would also suggest that you install this laravel project https://github.com/andrewelkins/Laravel-4-Bootstrap-Starter-Site which will give a very good starting on how to organise things in your laravel project. It also has the same folder structure you would like to use.
Good luck.

Categories