laravel: how to use multi 'can' in route? - php

laravel 5:8
I create roles,permissions,permission_role,role_user
And in AuthServiceProvider:
public function boot()
{
$this->registerPolicies();
$permissions = $this->getPermissions();
if ($permissions) {
foreach ($permissions as $permission) {
Gate::define($permission->name, function ($user) use ($permission) {
return $user->hasRole($permission->roles);
});
}
}
}
protected function getPermissions()
{
if (\Schema::hasTable('permissions')) {
return Permission::with('roles')->get();
}
return null;
}
I try use can in route:
$can = 'can:manage_global';
Route::get('/create', 'ProductController#create')->middleware($can)->name('panel.product.create');
it works.
But how can use multi can?
I try this:
$can = 'can:manage_global,manage_articles';
but it works only for manage_global not manage_articles.

$can = 'can:manage_global|manage_articles';
Try this with your desired condition, I applied | (OR) between both permissions conditions

Related

Call to a member function toArray() on integer

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

Slim3 right way to set errors and check is user logged in

I'm a new user of Slim framework, I've a simple Slim 3 application, with sign in and sign up validation. But I'm not really sure if this is the right/best way to set errors and check if user is logged in -In order to redirect it to his account if session user.id exists.
I used a middleware: AuthMiddleware which includes:
class AuthMiddleware
{
protected $container;
public function __construct($container)
{
$this->container = $container;
}
public function __invoke($request, $response, $next)
{
if (isset($_SESSION['user.id']) && !empty($_SESSION['user.id'])) {
return $response->withRedirect($this->container->router->pathFor('user.index'));
}
$twig = $this->container->view->getEnvironment();
if (isset($_SESSION['validation'])) {
$twig->addGlobal('errors', $_SESSION['validation']['errors']);
$twig->addGlobal('values', $_SESSION['validation']['values']);
unset($_SESSION['validation']);
}
if (isset($_SESSION['auth.signup.success'])) {
$twig->addGlobal('auth_signup_success', $_SESSION['auth.signup.success']);
unset($_SESSION['auth.signup.success']);
}
if (isset($_SESSION['auth.signin.failed'])) {
$twig->addGlobal('auth_signin_failed', $_SESSION['auth.signin.failed']);
unset($_SESSION['auth.signin.failed']);
}
$response = $next($request, $response);
return $response;
}
}
And I used Twig for my views.
Session validation assigned in the validator.php which includes:
class Validator
{
protected $errors = [];
protected $values = [];
public function validate($request, $rules)
{
foreach ($rules as $field => $rule) {
$this->values[$field] = $request->getParam($field);
try {
$rule->setName(ucfirst($field))->assert($request->getParam($field));
} catch (NestedValidationException $e) {
$this->errors[$field] = $e->getMessages()[0];
}
}
if ($this->failed()) {
$_SESSION['validation'] = [
'errors' => $this->errors,
'values' => $this->values,
];
}
return $this;
}
public function failed()
{
return !empty($this->errors);
}
}
Using Respect\Validation. Also, is this the right use of Middlewares?
Thanks in advance.
try creating a separate file for the methods, and calling it from the middleware:
<?php
class AuthMiddleware extends Middleware {
public function __invoke($request, $response, $next) {
if (!$this->container->auth->check()) {
$this->container->flash->addMessage('danger', 'Please sign in to continue.');
return $response->withRedirect($this->container->router->pathFor('auth.signin'));
}
$response = $next($request, $response);
return $response;
}
}
while the Auth class would have those methods to check:
<?php
public function check () {
return isset($_SESSION['user']);
}
public function user() {
if (isset($_SESSION['user'])) {
return User::find($_SESSION['user'])->first();
} else {
return false;
}
}
Don't forget to include the Auth Class within your $app:
<?php
$container['auth'] = function ($container) {
return new \App\Auth\Auth();
};

Can't use function from Model at Mail - laravel 5.1

