how to send id in route and controller in laravel localization - laravel

In my Laravel project with localization I made middleware, route group and all parameters, language switch work correct but when I click to send id by
I get the error:
Missing required parameters for [Route: products] [URI:
{lang}/products/{id}]
My Routes:
Route::group(['prefix' => '{lang}'], function () {
Route::get('/', 'AppController#index')->name('home');
Route::get('/categories', 'AppController#categories')->name('categories');
Route::get('products/{id}', 'AppController#products')->name('products');
Auth::routes();
});
My Middleware:
public function handle($request, Closure $next)
{
\App::setLocale($request->lang);
return $next($request);
}
My AppController:
public function products($id)
{
$products = Category::with('products')->where('id', $id)->get();
return view('products', compact('products'));
}
this is the URL:
http://127.0.0.1:8000/fa/products/1
if I change the above URL manually it works and shows the page:
http://127.0.0.1:8000/1/products/1
But if I click on:
I receive the error.

Since you added a route prefix the first parameter of the products method in your controller will be lang and the second one id.
This should fix the controller:
public function products($lang, $id)
{
$products = Category::with('products')->where('id', $id)->get();
return view('products', compact('products', 'lang'));
}

You need to use a key-value array in route('products', ['lang'=>app()->getLocale(), 'id'=>$category->id]) or whatever your route parameters are named in the original route.
Ref. Laravel Named Routes
PS. as Remul notes, since you have a lang param (as route prefix) the first param in your controller will be $lang then $id
public function products($lang, $id)
{
$products = Category::with('products')->where('id', $id)->get();
return view('products', compact('products'));
}

Related

Attempt to read property "title" on null - Laravel

when I enter the detail page in Laravel, it gives an error. I don't understand where the error is coming from. My codes are as follows.
where is the problem? actually it says it's empty, but it needs to pull data from $blog on controller side.
Controller:
public function show($id)
{
$blog = Blog::where('id',$id)->first();
return view('front.detail',compact('blog'));
}
routes/web.php:
Route::prefix('{lang?}')->middleware('locale')->group(function() {
Route::get('/', [MainController::class, 'index'])->name('home');
Route::get('/about', [MainController::class, 'about'])->name('about');
Route::resource('/blogs', MainController::class)->only([ 'show']);
});
detail.blade.php:
<li>
<h2>{{$blog->title}}</h2>
<p>{!! $blog->text !!}</p>
</li>
If you want to get a model by the main column you use find not where and the column:
public function show($id)
{
$blog = Blog::find($id);
return view('front.detail',compact('blog'));
}
Then, find can return the Model (hence an object) or null, so in your case it is not finding the model by ID.
What you should use is findOrFail so it throws an exception if it did not find the model:
public function show($id)
{
$blog = Blog::findOrFail($id);
return view('front.detail',compact('blog'));
}
Then you can continue debugging why it is not found
Doesn't appear you are passing the blog ID in with your URL:
Route::resource('/blogs', MainController::class)->only([ 'show']);
Try changing your route to this:
Route::resource('/blogs/{id}', MainController::class)->only([ 'show']);
Your URL should be something like (where 5 is the blog ID):
http://yourdomain.com/blogs/5
You could also use binding:
// Route
Route::get('/blogs/{blog}', [MainController::class, 'show']);
public function show(Blog $blog)
{
return view('front.detail', ['blog' => $blog]);
}
More info can be found here:
Route model binding

Auth::user() not defined in Laravel Route Group

