Generating language changing urls in laravel - php

I have decided to prefix all my routes with a $locale-variable. This is code found from googling:
$locale = Request::segment(1);
if (in_array($locale, Config::get('app.available_locales'))) {
App::setLocale($locale);
} else {
$locale = null;
}
Route::group(array('prefix' => $locale), function() {
//All my routes
});
Now, I would like to generate URL:s dynamically for jumping between locales. I want a way to generate the current url or route, but replace the $locale-parameter. You should be able to write something similar to this pseudocode:
route(Route::Current(), [$locale => 'foo'])
Question:
I want to take my current URL and replace one argument in it. How do I do that?
Update 1:
Giving my route a name, I'm able to do this:
route('index', 'foo') //Gives mywebsite.com?foo
This however, does not produce the wanted result, mywebsite.com/foo. It instead generates mywebsite.com?foo. My guess is that route doesn't understand that this route is nested and prefixed with a fragment, so it treats my argument as a parameter instead. Specifying that it is the locale I want to change does not help:
route('index', ['locale' => 'foo']) //Gives mywebsite.com?locale=foo
Update 2:
Changing the prefix to instead say:
Route::group(array('prefix' => '{locale?}'), function() {
Makes route() work:
route('index', ['locale' => 'foo']) //Gives mywebsite.com/foo
It does however ruin some url:s inside the group, as some of them start with variables. The following route inside the route-group stops working:
Route::get('/{id}', 'FooController#showFoo');
As routes.php interprets the url mywebsite.com/foo as 'foo' now being the language. If there is some way to set a default value in routes.php for locale so that you could write it as {route} instead of {route?} and have it redirect to a default locale if it was missing, the problem would be solved.
Update 3:
Moving in the direction of having 'prefix' => '{locale?}' instead leads into way too many sub-problems to be worth pursuing. The issue comes back to generating urls from the current url but inserting language into the url. I am currently considering doing this with just a regex replacement because it is the most straight-forward solution.

I didn't test this, but you could try to do it like this way.
If no parameter is given, you can easily redirect to the default locale route. If first parameter is given, you need to check if it's a correct locale.
use Illuminate\Support\Facades\Request;
$defaultLocale = 'en';
Route::get('/', function() use ($defaultLocale) {
return redirect('/' . $defaultLocale);
});
Route::group(array('prefix' => '{locale}'), function($locale) use ($defaultLocale) {
if(!in_array($locale, Config::get('app.available_locales'))) {
return redirect('/' . $defaultLocale . '/' . Request::path());
}
// All your routes
});

So I ended up not solving this with laravel magic, I wrote my own code.
The Route::Group remains the same, the code I use to create URL:s to different languages looks like this:
<a href="{{ change_locale_url('en') }}"</a>
The change_locale_url-function is just a regex function which uses URL::Current to get the current url and then either inserts or replaces the input string as a language parameter in the url.
When I'm on mywebsite.com/about, the function outputs mywebsite.com/en/about
When I'm on www.mywebsite.com/de/about, the function outputs www.mywebsite.com/en/about
When I'm on http://mywebsite.com, the function outputs http://mywebsite.com/en
As a reminder, when using this route group you need to create links using action('HomeController#index') to have the locale follow you to the next link. Linking to /about will remove any language currently selected.

Related

Redirecting with a query string in Laravel

At some point in the past, my company changed our search tool and with it the format of the search query in the url.
It used to be a typical query parameter:
/product-name-some-digits-12345?q=searchterm
But now it's sent as a fragment:
/product-name-some-digits-12345##search:query=searchterm
We have a small number of visits to pages in the old format - either links out there in the ether, or users searching before the JS which powers the search has loaded. To mitigate this, I'd like to write a route to redirect from the old format to the new.
I thought I could do this by adding something like the below to the route file web.php:
Route::get('{base}?q={query}', function ($base, $query) {
// output for now, write redirect later
dd($base . '#search:query=' . $query);
})->where([
'base' => '[^\?]?',
'query' => '.*',
]);
But the route just isn't being hit.
How can I write a Laravel route to act when a query string is present?
I don't know how Laravel would translate that Route, but I'm also not surprised that the Route wouldn't be accessible. To debug your available routes, you can use this Artisan command:
php artisan route:list
Typically, you don't define Query String parameters directly in the Route like ?q={query}, since you really don't have to; Query Strings are implicit; they can be present on any route, but aren't required.
If you change the route to a simple Route::get('{base}'), and add a check for $request->has('q'), you should be able to handle the redirect:
Route::get('{base}', function ($base) {
if (request()->has('q')) {
return redirect()->url($base . '#search:query=' . request()->input('q'));
}
// ...
});
request() is available app-wide and can be used to check for Query String or Body/Post Parameters. The alternative is to use Injection, like:
Route::get('{base}', function (Request $request, $base){ ... });
Then use $request->has() and $request->input(), but they are syntactically the same.
Another approach would be to wrap your routes with a Middleware that checks the same thing. Syntax would be similar, in that you check for the presence of ?q=whatever via $request->has('q'), and redirect or continue as required. Documentation for that can be found here:
https://laravel.com/docs/9.x/middleware

Laravel 5 redirect to path with parameters (not route name)

I've been reading everywhere but couldn't find a way to redirect and include parameters in the redirection.
This method is for flash messages only so I can't use this.
return redirect('user/login')->with('message', 'Login Failed');
This method is only for routes with aliases my routes.php doesn't currently use an alias.
return redirect()->route('profile', [1]);
Question 1
Is there a way to use the path without defining the route aliases?
return redirect('schools/edit', compact($id));
When I use this approach I get this error
InvalidArgumentException with message 'The HTTP status code "0" is not valid.'
I have this under my routes:
Route::get('schools/edit/{id}', 'SchoolController#edit');
Edit
Based on the documentation the 2nd parameter is used for http status code which is why I'm getting the error above. I thought it worked like the URL facade wherein URL::to('schools/edit', [$school->id]) works fine.
Question 2
What is the best way to approach this (without using route aliases)? Should I redirect to Controller action instead? Personally I don't like this approach seems too long for me.
I also don't like using aliases because I've already used paths in my entire application and I'm concerned it might affect the existing paths if I add an alias? No?
redirect("schools/edit/$id");
or (if you prefer)
redirect("schools/edit/{$id}");
Just build the path needed.
'Naming' routes isn't going to change any URI's. It will allow you to internally reference a route via its name as opposed to having to use paths everywhere.
Did you watch the class Illuminate\Routing\Redirector?
You can use:
public function route($route, $parameters = [], $status = 302, $headers = [])
It depends on the route you created. If you create in your app\Http\Routes.php like this:
get('schools/edit/{id}', 'SchoolController#edit');
then you can create the route by:
redirect()->action('SchoolController#edit', compact('id'));
If you want to use the route() method you need to name your route:
get('schools/edit/{id}', ['as' => 'schools.edit', 'uses' => 'SchoolController#edit']);
// based on CRUD it would be:
get('schools/{id}/edit', ['as' => 'schools.edit', 'uses' => 'SchoolController#edit']);
This is pretty basic.
PS. If your schools controller is a resource (CRUD) based you can create a resource() and it will create the basic routes:
Route::resource('schools', 'SchoolController');
// or
$router->resource('schools', 'SchoolController');
PS. Don't forget to watch in artisan the routes you created

Laravel - Change base URL globally?

Let assume, the base URL of my application is - http://www.example.com (I have not set anything in any config file to specify this). There are a lot of hard coded urls in the application.
eg. Contact
Now, if I go though the application using an URL like - http://www.example.com/country, is it possible to assign a global base URL, where when I click on contact it will take me to - http://www.example.com/country/contact.
There are a lot of such hard-coded URL, changing it individually will take a lot of time (like appending it with a global variable). Is there any simpler way to do this or is there any config specific for this in laravel? I am fairly new to laravel. Any help would be appreciated.
You can use the somewhat cumbersome solution of applying a filter, as suggested by #worldask, but I think it would be better to set a named route and change all occurrences using a regular expression (any decent editor allows for that). That way, for the lifetime of your application you only need to change the routes in routes.php, and it will be reflected everywhere.
e.g
Route::get('country/contact', ['as' => 'contact',
'uses' => 'SomeController#someFn'];
Contact
Of course, the same principle applies to adding a prefixed group of routes, so you can wrap the entire routes file with a group prefixed by 'country'.
you can try Route Prefixing
Route::group(array('prefix' => 'country'), function(){
Route::get('Contact', 'HomeController#index');
Route::get('another', 'HomeController#index');
});
edit
try route filter
Route::filter('filtername', function($route, $request, $value)
{
if ($route == 'country') {
return Redirect::to(url);
}
});

Laravel routing: static text in optional url segment

I'm migrating the forum section of my website to Laravel 4. I manage the pagination myself. (Not the Laravel built-in one)
My urls currently use the following format:
example.com/forum
example.com/forum/page-1
I'd like to keep it like that after the migration.
My route looks like that:
Route::get('/forum/page-{page?}',
array('uses' => 'ForumController#showForum', 'as' => 'forum'));
But of course it doesn't work when I request the page without a page number.
I can do it like /forum/{pagetext?}-{page?} but I dont want to have to catch the pagetext parameter in my Controller, and I want to only give the $page parameter when I build urls for the page with URL::route().
I've found many examples on Internet but it was always with multiple parameters, no static optional text.
How can I make this "static" portion optional as well ?
I'm thinking to something like an optional group in a regular expression, like /forum/(page-{page})? but how do I do that in Laravel ?
If you truly need the parameter to be optional, I would make the whole segment of that route a single parameter, and you can use a regular expression to enforce it:
Route::get('/forum/{page?}', function($page = null) {
echo 'On page ' . $page;
})->where('page', 'page-[\d]+');
The drawback here is you'll have to get the numeric page number from within your route.
As #Jarek mentioned in the comments, you can also split this up into two different routes:
Route::get('/forum', function() {
echo 'Forum Index';
});
Route::get('/forum/page-{page}', function($page) {
echo 'On page ' . $page;
})->where('page', '[\d]+');

Generating url relative to the base url in laravel 4

I'm new to Laravel & right now building one application on L-4 but got stuck at one place. Can't able to understand how to generate url relative to base url. In laravel-3 i know this can be done by
$url = URL::to('user/profile');
But, in L-4 how we can do this.. ?
To generate a relative URL, you can use URL::route or URL::action as they allow to pass a $absolute parameter which defaults to true. So to get a relative URL when using named routes for example, you can use the following:
URL::route('foobar', array(), false)
This will generate a URL like /foobar.
First you need to create a Named Route like
Say yo want to go to http://baseurl/user and runs the method 'showuser' define in controller 'allusers'
then your Route shold look like this:-
Route::get('user', array('as' => 'myuser', 'uses' => 'allusers#showuser'));
Now your URL to /user would be
$myuserurl = URL::to('/myuser');
echo $myuserurl; // would be http://baseurl/user
I hope this helps you. Pls refer http://laravel.com/docs/routing#named-routes

Categories