Laravel 5.8 isAdmin Gate? - laravel

I'm learning how to use the Gate and #can stuff
in my AuthServiceProvider I have
public function boot()
{
$this->registerPolicies();
$this->registerPostPolicies();
}
public function registerPostPolicies()
{
Gate::define('isAdmin', function($user) {
return $user->roles->where('title', 'like', '%' . 'Admin')->count();
});
}
and in my blade I have
...
#can('isAdmin')
<a aria-disabled="false" href="{{ route('admin.home')}}" target="_self" class="dropdown-item" role="menuitem" ><i class="fa fa-upload"></i> Admin Menu</a>
#endcan
...
For roles I have
| id | title |
+----+-------------+-
| 1 | Admin |
| 2 | User |
| 3 | Group Admin |
| 4 | Site Admin |
+----+-------------+-
Which is why the like %Admin query...
but what I am finding is that the gate doesn't seem to work.. it simply blocks everyone.. I want to enable the Admin menu for anyone with a role title that has Admin in it..
Any suggestions?

You should be using $user->roles() with brackets instead to indicate you are querying from database.
return $user->roles()->where('title', 'like', '%' . 'Admin')->count();
Without (), it has become Collection and you cannot use LIKE with where() when filtering a collection. Refer Collections - Laravel Docs

Related

No hint path defined for [mail]. in Laravel

