Laravel Forwarding Route To Another Route File - php

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.

Related

Laravel getting 404 error when creating new route

it appears that when I created a new route, I receive the 404 error when trying to access the url, which is funny,. because all of my other routes are working just fine.
My web.php looks like so:
Auth::routes();
Route::post('follow/{user}', 'FollowsController#store');
Route::get('/acasa', 'HomeController#index')->name('acasa');
Route::get('/{user}', 'ProfilesController#index')->name('profil');
Route::get('/profil/{user}/edit', 'ProfilesController#edit')->name('editareprofil');
Route::patch('/profil/{user}', 'ProfilesController#update')->name('updateprofil');
Route::get('/alerte', 'PaginaAlerte#index')->name('alerte');
Route::get('/alerte/url/{user}', 'UrlsController#index')->name('editurl');
Route::post('/alerte/url/{user}', 'UrlsController#store')->name('updateurl');
Route::get('/alerte/url/{del_id}/delete','UrlsController#destroy')->name('deleteurl');
The one that is NOT working when I am visiting http://127.0.0.1:8000/alerte is:
Route::get('/alerte', 'PaginaAlerte#index')->name('alerte');
The controller looks like so:
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Auth;
class PaginaAlerte extends Controller
{
public function __construct() {
$this->middleware('auth');
}
public function index(User $user)
{
return view('alerte');
}
}
I am banging my head around as I cannot see which is the problem. It is not a live website yet, I am just developing on my Windows 10 pc using WAMP.
Moved my comment to a little bit explained answer.
So, in your route collection, you have two conflicting routes
Route::get('/{user}', 'ProfilesController#index')->name('profil');
and
Route::get('/alerte', 'PaginaAlerte#index')->name('alerte');
Imagine that Laravel is reading all routings from top to bottom and it stops to reading next one after the first match.
In your case, Laravel is thinking that alerte is a username and going to the ProfilesController#index controller. Then it tries to find a user with alerte username and returning 404 because for now, you don't have a user with this username.
So to fix 404 error and handle /alerte route, you just need to move the corresponding route before /{username} one.
But here is the dilemma that you got now. What if you will have a user with alerte username? In this case, the user can't see his profile page because now alerte is handling by another route.
And I'm suggesting to use a bit more friendly URL structure for your project. Like /user/{username} to handle some actions with users and still use /alerte to handle alert routes.
The following route catches the url /alerte as well
Route::get('/{user}', 'ProfilesController#index')->name('profil');
Since this one is specified before
Route::get('/alerte', 'PaginaAlerte#index')->name('alerte');
The /alerte will go the the ProfilesController instead.
To fix this change the order of the url definitions or change either of the urls to have nesting e.g. /alerte/home or /user/{user}
Well.
Maybe this is too late, but I have all week dealing with this problem.
I made my own custom.php file and add it in the routes path of my Laravel project, and none of the routes were working at all.
This is how I solved it:
You must remember to edit the RouteServiceProvider.php file located in app\Providers path. In the map() function, you must add your .php file. That should work fine!
To avoid unexpected behaviors, map your custom routes first. Some Laravel based systems can "stop" processing routes if no one of the expected routes rules were satisfied. I face that problem, and was driving me crazy!
I would wish suggest to you declare your URL without the "/", like your first "post" route, because sometimes, I have been got this kind of errors (404).
So, my first recomendation is change the declaration of the route. After that, you should test your middleware, try without the construct, and try again.
Good luck!

Routing api to a controller in Laravel

I want to create a custom public API; and answer all api requests under ApiController with a routing like this:
Route::resource("/api","ApiController");
I tried to add this under routes/web or routes/api; but no chance. I get "Sorry..page not found".
Other routing options under routes/web work fine; I only have a problem when it comes to /api.
Should I proceed with a route like /custom_public_api or is there anything I can do about this?
If you put this in your api.php
Route::resource("/users","UserController");
Than the routes will be automatically prefixed with /api.
So the routes will look like this:
/api/users
/api/users/{user}
...
So in your case it is not working because you have this type of routes:
/api/api
/api/api/{api}
/api/api/{api}/edit
...
So you're having api twice. So you just have to suppose that the api prefix, is automatically added from routes/api.php.
For more information about your routes, you can run php artisan route:list and you can check how do your routes look like.
For api resources you have to use
Route::apiResource('photos', 'PhotoController');
as says in the documantation here (just scroll a little until you get to API Resource Routes)

Protect routes in Laravel 5.1

