User.php
public function role()
{
return $this->belongsToMany('App\Models\Role','user_role','user_id','role_id');
}
//проверка принадлежит ли пользователь к какой либо роли
public function isEmloyee(){
$role=$this->role->toArray();
return !empty($role);
}
//проверка имеетли пользователь определению роли
public function hasRole($check){
return in_array($check,array_pluck($this->role->toArray(),'name'));
}
//получение идентификатора роли
private function getIdinArray($array,$term){
foreach ($array as $key => $value){
if ($value == $term){
return $key +1;
}
return false;
}
}
//добавление роли пользователя
public function makeEmployee($title){
$assiqned_role = array();
$role = array_pluck(Role::all()->toArray(),'name');
switch ($title){
case 'admin':
$assiqned_role[] = $this->getIdinArray($role,'admin');
case 'client':
$assiqned_role[] = $this->getIdinArray($role,'client');
break;
default:
$assiqned_roles[] = false;
}
$this->role()->attach($assiqned_role);
}
Role.php
class Role extends Model
{
public function users()
{
return $this->belongsToMany('App\Models\User','user_role','role_id');
}
}
OwnerMiddleware.php
<?php
namespace App\Http\Middleware;
use Closure;
class OwnerMiddleware
{
public function handle($request, Closure $next,$role)
{
if(!$request->user()->hasRole($role)) {
return redirect('/');
}
return $next($request);
}
}
You have role column in database. It preserves access to your role relation collection. You should delete it or rename role() relation for example to roles(). Moreover, belongsToMany implies that user can have many roles.
In addition, I want to note that the collection has its own methods in_array => contains, array_pluck => pluck. You could optimize your code like that:
public function roles()
{
return $this->belongsToMany(Role::class, 'user_role');
}
public function isEmloyee(){
return $this->roles->isNotEmpty();
}
public function hasRole($name){
return $this->roles->pluck('name')->contains($name);
}
public function makeEmployee($name){
$role = Role::where('name', $name)->first();
if($role){
$this->role()->attach($role->id);
}
}
Related
User.php
public function roles()
{
return $this->belongsToMany(Role::class)->withTimestamps();
}
public function hasRole($role)
{
if($this->roles()->where('name',$role)->first())
return true;
else
return false;
}
public function teams()
{
return $this->belongsToMany(Team::class)->withTimeStamps();
}
Team.php
public function users()
{
return $this->belongsToMany(User::class)->withTimeStamps();
}
Role.php
public function users()
{
return $this->belongsToMany(User::class)->withTimestamps();
}
Now i want to get all users that are not engaged with any teams and whose role is member
Take a look at this helper:
https://laravel.com/docs/5.8/eloquent-relationships#querying-relationship-absence
$users = User::doesntHave('teams')->get();
-- EDIT
$users = User::doesntHave('teams')->whereHas('roles', function($query) {
$query->where('name', 'member');
})->get();
I have a Category model which has belongsToMany relation with Product model via a pivot table called product_to_category
I can get all products in a Category with $category->products() and then apply a Filter scope to it to filter the result with parameters given in Request like this:
When I send this request :
http://site.dev/category/205?product&available&brand
I apply the parameters like this:
Category::find($id)->products()->filter($request)
The problem is when I want to get all product in a category and its children. The existing products relation gives me products in only given category.
I tried to modify the products() method in Category model as this:
public function products()
{
return DB::table('oc_product')
->join('oc_product_to_category', 'oc_product_to_category.category_id', '=', 'oc_product_to_category.category_id')
->join('oc_category_path', 'oc_category_path.category_id', '=', 'oc_category.category_id')
->whereIn('oc_product_to_category.category_id', $this->children(true));
}
But when I this code :
Category::find($id)->products()->filter($request)
I get this exception error:
(1/1) BadMethodCallException
Call to undefined method Illuminate\Database\Query\Builder::filter()
I know that filter scope is defined in Model class, but how can I apply that filter scope to QueryBuilder which is returned by modified products method?
Here are my classes :
Product model:
class Product extends Model {
public function scopeFilter( $request, QueryFilter $filters ) {
return $filters->apply( $request );
}
public function categories() {
return $this->belongsToMany( Category::class, 'product_to_category', 'product_id', 'category_id' );
}
}
Category model:
class Category extends Model
{
public function scopeFilter($query, QueryFilter $filters)
{
return $filters->apply($query);
}
public function children($id_only = false)
{
$ids = $this->hasMany(CategoryPath::class, 'path_id', 'category_id')
->join('category', 'category.category_id', '=', 'category_path.category_id')
->where('category.status', 1)
->pluck('category.category_id');
if ($id_only)
return $ids;
return self::find($ids);
}
public function parent()
{
$parent = DB::Select("SELECT cp.path_id AS category_id FROM category_path cp LEFT JOIN category_description cd1
ON (cp.path_id = cd1.category_id AND cp.category_id != cp.path_id)
WHERE cd1.language_id = '2' AND cp.category_id = " . $this->category_id);
return $parent;
}
public function products()
{
return $this->belongsToMany(Product::class, 'product_to_category', 'category_id', 'product_id');
}
}
QueryFilter class:
abstract class QueryFilter {
protected $request;
protected $builder;
public function __construct( Request $request ) {
$this->request = $request;
}
public function filters() {
return $this->request->all();
}
public function apply( Builder $builder ) {
$this->builder = $builder;
foreach ( $this->filters() as $name => $value) {
if (method_exists($this, $name)) {
call_user_func_array([$this, $name], array_filter([$value]));
}
}
return $this->builder;
}
}
CategoryFilter class:
class CategoryFilters extends QueryFilter
{
public function id($id)
{
return $this->builder->where('category_id', $id);
}
public function procons()
{
return $this->builder->with('pros', 'cons');
}
public function available()
{
return $this->builder->where('quantity', '>', 0);
}
public function optionValues()
{
return $this->builder->with('optionValues');
}
public function description()
{
return $this->builder->with('description');
}
public function images()
{
return $this->builder->with('images');
}
public function order($order)
{
$params = explode(',', $order);
$order = isset($params[0]) ? $params[0] : null;
$way = isset($params[1]) && strtolower($params[1]) == 'desc' ? $params[1] : 'asc';
if ($order) {
return $this->builder->orderBy($order, $way);
}
return $this->builder;
}
}
I have filters which belong to filter groups
Filter.php:
namespace App;
use Illuminate\Database\Eloquent\Model;
class Filter extends Model
{
public function group()
{
return $this->belongsTo('App\FilterGroup');
}
public function products()
{
return $this->belongsToMany('App\Product', 'product_filters');
}
public function categories()
{
return $this->belongsToMany('App\Filter', 'category_filter');
}
}
And categories which have many to many relationship with the filters
Category.php:
namespace App;
use App\Events\CategoryDelete;
use Illuminate\Database\Eloquent\Model;
class Category extends Model
{
protected $events = [
'deleting' => CategoryDelete::class
];
protected $table = 'categories';
public function parent()
{
return $this->belongsTo('App\Category', 'parent_id');
}
public function children()
{
return $this->hasMany('App\Category', 'parent_id');
}
public function parents()
{
$parentCategories = collect([]);
$parent = $this->parent;
while (!is_null($parent)) {
$parentCategories[] = $parent;
$parent = $parent->parent;
}
return $parentCategories->reverse();
}
public function products()
{
return $this->hasMany('App\Product');
}
public function filters()
{
return $this->belongsToMany('App\Filter', 'category_filter');
}
public function hasFilter($filter_id)
{
foreach ($this->filters as $filter) {
if ($filter->id == $filter_id) {
return true;
}
}
return false;
}
public function getFilterGroups()
{
$filterGroups = collect([]);
foreach ($this->filters as $filter) {
if (!$filterGroups->has($filter->group->id)) {
$filterGroups[$filter->group->id] = $filter->group;
}
}
return $filterGroups;
}
}
And in the category view I want to display the filters along with their filter group but when I try the following:
#foreach($category->filters as $filter)
{{ $filter->group->name }}
<br>
#endforeach
It throws the Trying to get property of non-object exception
Why can't I get the group of the filter?
I changed the group() method inside the Filter model to filterGroup and now when I call $filter->filterGroup it works fine. I dont know why, maybe group is some reserved word or something.
I need to associate some models with at least two other models in an app that I'm developing, but I can't do the association in the controllers.
Here's the code.
UserModel
public function prices() {
return $this->hasMany(PriceClass::class);
}
PriceModel
public function user() {
return $this->belogsTo(ClassOfTheUser::class);
}
public function price_lines() {
return $this->hasMany(PriceLinesClass::class);
}
AreaModel
public function price_lines() {
return $this->hasMany(PriceLineClass::class);
}
PriceLinesModel
public function area() {
return $this->belongsTo(AreaClass::class);
}
public function price() {
return $this->belongsTo(PriceClass::class);
}
How may I do the creation of the Price, if I can't do something like:
public function store(Request $request) {
if ($request->ajax()) {
$user = UserClass::findOfFail($request->input("user_id"));
$user->prices()->save(new PriceClass());
$price = $user->prices()->lastest()->first();
foreach($request->input("price_lines") as $price_line) {
$area = AreaClass::findOrFail($price_line["area_id"]);
$area->price_lines()->save(new PriceLineClass());
$price_line_instance = $area->price_lines()->lastest()->first();
$price->price_lines()->save($price_line_instance);
}
}
}
I have 3 models for managing user permissions.
class User extends Authenticatable
{
public function roles()
{
return $this->belongsToMany('App\Models\Role');
}
}
class Role extends Model
{
public function users()
{
return $this->belongsToMany('App\Models\User');
}
public function permissions()
{
return $this->belongsToMany('App\Models\Permission');
}
}
class Permission extends Model
{
public function roles()
{
return $this->belongsToMany('App\Models\Role');
}
public function roleHavePermission(Role $role)
{
if ($this->roles()->find($role->id)) {
return true;
}
return false;
}
public function userHavePermission(User $user = null)
{
$roles = [];
if (is_null($user)) {
$roles[] = Role::where('slug', 'guest')->first();
} else {
foreach ($user->roles as $role) {
$roles[] = $role;
}
}
foreach ($roles as $role) {
if ($this->roleHavePermission($role)) {
return true;
}
}
return false;
}
}
Now because my application is grown, I'm moving to repositories. For example this is my PermissionRepository:
class PermissionRepository implements PermissionRepositoryInterface
{
protected $roleRepository;
/**
* PermissionRepository constructor.
* #param RoleRepositoryInterface $roleRepository
*/
public function __construct(RoleRepositoryInterface $roleRepository)
{
$this->roleRepository = $roleRepository;
}
public function action($routeName)
{
return Permission::where('action', $routeName)->first();
}
}
How can I implement roleHavePermission and userHavePermission in this repository? I tried implementing roles method with this syntax:
public function roles()
{
return Permission::roles();
}
But it wont work since Permission's roles method can not called statically. Thanks.
In fact in my opinion you shouldn't implement it in repository. When you call
$permission = $permissionRepository->action('abc.name');
you are getting permission object, so there is no point to implement it in repository. All you need is running:
$roles = $permission->roles;
In theory you could add for example into PermissionRepository method like this:
public function getRoles(Permission $permission)
{
return $permission->roles;
}
so you could now run
$roles = $permissionRepository->getRoles($permission);
to get roles of given permission but I don't see any point to do it like this.