I know this question is asked many times but I could not found the answer
I am using this method to sending email
Mail::send('dynamic_email_template',$data, function ($message) {
$message->from('sales#scoopscreamery.pk', 'Contact');
$message->to('hamzaqureshi401#gmail.com')->subject('Contact');
});
and getting this error No hint path defined for [mail].
the error cause is i am sending table in email using #component('mail::table') in dynamic blade view so then i tried to differernt technique of code but in this i am getting mail but without (user input) {{ $name }} , {{ $email }} , {{ $messae1 }} can any one help me
yo get input data in email
controller
$data = [
'name' => $request->name,
'email' => $request->email,
'message1' => $request->message1
];
Mail::to('hamzaqureshi401#gmail.com')->send(new \App\Mail\SendMail($data));
my model is
class SendMail extends Mailable
{
use Queueable, SerializesModels;
public $data;
public function __construct(array $data)
{
$this->data = $data;
}
public function build()
{
return $this->subject('Mail from Online Web Tutor')
->markdown('dynamic_email_template',['data'=>$this->data]);
}
and my dynamic blade is
<p>Hi, This is {{ $name }}</p>
<p>I have some query like {{ $email }}.</p>
<p>It would be appriciative, if you gone through this feedback {{ $message1 }}.</p>
#component('mail::table')
| Laravel | Table | Example |
| ------------- |:-------------:| --------:|
| Col 2 is | Centered | $10 |
| Col 3 is | Right-Aligned | $20 |
#endcomponent
the error cause is I am sending table in email using #component('mail::table') in dynamic blade view so then I tried to differernt technique of code but in this I am getting mail but without (user input) {{ $name }} , {{ $email }} , {{ $messae1 }} can any one help me yo get input data in email
There may be some error in mail or notification inside your vendor folder re-export the component using publish command
php artisan vendor:publish --tag=laravel-mail

laravel 6 calling post route to return to the same page for sorting table

I am trying to create a table which the user can sort
I created the following two routes
route::get('/manager', 'Manager\DeadlineController#index')->middleware(['auth', 'auth.manager'])->name('manager.index');
route::post('/manager/{name_id}', 'Manager\DeadlineController#sortByName')->middleware(['auth', 'auth.manager'])->name('manager.sortByName');
from my php artisan route:list
| | GET|HEAD | manager | manager.index | App\Http\Controllers\Manager\DeadlineController#index | web,auth,auth.manager |
| | POST | manager/{name_id} | manager.sortByName | App\Http\Controllers\Manager\DeadlineController#sortByName | web,auth,auth.manager |
and set up my controller as follows
public function index()
{
return view('deadline.index')
->with([
'modules' => Module::all(),
'name_id' => 0
]);
}
public function sortByName($name_id){
if($name_id == 0){
$sortedModule = Module::orderBy('name', 'DESC')->get();
}
else{
$sortedModule = Module::orderBy('name', 'ASC')->get();
}
return view('deadline.index')
->with([
'modules' => $sortedModule,
'name_id' => 1
]);
}
in my view i use the following link to sort
<th scope="col">NAME</th>
but when i use this link in my view I am somehow redirected to my GET route because i get the following error
The GET method is not supported for this route. Supported methods: POST.
What am I missing or doing wrong? Any help or tips will be appreciated. Please ask if I need to provide more details
Update
I change the link in my view to a form tag with a submit button and now it works
<th scope="col">
<form action="{{ route('manager.sortByName', $name_id) }}" method="POST">
#csrf
<button type="submit">NAAM</button>
</form>
</th>
When you click on <a> tag it does GET request, so you need to change your route from POST to GET, also returning view as a response to post method is not good idea,the best solution is GET route

display data from multiple tables and foreign keys in laravel

I have two tables :
bonhomme
+----+--------------+
| id | name |
+----+--------------+
| 1 | Alec Badwin |
| 2 | Maria Quiban |
+----+--------------+
serie
+----+---------------+
| id | name |
+----+---------------+
| 1 | 30 Rock |
| 2 | Good Day L.A. |
+----+---------------+
I have another one called : serie_personnage
+----+-------------+----------+--------------+
| id | bonhomme_id | serie_id | personnage |
+----+-------------+----------+--------------+
| 1 | 1 | 1 | Jack Donaghy |
| 2 | 2 | 2 | Maria Quiban |
+----+-------------+----------+--------------+
I want to display the personnage from serie_personnage and link it in my blade with the name of the bonhomme (in my table bonhomme) associated.
In other words, I want a table in my blade with rows where there is in column 1, the name of the bonhomme and in column 2, the personnage associated.
How can I do that with the relationships in Laravel ? I've tried it but it's not working well.
Controller
public function show($id)
{
$serie = Serie::where('id', $id)->first();
return view('admin.series.castings.show')->withSerie($serie);
}
Model - Serie
public function personnages()
{
return $this->hasMany('App\Models\Admin\SeriePersonnage');
}
public function acteurs()
{
return $this->belongsToMany('App\Models\Admin\Bonhomme', 'serie_personnage', 'serie_id', 'bonhomme_id');
}
Blade
<tbody>
#foreach($serie->acteurs as $acteur)
#foreach($serie->personnages as $personnage)
<tr>
<td>{{ $acteur->nom }}</td>
<td>{{ $personnage->personnage }}</td>
<td>bla</td>
<td>{{ $personnage->rang }}</td>
<td class="has-text-right">
<a class="button is-outlined" href="{{ route('series.show', $serie->id) }}">
Voir
</a>
<a class="button is-outlined" href="#">Editer</a>
</td>
</tr>
#endforeach
#endforeach
</tbody>
My Table in view
I have to help you as French developer as-well! First of all, I would change your controller for a more simple way to get the Serie :
public function show($id)
{
$serie = Serie::findOrFail($id);
return view('admin.series.castings.show')->withSerie($serie);
}
EDIT: I use Model::findOrFail($id); because it throws a Illuminate\Database\Eloquent\ModelNotFoundException. If you don't catch the exception, Laravel will automatically send a 404 HTTP response. It prevent the user to have an error using an obsolete link. See the doc for more informations.
Then I don't think it is a good idea to use foreach loop twice... I would rather use only one foreach loop on the personnages. Then, I would get the actor of the character from the Personnage model. It should looks like the code below:
App\Models\Admin\SeriePersonnage.php
<?php
namespace App\Models\Admin;
use App\Models\Admin\Bonhomme;
use Illuminate\Database\Eloquent\Model;
class SeriePersonnage extends Model
{
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
//Whatever you want to put here
];
/**
* Gets the actor of the character
*/
public function actor() {
return $this->belongsTo(Bonhomme::class);
}
}
Then in your blade view:
<tbody>
#foreach($serie->personnages as $personnage)
<tr>
<td>{{$personnage->actor->nom}}</td>
<td>{{$personnage->personnage}}</td>
<td>bla</td>
<td>{{$personnage->rang}}</td>
<td class="has-text-right"><a class="button is-outlined" href="{{route('series.show', $serie->id)}}">Voir</a> <a class="button is-outlined" href="#">Editer</a></td>
</tr>
#endforeach
</tbody>
You might also add a personnages() methods in your actor model so that you would be able to get all the characters this actor is playing.
Also I would advice you to use English words for variable names, class names and in fact every word in your code, especially if you post for help on English websites. I would also recommend you to change SeriePersonnage to only Personnage if you only manage series (you might also handle movies, Japanese Anime etc, in this case you can ignore my message). Also it would be great to change the row name of serie_personnage from personnage to nom.
Hope it helped you and I didn't do mistakes :P