I am using Laravel 5.1 for my project. I am trying to secure Routes and make sure only logged in user can access certain routes. I am aware about middlewares but I am wondering if anyone post an example or a link explaining about middleware and how to protect a page using middleware.
Thanks
To build on the answer given by Joe Rose, you can also specify the middleware in your controller rather than in your routes.php file.
E.g you could have your routes set out like
Route::get('/example', 'ExampleController#index');
Route::post('/example/post', 'ExampleController#post');
Route::resource('blog', 'BlogController');
And then inside your controller reference it like so:
class ExampleController extends Controller
{
public function __construct()
{
$this->middleware('auth');
}
//....
If you're looking for more info, check out the link to the docs Joe gave, and also this blog post which explains what middleware is really well and how to create your own if you need to.
You are correct about using middleware. The included Auth middleware is what you should use, as long as you are also using the included Auth controller to authenticate users. You would write your route like this:
Route::get('/page', array(
'uses' => 'Controller#method',
'middleware'=>'auth'
));
(The above example is using a GET request, but it could other request types, like POST for example).
This will use the default behavior of the middleware which checks to see if the user is logged in (authenticated). You can also extend or overwrite the built-in functions to allow you to direct the application on where to send the user if they are or are not logged in, etc. Laravel's official documentation is a good starting point: link

cakephp 3 prefix routing

I'm trying to set up a routing prefix in cakephp 3 so any URLs starting with /json/ get the prefix key set and I can change the layout accordingly in the app controller. Other than that, they should use the usual controller and action. I have added the following to routes.php
$routes->prefix('json', function($routes) {
$routes->connect(
'/:controller/:action/*',
[],
['routeClass' => 'InflectedRoute']
);
});
I want to direct all requests with json as first url segment to controller specified in second url segment. e.g. /json/users/add_account_type/ goes to users controller. However when accessing this URL I get the message:
Error: Create the class UsersController below in file:
src/Controller/Json/UsersController.php
whereas I want it to be using
src/Controller/UsersController.php
I think this should be possible but I can't quite see what I'm doing wrong when consulting the book. Have partly based my code on: CakePHP3.x controller name in url when using prefix routing
Thanks a lot in advance
That's simply how prefix routing now works in 3.x, as explained in the docs, prefixes are being mapped to subnamespaces, and thus to separate controllers in subfolders.
http://book.cakephp.org/3.0/en/development/routing.html#prefix-routing
If you'd wanted to change that behavior (I don't really see why), one way would be to implement a custom ControllerFactory dispatcher filter.
http://book.cakephp.org/3.0/en/development/dispatch-filters.html
On a side note, the RequestHandler component supports layout/template switching out of the box, so maybe you should give that a try.
http://book.cakephp.org/3.0/en/controllers/components/request-handling.html
http://book.cakephp.org/3.0/en/views/json-and-xml-views.html
Prefix routing is a way of namespacing parts of your routes to a dedicated controller. It seem that what you want is a scope and not a prefix, for what you describe:
Router::scope('/json', function($routes) {
$routes->fallbacks('InfledtedRoute')
});

Dynamic Routing in cakephp issue

I want to use Dynamic Routing for the static pages of my site.
I have used the following code in my Routes file
$arr = ClassRegistry::init('Page');
and
$this->loadModel('Page');
$arr = $this->Page->find('all');
foreach($arr as $value)
{
//my code
}
But it doesn't work, and shows an error like below:
ClassRegistry is not defined
Don't do that
you've tried to put controller code in your routes file and are intending to make your site so needlessly dependent on the database. Of course, your whole site is likely dependent on the database, but by making your routes db-dependent all requests that make it to cakephp (which means, all requests that are not a static file in the webroot) need to talk to the db at least slowing things down, and if anything goes wrong with the db, your site is white page of fatal error awesomeness for all requests. This is because the routes file is loaded very early in the request handling process. The routes file is not supposed to contain any real logic - just Router::connect statements.
Alternative: Use a catchall route
If you have any pattern that you can use for your static pages, use it so that you have only one route definition. i.e.:
Router::connect('/x/*', array('controller' => 'some', 'action' => 'thing')); //eerily similar to the default static pages route
Alternative: Write a static routes file
Build, however you like, your routes logic whenever the rules for your routes change and write them to a static file. Therefore your routes.php file becomes:
<?php
... routes that don't change ...
require 'path/to/dynamic_routes_file.php';
You can use the afterSave handler for a relevant model to trigger rebuilding this dynamic routes file.
More alternatives
There are many other ways to handle this kind of thing e.g. override the error handling process to first check if there's one of these db-dependent routes to process - Or simply create a custom route class which implements literally whatever you want.
Whatever you do though - aim for the logic at run time to be as simple/cached/static as possible - don't build a system which makes all requests need to talk to the db all the time.

Categories