Laravel Localized Routes - laravel

I want to create laravel(5.6) localized routs for example : mysite.com/about - mysite.com/fr/sur
Route -> Web.php
foreach (config('app.locales') as $locale){ //config('app.locales') = ['en','fr']
$pref = ($locale != 'fr') ? ['prefix'=>$locale,'middleware'=>'LanguageCheck'] : ['middleware'=>'LanguageCheck'];
Route::group($pref,function (){
Route::get('/','HomeController#index');
Route::get('/'.__('urlabout').'','HomeController#about');
});
}
Middleware -> LanguageCheck
public function handle($request, Closure $next)
{
if($request->segment(1)){
session(['locale'=>$request->segment(1)]);
app()->setLocale($request->segment(1));
}else{
session(['locale'=>'fr']);
app()->setLocale('fr');
}
return $next($request);
}
This way working on mysite.com/about, mysite.com/fr/about but when i try access mysite.com/fr/sur I'm getting the error that the page can not be found.
Any suggestion for localized routes without any package.
Thanks in advice.

If you do not necessarily transfer the localization via url, then the best solution is to transfer the localization using Headers Accept-Language. You can get headers in the middleware and display content from the controller depending on what you came up with

Related

Cookie read correctly in controllers but not in middleware - Laravel

I was trying to set a cookie to define a user-preferred language. I did that by having a link that leads to a helper controller :
/set-locale/{locale}
public function edit_locale($locale) {
$durata= 2628000; // "forever"
if (Cookie::has('locale')) {
Cookie::queue(Cookie::forget('locale')); // If locale cookie is already defined, delete it
}
Cookie::queue("locale", $locale, $durata); // Set the cookie to either "en", "fr" or "ar"
return redirect()->back();
}
I know this works correctly because if I do :
dd(Cookie::get('locale'));
It shows the correct locale chosen. So next step was to actually apply this chosen locale everywhere using a middleware, I named it "SetLocale" :
public function handle(Request $request, Closure $next)
{
if (Cookie::has('locale')) {
$locale = Cookie::get('locale'); // The cookie gotten here is all scrambled for some reason
} else {
// other logic for when cookie is not set (irrelevant for this question)
}
App::setLocale($locale);
return $next($request);
}
But if I execute
dd(Cookie::get('locale'));
here in the middleware, it reads the cookie all scrambled.
So my question is why is it doing that and how do I read the cookie correctly from here?
use this to get cookie from request :
\Crypt::decrypt(Cookie::get('locale'))
or use
\Crypt::decryptString(Cookie::get('locale'))
Okay, esmaill's answer didn't work for me (Got a "unserialize(): Error at offset 0 of 43 bytes" error) but it did help point me in the right direction to solve it.
All I did was add 'locale' to the $except attribute of the EncryptCookies middleware and reset the cookie and now it's read correctly.

Redirect to custom tool url in a laravel nova application

Laravel Version: 7
Nova Version: 3
PHP Version: 7.4
Database Driver & Version:
Operating System and Version: MacOS
Browser type and version: Chrome
Reproduction Repository: https://github.com/###/###
Description:
I am trying to redirect a user after checking for a condition in a middleware, I have tried to use
return redirect('/admin/paddle-subscription');
But it does not work, it just redirects the page and shows it right in the browser url but show a 404 error in the screen, it looks that as nova uses vue.js it is creating some kind of errors.
I have been reading some post in laracast https://laracasts.com/discuss/channels/nova/nova-resource-route-redirect and it is clearer to me that it requires a special way to redirect.
I have tried
return redirect()->action('\Laravel\Nova\Http\Controllers\RouterController#show', ['resource' => '/admin/paddle-subscription']);
And it does not work, how I am supposed to redirect properly?
Thanks
Detailed steps to reproduce the issue on a fresh Nova installation:
You can do this by creating the route in the backend first so that Laravel knows the page exists. Use Nova's RouterController#show action for the route like in your Laracast example and make sure to apply all the Nova middleware to it.
In app/Providers/NovaServiceProvider.php add a custom route to your routes() method:
protected function routes()
{
Nova::routes()
->withAuthenticationRoutes()
->withPasswordResetRoutes()
->register();
Route::domain(config('nova.domain', null))
->middleware(['web'])
->as('nova.')
->prefix(Nova::path())
->group(function () {
Route::get('/admin/paddle-subscription', [\Laravel\Nova\Http\Controllers\RouterController::class, 'show'])
->middleware(config('nova.middleware', []));
});
}
In your middleware you can now redirect to that route and the page will render properly:
public function handle(Request $request, Closure $next)
{
if ($foo === $bar) {
return new \Illuminate\Http\RedirectResponse('/admin/paddle-subscription');
}
return $next($request);
}
try this:
add in your nova action
public function handleRequest(\Laravel\Nova\Http\Requests\ActionRequest $request)
{
parent::handleRequest($request);
return Action::redirect('/admin/paddle-subscription');
}

