modify getRouteKeyName in Laravel 5.7 - laravel

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
}

Related

Laravel authorization policy not working on Show page

I have a laravel app using Policies to assign roles and permissions, i cant seem to access the show page and im not sure what im doing wrong?
If i set return true it still shows a 403 error as well, so im unsure where im going wrong here. The index page is accessable but the show page is not?
UserPolicy
public function viewAny(User $user)
{
if ($user->isSuperAdmin() || $user->hasPermissionTo(44, 'web')) {
return true;
}
return false;
}
public function view(User $user, User $model)
{
if ($user->isSuperAdmin() || $user->hasPermissionTo(44, 'web')) {
return true;
}
return false;
}
UserController
public function __construct()
{
$this->authorizeResource(User::class, 'user');
}
public function index()
{
$page_title = 'Users';
$page_description = 'User Profiles';
$users = User::all();
return view('pages.users.users.index', compact('page_title', 'page_description', 'users'));
}
public function create()
{
//
}
public function store(Request $request)
{
//
}
public function show($id)
{
$user = User::findOrFail($id);
$user_roles = $user->getRoleNames()->toArray();
return view('pages.users.users.show', compact('user', 'user_roles'));
}
Base on Authorize Resource and Resource Controller documentation.
You should run php artisan make:policy UserPolicy --model=User. This allows the policy to navigate within the model.
When you use the authorizeResource() function you should implement your condition in the middleware like:
// For Index
Route::get('/users', [UserController::class, 'index'])->middleware('can:viewAny,user');
// For View
Route::get('/users/{user}', [UserController::class, 'view'])->middleware('can:view,user');
or you can also use one policy for both view and index on your controller.
I had an issue with authorizeResource function.
I stuck on failed auth policy error:
This action is unauthorized.
The problem was that I named controller resource/request param with different name than its model class name.
F. ex. my model class name is Acknowledge , but I named param as timelineAcknowledge
Laravel writes in its documentation that
The authorizeResource method accepts the model's class name as its first argument, and the name of the route / request parameter that will contain the model's ID as its second argument
So the second argument had to be request parameter name.
// Here request param name is timelineAcknowledge
public function show(Acknowledge $timelineAcknowledge)
{
return $timelineAcknowledge->toArray();
}
// So I used this naming here also
public function __construct()
{
$this->authorizeResource(Acknowledge::class, 'timelineAcknowledge');
}
Solution was to name request param to the same name as its model class name.
Fixed code example
// I changed param name to the same as its model name
public function show(Acknowledge $acknowledge)
{
return $acknowledge->toArray();
}
// Changed here also
public function __construct()
{
$this->authorizeResource(Acknowledge::class, 'acknowledge');
}
I looked over Laravel policy auth code and I saw that the code actually expects the name to be as the model class name, but I couldn't find it anywhere mentioned in Laravel docs.
Of course in most of the cases request param name is the same as model class name, but I had a different case.
Hope it might help for someone.

Laravel Resource Routing not showing anything when directly call method

I am stuck in resource routing
when I enter url netbilling.test/customer it goes to customer index file but when I enter url netbilling.test/customer/index nothing is returned. Also guide me if I have to route different method than in resource what is the method for that.
here is my web.php,
Route::get('/dashboard', function () {
return view('dashboard/index');
});
Route::resource('/customer','CustomerController');
here is my customer controller :
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Customer;
use App\Package;
use Redirect,Response;
class CustomerController extends Controller
{
public function index()
{
$packages = Package::get();
$customers = Customer::orderBy('id', 'DESC')->get();
return view('customer/index', compact('customers','packages'));
}
public function create()
{
//
}
public function store(Request $request)
{
//
}
public function show($id)
{
//
}
public function edit($id)
{
//
}
public function update(Request $request, $id)
{
//
}
public function destroy($id)
{
}
}
Without custom route specification, this is how the index route maps to a Resource Controller, taken from Actions Handled By Resource Controller:
Verb
URI
Action
Route Name
GET
/photos
index
photos.index
So if you want URI /customer/index to work, then you need to specify this explicitly in your Controller:
use App\Http\Controllers\CustomerController;
Route::resource('customer', CustomerController::class);
Route::get('customer/index', [CustomerController::class, 'index'])->name(customer.index);

how to send id in route and controller in laravel localization

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'));
}

How to call model in Controller request $request

I have a query in my model, which I want to call in my controller (request $request). It's working fine when the controller parameter is controller($id). But how to pass it in $request controller.
teacher Model with Query:
class teacher extends Model
{
public static function teacher($id)
{
return DB::table('teachers')
->leftjoin('religions', 'teachers.religion_id', '=', 'religions.id')
->leftjoin('areas', 'teachers.area_id', '=', 'areas.id')
->select('teachers.*','religions.*','areas.*')
->where('teachers.id',$id)
->first();
}
Controller which calls this model perfectly fine passing direct id:
public function report1($id)
{
$teacher = Teacher::teacher($id);
return View('teachers.report1' ,compact('teacher'));
}
Controller where I want to call it:
public function printreports(Request $request)
{
$teachers = $request->get('select2');
return view('teachers.report1',compact('teachers'));
}
Note: select2 contains teacher ids where I want to run model query.
Supposing you are have an array of ids in your select2 request param, probably easiest way is to change query at teacher model as follows:
use Illuminate\Support\Arr;
class teacher extends Model
{
public static function teacher($id)
{
return DB::table('teachers')
->leftjoin('religions', 'teachers.religion_id', '=', 'religions.id')
->leftjoin('areas', 'teachers.area_id', '=', 'areas.id')
->select('teachers.*','religions.*','areas.*')
->whereIn('teachers.id', Arr::wrap($id))
->get();
}
}

how to use laravel Scope in a relationship?

I'm using laravel
I have two models
Product
class Product extends Model
{
public function productcategories(){
return $this->hasOne('App\Product\Productcategorie','CategoryID','ProductCategoryId');
}
}
and Productcategorie
class Productcategorie extends Model
{
protected $primaryKey = 'CategoryID';
public function product(){
return $this->belongsToMany('App\Product\Product','ProductCategoryId','CategoryID');
}
public function scopeCp($query,$id){
return $query->where('categoryparent_id', '=', $id);
}
}
The Product model has a scope Cpscope
and i have ProductController with function
function productCatgoryPaFilter(Request $request){
$categories= Categoryparent::with('categories')->get();
$id=$request->id;
return $product = Product::with('productcategories')->with('productoption.option')->orderBy('created_at','DESC')->get();
}
i want to get all products with categoryparent_id equal to passed parametre in scope
how can i do it?
If you want to filter data in relational model, use whereHas(). Though i have not tested, give it a try
Product::whereHas('productcategories', function ($query) use($id) {
$query->cp($id);
})
->orderBy('created_at','DESC')->get()

Resources