Pattern based filter except one route - php

I have these filters in place
Route::when('app/*', 'auth');
Route::when('app/*', 'filled_basic_info');
The "filled_basic_info" filter redirects the user to the 'users.personal' route if the basic information of the user is not yet filled.
The 'users.personal' route leads to the "app/personal" url.
My question is, how do I set the 'filled_basic_info' filter to be applied on all the routes that lead to 'app/*' except the 'users.personal' route?
I have tried
Route::when('app/*', 'filled_basic_info', array('except' => 'users.personal'));
but it doesn't work.
I'd love to avoid grouping all the 'app/*' routes as I would need to do that on all the packages I have in place.
Thank you.

I ended up editing the filter like so:
Route::filter('filled_basic_info', function()
{
if (empty(Auth::user()->first_name) || empty(Auth::user()->last_name))
{
if(!(Route::currentRouteName() == "user.personal"))
return Redirect::route('user.personal')->withAlerts(['Please enter your name below to continue.']);
}
});

Related

Add JSON routes for all routes to handle backend requests

I'm using Laravel 5.1 and am building a service that can be seen as JSON or HTML. This approach is already done by sites like reddit.
Example
Normal view: http://www.reddit.com/r/soccer
JSON view: http://www.reddit.com/r/soccer.json
As you can see, they simply add .json to an URL and the user is able to see the exact same content either as HTML or as JSON.
I now wanted to reproduce the same in Laravel, however I'm having multiple issues.
Approach 1 - Optional parameter
The first thing I tried was adding optional parameter to all my routes
Route::get('/{type?}', 'HomeController#index');
Route::get('pages/{type?}', 'PageController#index');
However, the problem I was facing here, is that all routes were caught by the HomeController, meaning /pages/?type=json as well as /pages?type=json were redirected to the HomeController.
Approach 2 - Route Grouping with Namespaces
Next I tried to add route groupings with namespaces, to seperate backend and frontend
Route::get('pages', 'PageController#index');
Route::group(['prefix' => 'json', 'namespace' => 'Backend'], function(){
Route::get('pages', 'PageController#index');
});
However, this doesn't work either. It does work, when using api as prefix, but what I want, is that I can add .json to every URL and get the results as json. How can I achieve that in Laravel?
You can apply regular expressions on your parameters to avoud such catch-all situation as you have for HomeController#index:
Route::get('/pages{type?}', 'PageController#index'->where('type', '\.json'));
This way it type will only match, if it is equal to .json.
Then, to access it in your controller:
class PageController {
public function index($type = null) {
dd($type);
}
}
and go to /pages.json

Laravel 5 - Determine if route belongs to user

What I am looking to achieve here is to have the username set as myapp.com/username. I can achieve this by doing:
/*
* Other route logic, containing static-url pages, such as
* myapp.com/login so that it overrides any usernames
*/
Route::get('/{username}', function($username) {
return $username . "'s profile.";
});
However, I also want to include company pages following the same rule. For example, myapp.com/janes-bakery. But I cannot seem to achieve this because Laravel automatically stops searching for routes if it comes across one that returns nothing. Instead it will just throw a 404 page.
I did think that I could use something similar along these lines:
Route::get('/{slug}', ['as' => 'profile', function($slug) {
$company = \App\Models\Company::where('slug', '=', $slug)->get();
if($company->count() > 0) {
return "Company found.";
}
$user = \App\User::where('username', '=', $slug)->get();
if($user->count() > 0) {
return "User found.";
}
abort(404);
}]);
Which works fine, however I feel as though it's bad practice. Besides that, I cannot access suffix routes based on the company/user. For example myapp.com/jane/friends or myapp.com/janes-bakery/services.
Does anybody have any recommendations on how to go about this? I am finding it very hard to think of any solutions. Thank you in advance!
P.S. It is important the URLs have no correlation, e.g. no myapp.com/company/user (or vice versa), myapp.com/company_name_here and myapp.com/users_name_here are two totally separate things.
You can stick with your route and make another route with company/user pattern. You can do it this way.
Create another route with company and user parameter.
Route::get('{company}/{user}', function($company, $user){
dd($company, $user);
});
And you need to put this route above your profile route because, in laravel, the first route present will be processed before the others routes below.

Intercepting and changing route-based input in Laravel?

So I've been using Laravel a lot lately, and it's great! But I've found myself banging my head against the keyboard on this issue I'm having.
I have this pattern:
Route::pattern('id', '(\d*|(me))');
And this route is required for a lot of my API calls. What it's supposed to do, is give consumers the option to simply append /me at the end of the call, to get info relating to them, so not having to use the userId. I can of course put this login in the controller, no problem, but I would love to be able to put some login in the "pattern", meaning that if this pattern is used, that I can check what userId "/me" correspons to and translate it. I want to do it this way to avoid having to write the same code translating "/me" in all controllers where this is used.
Hope someone has a clever solution out there! :-)
You can try using a Route filter. Something like this ought to work:
Route::filter('route_filter_name', 'F\Q\ClassName');
<?php namespace F\Q;
class ClassName
{
/**
* #param Illuminate\Routing\Route
*/
public function filter($route)
{
$userId = $route->getParameter('id');
if($userId == 'me' && ($user = Auth::user())) {
$route->setParameter('id', $user->id);
}
}
}
This is more specific to the route rather than your route pattern as it depends on what name you give the id parameter in each route that you want to use it in. An example route that uses it would look like this:
Route::get('/users/{id}', [
'before' => 'route_filter_name',
'uses' => 'UserController#showUserInfo'
]);

Laravel 4 routing - the ability to skip a route if conditions are not met

So we have a load of content within the database, let's call these Articles. The paths for the Articles start from the application root and can contain slashes. So we want to search the DB to see if we match an Article, and if not skip the route and give other routes the opportunity to respond.
In Sinatra (which I believe has inspired the routing within Laravel) you have the option to pass to the next route. It might be this that's leading me astray.
Route::get( '{uri}', function( URI $uri ) {
// check database, if we find a record we'll need to pass it to the appropriate controller
// we'll have a class that handles this responsiblity
// pass if we don't find anything
} )->where('uri', '.*');
Route::get( 'other/page', 'OtherController#sayHello' );
The issue Allow skip the route based on conditions #1899 talks about this, although I can't see how filters cater for this, they will simply intercept and give you an opportunity to stop route execution (throw exception, redirect to route specifically etc.), you can't return FALSE; without error. There is an example chaining a condition method to a route, although this method doesn't seem to exist (in 4.2).
Any ideas?
In addition to this, we're also are thinking about containing this logic within a package so it can be shared across applications, and wonder if you can influence the order of execution of routes provided by package?
You can have a group of routes, which you contain within all the routes that match it. If it fails that group then it skips to the next section.
Route::group(array('before' => 'auth'), function()
{
Route::get('/', function()
{
// Has Auth Filter
});
Route::get('user/profile', function()
{
// Has Auth Filter
});
});
http://laravel.com/docs/4.2/routing

Laravel pattern based filter

I'm reading the Laravel documentation and it is saying that it is possible to add a pattern based filter to a route
Route::filter('admin', function()
{
//
});
Route::when('admin/*', 'admin');
I want to know how to specify if the filter is executed before or after the request?
Pattern filters are always called before and cannot be called after a routes execution.
You can see it being called in the source (4.1.24) on GitHub.
A solution to this is to have all your admin routes inside a route group and apply the filter to the entire group.

Categories