Laravel : optional parameters in url in every page?

I need to have an optional parameter in every route in my app. (for example : sponsoring code)
Is there a way to check it on every page, without coding every possible route ?
In a classic website without framework we should make it like this :
if(isset($_GET['my_optional_parameter'])) { ... } (in a file included in every page)
Thanks in advance for your reply
Have a nice day
Frederic
Just basic steps. Do anything you want!
1. Create middleware
php artisan make:middleware SponsorMiddleware
2. In app/Http/Middleware/SponsorMiddleware.php
public function handle($request, Closure $next) {
if ($request -> query('sponsor_id')) {
//DO YOUR LOGIC HERE
}
return $next($request);
}
3. In app/Http/Kernel.php. Add to $middlewareGroups['web']
\App\Http\Middleware\SponsorMiddleware::class

Set Locale when using Auth::loginUsingId for phpunit

I have several languages in my Laravel 5.2 app. Each locale is stored in DB in th User Model. So, each time a user log, the locale must update.
Thing is in my Test, I use a lot Auth::loginUsingId, because I need to test function with differents user profiles.
So, I don't want to append to each of those calls with a App::setLocale(Auth::user->locale), nor extract it to a function.
Any Idea how should I do it???
What I did to address this problem is creating a middleware with
public function handle($request, Closure $next)
{
if ($user = Auth::user()) {
App::setLocale($user->locale);
}
return $next($request);
}
By handling all routes through this middleware, you can have the locale set automatically at each request.

Testing redirect links to external sites

I have a link on a page /my/example/page which links to a laravel route my.route.
Route
Route::group(['middleware' => ['auth']], function () {
Route::group(['middleware' => ['Some\Custom\Auth\Middleware:1']], function () {
Route::match(['GET', 'POST'], '/my/route/to/external/controller', 'exampleController#externalLink')->name('my.route');
}
}
Link on /my/example/page
Link
This route /my/route/to/external/controller points to this controller method externalLink in the exampleController controller, which returns the url for the href to use
public function externalLink()
{
return $this->redirect->away('www.externalsite.com');
}
My test is
$this->visit(/my/example/page)
->click('Link')
->assertRedirectedToRoute('my.route');
I constantly get the error
Symfony\Component\HttpKernel\Exception\NotFoundHttpException
when I use the click() testing method.
I can catch this using #expectedException but his doesn't help as I am expecting to see a different page.
I have also tried (not together);
->assertResponseStatus(200);
->seePageIs('www.externalsite.com');
->assertRedirect();
->followRedirects();
From browser inspection, when the url is clicked I get
http://www.example.com/my/route/to/external 302
http://www.externalsite.com 200
How can I functionally test the button being clicked and redirecting to an external site?
I am struggling with a similar problem right now, and I have just about given up on testing the endpoint directly. Opting for a solution like this...
Test that the link contains proper information in the view:
$this->visit('/my/example/page')
->seeElement('a', ['href' => route('my.route')]);
Moving the logic in the controller to something you can test directly. The Laravel\Socialite package has some interesting tests that might be helpful if you do this...
class ExternalLinkRedirect {
public function __construct($request){
$this->request = $request;
}
public function redirect()
{
return redirect()->away('exteranlsite.com');
}
}
Then test it directly
$route = route('my.route');
$request = \Illuminate\Http\Request::create($route);
$redirector = new ExternalLinkRedirect($request);
$response = $redirector->redirect();
$this->assertEquals('www.externalsite.com', $response->getTargetUrl());
A simple way is to use the get method instead of visit.
An example:
$this->get('/facebook')
->assertRedirectedTo('https://www.facebook.com/Les-Teachers-du-NET-516952535045054');

Resources