Suppose I have multiple routes in my Laravel routes.php Like-
Route::post( 'createClan',array('uses'=>'MyClan#createClan'));
Route::post( 'joinClan',array('uses'=>'MyClan#joinClan'));
Route::get( 'myclan', array( 'as' => 'myclan' , 'uses' => 'MyClan#myclan' ));
Route::get( 'clanDetails', array( 'as' => 'clanDetails' , 'uses' => 'MyClan#clanDetails' ));
Route::get( 'myclanDefault', array('as' => 'myclanDefault' , 'uses' => 'MyClan#myclanDefault' ));
And I have Controller named 'Common' and I have a 'ValidateRoute' function inside that common like this-
public function ValidateRoute($UserId, $form_name){
switch ($form_name)
{
case 'createJoin'://Create/Join Clan Menu Option.
$createJoin=TRUE;
$clans= Userclanmapping::where('user_id','=',$UserId)->where('active','=',1)->get(array('clan_id'));
foreach($clans as $clan)
{
$createJoin=FALSE;
}
return $createJoin;
}
}
My problem is that I want to call that function before calling that route. And If the function returns true only then I can open that route but if function returns false I should be moved to another route or I should get a message like route not found.
In short, I am trying to apply a custom check on every route. A route is only accessible only if it fulfills that conditions.
I tried this code-
Route::get( 'myclanDefault', array( 'before'=>'common:ValidateMenuOptions(Session::get(\'userid\'),\'createJoin\'))','as' => 'myclanDefault' , 'uses' => 'MyClan#myclanDefault' ));
But this didn't work.
You can use route filters per route basis using something like this:
// In filters.php
Route::filter('myclanDefaultFilter', function($route, $request){
// ...
if(someCondition) {
return Redirect::route('routeName');
}
});
Then declare the route like this:
Route::get(
'myclanDefault',
array(
'before' => 'myclanDefaultFilter',
'as' => 'myclanDefault',
'uses' => 'MyClan#myclanDefault'
)
);
Now before myclanDefault is dispatched to the action the myclanDefaultFilter filter will run first and you may redirect from that filter depending a certain condition.
Also, you may declare a global before event for all the routes using something like this:
App::before(function($request){
// This event will fire for every route
// before they take any further action
});
Related
I want to create dynamic route name for my app. Here is my route file
Route::group(['prefix' => '{team}/dashboard', 'middleware' => 'isMember'], function() {
Route::get('/user', array('uses' => 'UserController#index', 'as' => 'user.index'));
Route::get('/user/edit/{id}', array('uses' => 'UserController#edit', 'as' => 'user.edit'));
Route::patch('/user/{id}', array('uses' => 'UserController#update', 'as' => 'user.update'));
Route::delete('/user/{id}', array('uses' => 'UserController#destroy', 'as' => 'user.delete'));
it's not simple if i have to define route like this
'route' => ['user.delete', $team, $user->id]
or
public function destroy($team,$id) {
// do something
return redirect()->route('user.index', $team);
}
I want to generate route name like "$myteam.user.delete" or something more simplier like when i define "user.delete" it includes my team name.
How i can do that? is it possible?
You could do that by setting as. Also using resource routes will be handy.
$routeName = 'team.';
Route::group(['as' => $routeName], function(){
Route::resource('user', 'UserController');
});
Now you can call like
route('team.user.index');
More on resource routes here https://laravel.com/docs/5.3/controllers#resource-controllers
try this:
Route::delete('/user/{team}/{id}', array('uses' => 'UserController#deleteTeamMember', 'as' => 'myteam.user.delete'));
Now call the route as:
route('myteam.user.delete', [$team, $id]);
Have a list of providers with a three filters (location, category, event type), i need to concatenate filters in routes for make the url more friendly, it would be like ej.: mysite.com/filter/location/cordoba/eventtype/weeding/category/travels
these filters are not required, so i can filter for only location, or location and category, event type and category, etc.. now my question is, ¿could i do that in laravel 5.2?
i before do this like this:
Route::get('/filtro/localidad/{localidad?}', [
'uses' => 'ProviderController#filterLocation',
'as' => 'site_filter_location_path'
]);
Route::get('/filtro/tipo_evento/{event_type?}', [
'uses' => 'ProviderController#filterEventType',
'as' => 'site_filter_event_type_path'
]);
Route::get('/filtro/rubro/{caption?}', [
'uses' => 'ProviderController#filterCaption',
'as' => 'site_filter_caption_path'
]);
i need something like this (it send me a error where i put only one or two parameters)
Route::get('/filtro/location/{localidad?}/event_type/{event_type?}/caption/{caption?}', [
'uses' => 'ProviderController#filter',
'as' => 'site_filter_path'
]);
Let's say that I search by location and category, then the url would be like this: mysite.com/location/cordoba/event_type//caption/travel This generates a bad url which gives me error, then how can I do this?
Laravel will not know how to find your route every time you have a missing parameter, so you cannot really rely on
Route::get('/filtro/location/{localidad?}/event_type/{event_type?}/caption/{caption?}', [
'uses' => 'ProviderController#filter',
'as' => 'site_filter_path'
]);
You should have something like
Route::get('/filtro/location/{localidad}/event_type/{event_type}/caption/{caption}', [
'uses' => 'ProviderController#filter',
'as' => 'site_filter_path'
]);
So in this case you can call
/filtro/location/Santito/event_type/Fiesta/caption/false
To be sure there would not have missing parameters.
What I prefer to do
Filtering is something hard to put in URLs. Every time you have a new filter, you'll get a new url and that's not good at all, because it gets messy really fast. What people do, usually is to have an endpoint only for the filter, and use url parameters to configure the filter. Laravel pagination is a kind of filter that does not uses route, but url parameter. So I would do
Route::get('/filtro', [
'uses' => 'ProviderController#filter',
'as' => 'site_filter'
]);
And a controller like this
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class ProviderController extends Controller
{
private function buildFilter($request, $query)
{
if ($localidad = $request->get('localidad')) {
$query->where('localidad', $localidad);
}
if ($tipoEvento = $request->get('tipo_evento')) {
$query->where('tipo_evento', $tipoEvento);
}
...
return $query;
}
public function filter(Request $request)
{
$query = Localidad::newQuery();
$query = $this->buildFilter($request, $query);
$query->where('filter something else');
return view('home', ['data' => $query->get()]);
}
}
Then you only have to make a form using method="GET" to filter
<form action="/filtro" method="GET">
...
</form>
And you app should receive requests like
/filtro?localidad=Santa Maria&tipo_evento=Fiesta
And if you need to hit your own routes, by doing internal filter, you can do things like:
Route::get('/filter', function () {
$items = [
'localidad' => 'Buenos Aires',
'tipo_evento' => 'Santa Maria',
'rubro' => 'Todos',
];
$items = collect($items)->map(function($item, $key) {
return "$key=$item";
});
$filter = implode('&', $items->toArray());
return redirect()->to('/filter?'$filter);
});
In the example $filter is localidad=Buenos Aires&tipo_evento=Santa Maria&rubro=Todos, so it would call
/filter?localidad=Buenos Aires&tipo_evento=Santa Maria&rubro=Todos
I have following routes:
Route::group(['prefix' => 'group1'], function () {
Route::get('view1', ['as' => 'group1_view1', 'uses' => 'group1Controller#get_view1']);
Route::get('view2', ['as' => 'group1_view2', 'uses' => 'group1Controller#get_view2']);
});
Route::group(['prefix' => 'group2'], function () {
Route::get('view1', ['as' => 'group2_view1', 'uses' => 'group2Controller#get_view1']);
Route::get('view2', ['as' => 'group2_view2', 'uses' => 'group2Controller#get_view2']);
});
I wish to pass variables, for example, $title = 'group-one' to all views in group1 and $title = 'group-two' to all views in group2. Instead of adding variable $title in all methods in each group controller, is it possible to pass variables groupwise in routes?
NO you cannot pass variables into route groups, but if in case you need one piece of view/code in multiple views, title for example, you can use view composers instead.
In my routes file, I have;
Route::get('/{token}/student', [
'uses' => 'SurveyController#resumeSurvey',
'as' => 'student',
]);
Route::get('/{token}/city', [
'uses' => 'SurveyController#resumeSurvey',
'as' => 'city',
]);
So the route is either "student" or "city". How do I determine which one in my controller method? Should I even be structuring my routes like this? Should I just point them to two different methods?
I can easily pass in {token} for example with just;
public function resumeSurvey($token)
{
Inside a controller you can get a current route name by getting a route object Illuminate\Routing\Route, at first place, then calling its method getName.
The next two ways are the same.
public function resumeSurvey($token)
{
$routeName = Route::getCurrentRoute()->getName();
$routeName = $this->getRouter()-> getCurrentRoute()->getName());
}
You should use different methods if you would like different things to do.
Example:
Route::get('/{token}/student', [
'uses' => 'SurveyController#resumeStudent',
'as' => 'student',
]);
Route::get('/{token}/city', [
'uses' => 'SurveyController#resumeCity',
'as' => 'city',
]);
And in your controller you should have two methods:
public function resumeStudent($token) {
}
public function resumeCity($token) {
}
Then your first route goes to resumeStudent and the ohter route to resumeCity.
How to you add a filter to a route and pass a controller to it?.
In Laravel's doc they said that you can add a filter to a route like this:
Route::get('/', array('before' => 'auth', function()
{
return 'Not Authorized';
}));
But I need to pass a controller, like this:
Route::get('/', array('before' => 'auth', 'HomeController#index'));
But I get this error when I do it like that:
call_user_func_array() expects parameter 1 to be a valid callback, no array or string given
Any idea?
You should pass the controller function with uses key, So replace,
Route::get('/', array('before' => 'auth', 'HomeController#index'));
With,
Route::get('/', array('as' => 'home', 'before' => 'auth', 'uses' => 'HomeController#index'));
And there should be a route for login to process the auth filter like this.
Route::get('login', function()
{
if(Auth::user()) {
return Redirect::to('/');
}
return View::make('login');
});
Wanted to add another solution to your problem.
You can also use this, which in my opinion feels more readable.
Route::get('/', 'HomeController#index')->before('auth');
You only need to use "as" and "uses" if you're in need of named routes, eg. for a Form route.