I have this code which store offer and maxoffer but I can't use it into my Mail function:
public function store(Requests\OfferRequest $request)
{
$offer = new Offer($request->all());
Auth::user()->offer()->save($offer);
$maxoffer = Maxoffer::where('article_id', $request->input('article_id'))
->where('start', Carbon::createFromFormat('m/d/Y h:i a', $request->input('start')))
->first();
//dd($maxoffer);
if($maxoffer == null)
{
Auth::user()->maxoffer()->create($request->all());
}
else
{
if($maxoffer->price < $request->input('price'))
{
$key = '';
$newOffer = Maxoffer::where('id', $maxoffer->id)
->update(['price'=>$request->input('price'),'user_id'=>Auth::user()->id, 'key'=>$key, 'provera'=>$request->input('provera')]);
}
}
Alert::success('Keep looking for best rates. Good luck...', 'Thanks for bidding!')->persistent("Close");
$user = Auth::user();
Mail::send('emails.newoffer', compact('user', 'maxoffer'), function ($m) use ($user) {
$m->from('info#sss.com', $maxoffer->article()->hname);
$m->to($user->email, $user->name)->subject('Someone have the bigger offer than you');
});
return Redirect::back();
}
so In Maxoffer controller I have:
public function user(){
return $this->belongsTo('App\User');
}
public function article(){
return $this->belongsTo('App\Article');
}
but in Mail function I cant use it. WHY?
Why $maxoffer->article()->hname inside Mail:: is a problem...
laravel error:
i get errors: ErrorException in 22b7e7ff4b942f1d8fa25f9b1c9a1748 line 6: Undefined property: Illuminate\Database\Eloquent\Relations\BelongsTo::$hname (View: /var/www/html/resources/views/emails/newoffer.blade.php)
Pass $maxoffer to the closure. like this use($user, $maxoffer)
Mail::send('emails.newoffer', compact('user', 'maxoffer'), function ($m) use ($user, $maxoffer) {
$m->from('info#sss.com', $maxoffer->article()->hname);
$m->to($user->email, $user->name)->subject('Someone have the bigger offer than you');
});

Passing an array in the construct of a controller with laravel

I am wanting to find out how I can pass in roles as an array because when I try to do this in my construct of my controller it always seems to only be Administrator.
The following is my app/controllers/UserscController.php
class UsersController extends BaseController {
public function __construct()
{
parent::__construct();
$this->beforeFilter('role:Administrator,Owner');
}
}
The following is my app/filters.php
Route::filter('role', function($route, $request, $roles)
{
if(Auth::guest() !== true)
{
if(!empty($roles))
{
$roles = explode(',', $roles);
if(count($roles) > 0)
{
foreach($roles as $role)
{
if (Auth::user()->role->role_name == $role)
{
return;
}
}
}
}
return Redirect::to('/youshallnotpass');
}
});
You can set the roles as a parameter in your controller. To load the roles into your filter you would do this:
Route::filter('role', function($route, $request)
{
if(Auth::guest() !== true)
{
$roles = $route->parameter('roles');
if(!empty($roles))
{
foreach($roles as $role)
{
if (Auth::user()->role->role_name == $role)
{
return;
}
}
}
return Redirect::to('/youshallnotpass');
}
});
Note:
Before laraval 4.1 you would use: $roles = $route->getParameter('roles'); instead of $roles = $route->parameter('roles');
Hope this helps!
Laravel already explodes your filter parameters on the comma, to allow passing multiple parameters to a filter. So, in your case, you've actually passed two parameters to your filter: the first parameter has the value 'Administrator', and the second parameter has the value 'Owner'.
So, two quick options are:
Change the delimiter you're using in your string. In your controller: $this->beforeFilter('role:Administrator;Owner'); and then in your filter: $roles = explode(';', $roles);
Or, leave your controller code alone and use PHP's func_get_args() function in your filter:
Route::filter('role', function($route, $request)
{
if(Auth::guest() !== true)
{
$roles = array_slice(func_get_args(), 2);
foreach($roles as $role)
{
if (Auth::user()->role->role_name == $role)
{
return;
}
}
return Redirect::to('/youshallnotpass');
}
});

In Laravel how can I replace a controller/method/id with just /slug in the URL?

What is the best way I could replace /controller/method/id in the URL with just /slug?
For example: trips/1 would become /honduras-trip
This is what I am doing but couldn't their be a better way?
My routes:
Route::get('/{slug}', 'HomeController#show');
My Controller:
public function show($slug)
{
$class = Slug::where('name', '=', $slug)->firstOrFail();
if($class->slugable_type == 'Trip')
{
$trip = Trip::find($class->slugable_id);
return $trip;
}
if($class->slugable_type == 'Project')
{
$project = Project::find($class->slugable_id);
return $project;
}
if($class->slugable_type == 'User')
{
$user = User::find($class->slugable_id);
return $user;
}
}
My Slug Model:
class Slug extends Eloquent {
public function slugable()
{
return $this->morphTo();
}
}
The other models all have this method:
public function slugs()
{
return $this->morphMany('Slug', 'slugable');
}
In your routes.php just give
Route::get('slug', array('uses' => 'HomeController#show'));
In your controller, write show() function
public function show() {
return View::make('welcome');
}
In your view give,
<li>slug</li>

Categories