How to check user is Admin or not in laravel blade view

I have
User table like
+==============+
| User |
+==============+
| id |
+--------------+
| firstname |
+--------------+
| lastname |
+--------------+
| email |
+--------------+
| password |
+--------------+
and my roles table
+==============+
| Roles |
+==============+
| id |
+--------------+
| name |
+--------------+
and my role_user table is
+=============+
| role_user |
+=============+
| user_id |
+-------------+
| role_id |
+-------------+
How can I check current logged user is admin or normal user?
You need to add roles relationship in your User model like so:
public function roles()
{
return $this->belongsToMany(App\Role::class);
}
and now you need to create isAdmin user like so:
public function isAdmin()
{
return in_array(1, $this->roles()->pluck('role_id')->all());
}
As 1 you put id of your admin role. Of course it could be also defined in other way, but everything depends on how this will be used.
It could be also defined this way:
public function isAdmin()
{
return $this->roles()->where('role_id', 1)->first();
}
and now in your Blade you can do:
#if (auth()->check())
#if (auth()->user()->isAdmin())
Hello Admin
#else
Hello standard user
#endif
#endif
It's not an ACL for this simple functionality you don't even need a database table roles you can add extra tinyInteger status column and add numbers for example:
0 = Disabled
1 = Visitor
2 = Admin.
To make it functional add following code to your User.php.
public function isDisabled ()
{
return $this->statusCheck();
}
public function isVisitor ()
{
return $this->statusCheck(1);
}
public function isAdmin ()
{
return $this->statusCheck(2);
}
protected function statusCheck ($status = 0)
{
return $this->status === $status ? true : false;
}
To check in blade template you can add
#if(Auth::user()->isDisabled())
You are not Active
#elseif(Auth::user()->isVisitor())
Welcome to example.com
#elseif(Auth::user()->isAdmin())
Welcome Admin
#endif
Moreover you can make blade custom directives, paste this code to your app/providers/AppServiceProvider.php in boot() method.
// Blade custom directives for isAdmin
Blade::directive('isAdmin', function() {
return "<?php if(Auth::user()->isAdmin()): ?>";
});
Blade::directive('endisAdmin', function() {
return "<?php endif; ?>";
});
// Blade custom directives for isVisitor
Blade::directive('isVisitor', function() {
return "<?php if(Auth::user()->isVisitor()): ?>";
});
Blade::directive('endisVisitor', function() {
return "<?php endif; ?>";
});
// Blade custom directives for isDisabled
Blade::directive('isDisabled', function() {
return "<?php if(Auth::user()->isDisabled()): ?>";
});
Blade::directive('endisDisabled', function() {
return "<?php endif; ?>";
});
To call this you use need to write following lines in your blade view
#isAdmin()
Welcome Admin
#endisAdmin
#isVisitor()
Welcome to example.com
#endisVisitor
#isDisabled()
Your are not active
#endisDisabled
In short laravel provides you a number of ways to solve a problem, it just depend on your need and application structure.
Role.php
use Illuminate\Database\Eloquent\Model;
class Role extends Model {
protected $fillable = [
'name'
];
/**
* A role can have many users.
*
* #return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function users() {
return $this->belongsToMany('App\User');
}
}
Then you can add this to User model:
public function isAdmin()
{
foreach ($this->roles()->get() as $role)
{
if ($role->name == 'Admin')
{
return true;
}
}
}
View
#if(Auth::check())
#if (Auth::user()->isAdmin())
<h2>Admin user enter code here<h2>
#endif
#endif
the methods shared works. the problem is if you have to check more than once per page, it hits the database that many times. for instance, let's say you have a navigation with 8 links. the first, fourth, and seventh links should only be visible by admin only. that query will hit your database 3x. maybe i'm just anal but it's a duplicated request.
i'm trying to find another way to store a variable that loads once in the view/template so that every time i need to check if it's an admin, i check the variable and not hit the database every time. i've done it via controller -> view, but not just view alone in a template. i'm thinking of creating a helper method and returning an object to be checked once per page load.
So you have some field isAdmin if it is 1 for example user is admin if not it is not. When user is loged check with (Auth::user()->isAdmin == 1) then user is admin else it is not
with Auth::user()-> u can check any field from user table of current logged user.
Best Regards

Laravel 5 Eloquent relationship get the data

I have two table.
(Persons)
+------+------+
| id | name |
+------+------+
| 1 | John |
+------+------+
| 2 |Albert|
+------+------+
(Motors)
+------+------+------+
| id | name | age |
+------+------+------+
| 1 | 1 | 20 |
+------+------+------+
| 2 | 2 | 21 |
+------+------+------+
| 3 | 1 | 20 |
+------+------+------+
In "motors.name" i have the ids of people.
I have two models.
(Motors)
class Motors extends Eloquent
{
public function person(){
return $this->hasMany('App\Persons', 'id');
}
}
(Persons)
class Persons extends Eloquent
{
protected $table = 'persons';
public function motors(){
return $this->belongsTo('App\Motors', 'name', 'id');
}
}
1 controller
class PrototypeController extends Controller
{
public function names(Request $request) {
$res = Motors::get()->person->name;
return view('pages.prototype', compact('res'));
}
}
1 view
<ul class="list">
#foreach ($res as $row)
#if (!empty($row->name))
<li class="list-group-item">
{!! $row->name !!}
</li>
#endif
#endforeach
</ul>
I'd like tosee the rerelational dara in view, not the ids. How can it be solved?
This code isn't good:
$res = Motors::get()->person->name;
Thanks in advance for your help.
Let me try to answer this. You should try to follow conventions to make it easier to work with Laravel.
Your motors.name column should be called person_id. Your model for motors table should be called Motor.php (singular of motors). The same for persons table, Person.php.
In your Motor.php file, your relationship will be:
public function person(){
return $this->belongsTo('App\Person');
}
If you follow conventions, you don't need to add the second parameter to the relationship name. Note that I put App\Person, you should have App\Persons if you decide to maintain the file naming you are using.
In your Person.php file, your relationship will be:
public function motors(){
return $this->hasMany('App\Motor');
}
Your foreach will be:
#foreach ($res as $row)
#if (!empty($row->person))
<li class="list-group-item">
{!! $row->person->name !!}
</li>
#endif
#endforeach
Note how I check:
#if (!empty($row->person))
and not:
#if (!empty($row->person->name))
It has to be done like this, because if $row->person is null, it will throw an error when you do $row->person->name

Resources