I'm trying to get auth users data and use it for creating sub-domain.
I found, that I can get need data at single route, such:
Route::get('/', function ()
if (Auth::user()) {
return redirect()->route('home');
}
return view('user.login');
});
But I can't get data in group ruotes. Such I get null:
Route::group(['prefix' => 'dashboard'], function () {
$id = Auth::id();
Route::any($id.'/', 'myController#myAction')->name('some');
Route::get('/', function ()
if (Auth::user()) {
return redirect()->route('home');
}
return view('user.login');
});
It works cause the function is in the same position as a controller in the lifespan of the request. At that sequence, the AuthServiceProviderhas already finished booting.
In the second one, The callback function is part of the routing provider, wich is triggered before assigning the Auth::user().
What you should do, since it's a route for logged in user only, is to have it static
Route::group(['prefix' => 'dashboard'], function () {
$id = Auth::id();
Route::any('/', 'myController#myAction')->name('some');
or
Route::any('profile', 'myController#myAction')->name('some');
And in your controller, you can recover the id
MyConrtoller.php
public function myAction()
{
$id = \Auth::id();
}

modify getRouteKeyName in Laravel 5.7

I defined slug for single DB in a column of structure DB. When I will call the slug in route, Could I get slug from another model (e.g. structure here) in route?
The route is:
localhost:8000/api/singles/firstTest
I defined getRouteKeyName function in Single model:
public function structure()
{
return $this->belongsTo(Structure::class);
}
public function getRouteKeyName()
{
return $this->structure()->select('slug')->first();
}
In your controller you will get the firstTest as route param if you have specified route as :
Route::get('api/singles/{slug}', 'SomeController#someAction');
Then controller :
public function someAction(Request $request, $slug)
{
// Perform validations and policy authorization if required
$id = Single::whereHas('structure', function ($query) use($slug) {
$query->where('slug', '=', $slug);
})->first();
if(!$id){
abort(404);
}
// Process the data using $id obtained above
}

Laravel show() parameter are null

I am using Laravel version 5.6.26. My show() parameter get null value. Why? and how to solve it? Thank you
web.php
Route::get('/peoples', 'UsersController#index')->name('peoples');
Route::get('/peoples/{id?}', 'UsersController#show');
UserController.php
public function show(User $user)
{
$user = User::where('id', $user->id)->first();
//$user = User::find($user->id)->first();
return dd($user);
//return view('profile',['user' => $user]);
}
user.blade.php when I click <a href="/peoples/{{$user->id}}" > , it show null
<h4><a href="/peoples/{{$user->id}}" > {{$user->name}}</a></h4>
result
https://imgur.com/QlaiFse
But if i do like this,I can get the value
public function show(User $user)
{
$user = User::where('id',1)->first();
//$user = User::find($user->id)->first();
return dd($user);
//return view('profile',['user' => $user]);
}
The way you defined your show method i.e. show(User $user) is called route model binding if your variable name ($user) is similar to your route declaration. But your route declaration is /peoples/{id?} so the User instance is not created in your controller. So just rename the route declaration as /peoples/{user?}.
The use case of route model binding is you don't want to query/load the model related to a route parameter. So if you define the route the way I've mentioned you won't need the $user = User::where('id', $user->id)->first(); query. Because Laravel will automatically instantiate that $user with the User model of id passed in the route.
If you want to query/load the User model manually then keep your existing route declaration as it is. And change your controller method declaration as show($id = null)
You are injecting the User model in your controller, but not accessing the route path. If you want to access the {id} which set in the route, you have to access that in your controller too.
So your UserController will be something like
public function show(User $user, $id)
{
$user = User::where('id', $id)->first();
dd($user);
}
When you type hinted in your controller's method show() with User, Laravel will automatically inject that using Service Container.
Your UserController.php's code should be:
public function show(User $user) {
// no need to fetch user again. Laravel had already done that for you.
dd($user);
return view('profile', compact('user'));
}

How to use a dynamic variable in Laravel group routes?

for example:
Route::group(['prefix' => '{lang?}'], function () {
//..
});
create a variable in middleware:
public function handle($request, Closure $next){
$lang = session('locale');
App::setLocale($lang);
return $next($request);
});
also tried to get the data in the prefix, but got null
Route::group(['prefix' => config('app.locale')], function () {
//..
});
or
Route::group(['prefix' => session('locale')], function () {
//..
});
change language separate route through session
Route::get('setlocale/{locale}', function ($locale) {
session(['locale' => $locale]);
return redirect()->back();
})->name('setlocale');
Thank you in advance for your help.
You don't need to group your routes under a lang route, you can create your own middleware and group your routes under that middleware, and use this code inside of it:
public function handle($request, Closure $next){
$lang = request->get('locale');
$currentLang = App::getLocale();
//If locale exists in the url and it's changed
if($lang && $lang != $currentLang) App::setLocale($lang);
//If locale doesn't exist in the url, fallback to default locale
if(!$lang) App::setLocale('en');
return $next($request);
});
The url should be data/store?locale=en, ur url should always append locale after ? in the url, otherwise, your default locale will be used
EDIT: Since your routes include locale as a part of the url, and not as a request param, then I suggest you use a library to handle this for you, because you will have a lot of stuff to do before you will be able to have a working example: Laravel localization mcmara

Resources