i am just starting to learn laravel. And found a small sample project from nettuts+ ( url shortner ). it works well but only problem i face is that (:any) route doesn't work.
Here are three routes i have in file.
Route::get('/', function()
{
return View::make('home.index');
});
Route::post('/', function()
{
$url = Input::get('url');
// Validate the url
$v = Url::validate(array('url' => $url));
if ( $v !== true ) {
return Redirect::to('/')->with_errors($v->errors);
}
// If the url is already in the table, return it
$record = Url::where_url($url)->first();
if ( $record ) {
return View::make('home.result')
->with('shortened', $record->shortened);
}
// Otherwise, add a new row, and return the shortened url
$row = Url::create(array(
'url' => $url,
'shortened' => Url::get_unique_short_url()
));
// Create a results view, and present the short url to the user
if ( $row ) {
return View::make('home.result')->with('shortened', $row->shortened);
}
});
Route::get('(:any)', function($shortened)
{
// query the DB for the row with that short url
$row = Url::where_shortened($shortened)->first();
// if not found, redirect to home page
if ( is_null($row) ) return Redirect::to('/');
// Otherwise, fetch the URL, and redirect.
return Redirect::to($row->url);
});
first two routes work fine but third one never gets activated. it only works if i call it with index.php in url. Like /index.php/abc whereas it should work for /abc too. And fyi, i have removed index.php setting from application config file too.
Can you please help ho to fix it?
Change the route declaration from '(:any)'
Route::get('(:any)', function($shortened){ //... });
to ('/(:any)')
Route::get('/(:any)', function($shortened){ //... });
Related
I have a route something like this. The $slug is a variable that is matched to the slugs stored in the database to add the pages dynamically to the website.
#slug variable for different values of page slug....
Route::get('/{slug?}', array(
'as' => 'page',
'uses' => 'AbcController#renderPage'
));
However, now I wish to add an admin side of the website and want routes to be prefixed with media-manager.
My problem is, whenever I make a call to another route in the file, the above mentioned route takes the request call and calls the renderPage method every time, no matter wherever the request is coming from.
This is my middleware where I check for whether request is coming from a URL like 'media-manager/*', if so I don't want to check for the language of the website and redirect it to the media-manager's page.
private $openRoute = ['media-manager/login', 'media-manager/postLogin', 'media-manager/media'];
public function handle($request, Closure $next)
{
foreach ($this->openRoute as $route) {
if ($request->is($route)) {
return $next($request);
}
}
// Make sure current locale exists.
$lang = $request->segment(1);
if(!isValidLang($lang)) {
$lang = getDefaultLang();
$segments = $request->segments();
array_unshift($segments, $lang);
$newUrl = implode('/', $segments);
if (array_key_exists('QUERY_STRING', $_SERVER))
$newUrl .= '?'.$_SERVER['QUERY_STRING'];
return $this->redirector->to($newUrl);
}
setLang($lang);
return $next($request);
}
This is the renderPage method where every time the request is being redirected, no matter what.
public function renderPage($slug = '')
{
if ($slug == 'login') {
return view ('site.login');
}
$page = Page::getBySlug($slug);
if(empty($page)){
return URL::to ('/');
}
if($slug == ''){//home page
$testimonial = DB::table('testimonial')->where('lang','=',$this->lang)->get();
$client_logo = DB::table('client_logo')->get();
return View::make('index', compact('data','page', 'testimonial', 'client_logo'));
}elseif($slug == 'services'){
return View::make('services', compact('page'));
}elseif($slug == 'portfolio'){
$categories = PortfolioCategory::getAll();
$portfolio = Portfolio::getAll();
return View::make('portfolio', compact('page', 'categories', 'portfolio'));
}elseif($slug == 'oshara'){
return View::make('oshara', compact('page'));
}elseif($slug == 'blog'){
$limit = 8;
$pageNum = 1;
$offset = ($pageNum-1)*$limit;
$totalPosts = BlogPost::totalPosts();
$totalPages = ceil($totalPosts/$limit);
$posts = BlogPost::getAll($offset, $limit);
$blog_posts = View::make('partials.blog_posts', compact('posts','pageNum','totalPages'));
return View::make('blog', compact('page', 'blog_posts', 'pageNum', 'totalPages'));
}elseif($slug == 'contact'){
$budgets = Budget::getAll();
return View::make('contact', compact('page', 'budgets'));
}
}
This is postLogin method in the controller that I want to call after user clicks on Login button on login page.
public function postLogin($request) {
# code...
//$request = $this->request;
$this->validate($request, [
'email1' => 'required|email',
'password' => 'required|string'
]);
if($user = User::whereEmail($request->email1)->first() ) {
if(Hash::check($request['password'], $user->getAttributes()['password'])) {
if(!$user->getAttributes()['is_active']) {
return redirect('/media-manager/login')->withErrors('Your Account is not Activated Yet!');
} else if($user->getAttributes()['is_deleted']) {
return redirect('/media-manager/login')->withErrors('Your Account is Banned!');
} else {
# Success
$cookie = Cookie::make('user_id', $user->getAttributes()['id'], 864000);
//echo "hello";
return view('site.media')->with('message', 'You have Successfully Logged In!')->withCookie($cookie);
}
} else {
return redirect('/media-manager/login')->withErrors('Your Login Information is Wrong!');
}
} else {
return redirect('/media-manager/login')->withErrors('Your Login Information is Wrong!');
}
}
Can any one please suggest me some way so that I can disable renderPage method on every call and have my normal routing perform perfectly.
In Laravel the first matching route is used. So I would guess you have your slug route defined above the others (at least above the media-manager ones), right?
So a simple solution would be to just put the slug route definition at the end of your routing file.
Another approach would be utilize conditions for the route. For more information you can read this or leave a comment!
Hope that helps!
Hello I am trying to do it like this but it's getting all the routes, I only want the routes from a specific group(s).
This is my code:
<?php
$routes = Routes::getRoutes();
#foreach($routes as $route)
{{ $route->getPath() }}
#endforeach`
Thanks in advance!
Let's create some routes without any groups
Route::get('/', function () {
return view('welcome');
});
Route::get('/load', 'defaultController#load');
Now we'll create some routes with groups
Route::group(['as' => 'admin'], function () {
Route::get('users', function () {
return "users route";
});
Route::get('ravi', function () {
return "ravi route";
});
Now we are going to create a route in this group which will look for the admin group and print all routes that exist in this group.
Route::get('kumar', function () {
$name = 'admin';
$routeCollection = Route::getRoutes(); // RouteCollection object
$routes = $routeCollection->getRoutes(); // array of route objects
Now in our route object, we will look for our named route by filtering the array.
$grouped_routes = array_filter($routes, function($route) use ($name) {
$action = $route->getAction(); // getting route action
if (isset($action['as'])) {
// for the first level groups, $action['as']
// will be a string
// for nested groups, $action['as'] will be an array
if (is_array($action['as'])) {
return in_array($name, $action['as']);
} else {
return $action['as'] == $name;
}
}
return false;
});
// Here we will print the array containing the route objects in the 'admin' group
dd($grouped_routes);
});
});
Now you can copy and paste this in your route folder and you will be able to see the output by hitting your_project_public_folder_url/kumar
I took help from this answer Answer of patricus
I'm trying to create a language switcher, so that you can easily change language on the fly (without being redirected to the home page).
The thing I can't seem to accomplish is getting a url from a route name in a different locale.
Imagine your on mydomain.com/events (or mydomain.com/en/events since these are the same) and I want to get url in french (mydomain.com/fr/evenements)...
In my routes.php I have:
$locale = Request::segment(1);
if ( !array_key_exists($locale, Config::get('translatable.languages'))) {
$locale = null;
App::setlocale(Config::get('translatable.fallback_locale'));
}else{
App::setLocale($locale);
}
Route::group(array('prefix' => $locale), function(){
Route::get(Lang::get('routes.events'), array('as' => 'events.index', 'uses' => 'EventController#index'));
});
I have tried
setting the application locale right before calling the route($route_name) helper function
Setting a session variable with the requested locale (in this example 'fr'), then calling the route($route_name) function. For this I also added at the top of routes.php:
if( Session::has('requested_locale') ){
$locale = Session::pull('requested_locale');
}
I have no idea's left on how to handle this...
I know there is a package Laravel Localization that can do this, but I need it to work without that package (if possible)...
My solution on Laravel 5.1 was...
Defined locales in the config/app.php to create routes using the language files
'locale' => 'en',
'locales' => [
'en'=>'English',
'fr'=>'Français'
],
I've defined my routes in the resources/lang/ directory ('en/routes.php' and 'fr/routes.php' in my case)
return [
'about' => 'a-propos',
];
Defined routes using the language keys, example:
Route::get(trans('routes.about'), ['as' => 'about', function () {
return view('pages.'.App::getLocale().'.about');
}]);
Then I've created dummy route that would be used only for switching to another locale, ONLY after the current route has been matched to request
`
Route::matched(function($route) {
$route = Route::current();
$route_name = $route->getName();
$route_uri = $route->uri();
$locales = Config::get('app.locales');
foreach ($locales as $locale_code => $locale_name) {
if ($locale_code == App::getLocale()) {
continue;
}
if (Lang::has('routes.'.$route_name, $locale_code)) {
$route_uri = $locale_code . '/' . Lang::get('routes.'.$route_name, [], $locale_code);
}
else {
$route_uri = $locale_code . '/' . substr($route_uri, 3);
}
Route::get($route_uri, ['as' => 'change_locale_to_'.$locale_code, function(){
}]);
}
});
`
Finally, I use the dummy route in the view I want. $locale_toggle is a Locale eloquent Model that I'm setting in a Middleware for handling the language with a language code route prefix.
<a href="{{ route('change_locale_to_'.$locale_toggle->code, Route::current()->parameters()) }}" class="dropdown-toggle">
I have an route that looks as following:
Route::group(['prefix' => 'show' ], function() {
Route::get('{id}', function($id)
{
return View::make('show')->with('id' , $id);
});
});
When I enter URL etc test.com/show/343242 it returns what it should. But what I want it to redirect to that site. When I use Redirect::to('show/34324'); it simply just give me an blank screen. When I try to use return Redirect::route('show/34324'); it just give me that the route show/34324 don't exist. I have no idea how to proceed, have search around for 1 hour until now.
Hopefully someone can bring some light into this, thanks.
You should return your Redirect
return Redirect::to('show/34324');
To Redirect from a named route
Route::get('{id}', array('as'=>'route-name',function($id)
{
return View::make('show')->with('id' , $id);
}));
// ...
return Redirect::route('route-name',array(34324));
If I have two route groups (for simple prefixing of routes) is it possible to Route::bind per just that group?
When I do the following:
Route::group( array('prefix'=>'pre1'), function(){
Route::bind('items', function( $value, $route ){
$item = Item::find( $value );
if( !$item ) App::abort( 404 );
return $item;
})
Route::resource('items', .... );
})
Route::group( array('prefix'=>'pre2'), function(){
//put bind for users here...
Route::bind('items', function( $value, $route ){
$user_id = $route->parameter('users')->getAttribute('id');
$item = Item::where('id', $value)->whereUserId( $user_id );
if( !$item ) App::abort( 404 );
return $item;
})
Route::resource('users.items', ....)
})
The first bind to 'items' is overridden by the last one declared. I would rename the 'items' to something else, but nested Resource routes are auto generated by laravel.
Ie the first route is
/items/{items}
where the second is
/users/{users}/items/{items}
I would simply rename the end routes, but they make sense with regards to the resources being used from an admin having permissions on one resource and users on the other.
A couple of things. Firstly you dont need this code
Route::bind('items', function( $value, $route ){
$item = Item::find( $value );
if( !$item ) App::abort( 404 );
return $item;
})
You just need
Route::bind('items', 'Item')
It will automatically throw a 404 if it cant bind the Item model at runtime.
Secondly, you wont be able to do what you want (have two different bindings of the same name) - but there are two options.
Option 1 is just explicitly have all your routes defined in your routes file, and dont use Route::resource(). This article from Phil Sturgeon gives an excellent explanation of why you should just define each route manually.
The second Option is just to use the main Items route binding, but add a filter to the user items. Something like this:
Route::group( array('prefix'=>'pre2', 'before' => 'user.item'), function(){
Then define a filter which checks if the item belongs to the user
Route::filter('user.item', function($route, $request)
{
if ($route->parameter('item')->user_id !== Auth::user()->id)
{
App::abort(404);
}
});