Laravel show data - php

I'm new with Laravel or any MVC.
I created the models, I create the route from web.php, I created the view with Blade, I created the controller and fetched all the data from a single model. Now, I want to make a join or something similar.
I want to get something this:
Name | Section name | Status.
In my user Model I have:
ID | Name | SectionID | Status
In my sections Model I have:
ID | SectionID | Active
Currently I created the controller like this:
public function show($name)
{
if(User::where('name', '=', $name)->exists())
{
return view('profile', ['user'=>User::where('name', $name)->first()]);
}
else
{
return 'User not found';
}
}
And in my Blade I'm getting content like this: {{ $user->name }}

Hmm you have to define the relationship between user and section model.
Please check this thread for how to work with relationships in laravel Laravel Eloquent Relationships.
Then whenever you get the user you can load any relationship that its defined on User model.
In your case you are performing two unecessary database calls, so I would suggest you to check out DRY principle.
Lets say in User has one Section you define the relationship in User model like so:
public function sections(){
return $this->hasOne(Section::class);
}
Then the reverse relationship from section model:
public function user(){
return $this->belongsTo(User::class);
}
So now your method in controller might look something along the lines of this:
public function show($name){
return view('profile', ['user'=>User::with('sections')->where('name', $name)->firstOrFail()]);
}
This way you eagerload the sections that are tied to that user, for more about Laravel eagerloading
Then in the blade you can access any of the attributes from user or section model.

Related

Laravel 8 - relationship return null

I have one more relationship in the project like this it works but this is not working. I can't see any value on the screen. It return null. I'm not good with Laravel and relationships in database. I think my controller and routes are correct but my relationships are incorrent.
My User model contains the following relationship:
public function follows(){
return $this->hasMany('App\Models\Follow');
}
My Follow model contains the following relationship:
public function user(){
return $this->belongsTo('App\Models\User');
}
My blade is:
#foreach ($user->follows as $followr)
<h6><strong>{{$followr}}</strong></h6>
#endforeach
please refer laravel eloquent documentation here
you can pass foreign key and local key as 2nd and 3rd arguement in hasMany function and pass foreign key and owner key as 2nd and 3rd arguement in belongsTo function

Laravel 5.8 - Fetching models using getRouteKeyName() slug not working

For reference I used this post and Laravel documentation:
Laravel 5.6 getRouteKeyName() not working
https://laravel.com/docs/5.8/routing#explicit-binding
In my routes I have a resources array like this:
Route::resources([
...
'state' => 'StateController',
...
]);
In my controller I am trying to access models by the slug. My state table and model has name and slug columns.
StateController
public function show(State $state)
{
dd($state);
// return view('state.show', compact('state'));
}
public function getRouteKeyName()
{
return 'slug';
}
If I remove the State model typecast it prints out the string indiana for the url: http://codebase.localhost.com/state/indiana But when I put the typecast back in, it gives me a 404. It can't find the model.
I thought getRouteKeyName was supposed to retrieve the model by the string passed.
What gives?
Here are my models fillables
'name', 'order', 'slug'
It's definitely a record in my table.
Looks like the issue is with the getRouteKeyName method being defined in your controller.
From the docs:
you may override the getRouteKeyName method on the Eloquent model
Try moving the getRouteKeyName method into your State model.

Final Route URL Change Laravel 5.5

I am working on a school project. while working on a schools detail page I am facing an issue with the URL. My client needs a clean URL to run AdWords. My school detail page URL: http://edlooker.com/schools/detail/4/Shiksha-Juniors-Ganapathy. But he needs it like http://edlooker.com/Shiksha-Juniors-Ganapathy. If anyone helps me out it will be helpful, thanks in advance.
You need to define this route after all routes in your web.php (if laravel 5.x) or in routes.php (if it is laravel 4.2).
Route::get('{school}','YourController#getIndex');
And your controller should be having getIndex method like this,
public function getIndex($school_name)
{
print_r($school_name);die; // This is just to print on page,
//otherwise you can write your logic or code to fetch school data and pass the data array to view from here.
}
This way, you don't need to use the database to get URL based on the URL segment and you can directly check for the school name in the database and after fetching the data from DB, you can pass it to the school details view. And it will serve your purpose.
Check Route Model Binding section in docs.
Customizing The Key Name
If you would like model binding to use a database column other than id when retrieving a given model class, you may override the getRouteKeyName method on the Eloquent model:
/**
* Get the route key for the model.
*
* #return string
*/
public function getRouteKeyName()
{
return 'slug';
}
In this case, you will have to use one front controller for all requests and get data by slugs, for example:
public function show($slug)
{
$page = Page::where('slug', $slug)->first();
....
}
Your route could look like this:
Route::get('{slug}', 'FrontController#show');

Laratrust : Users and Roles Usage

I'm a Laravel user. I am currently trying to use the Laratrust package for web admin purposes. For User and Role implementations I want one user to hold multiple roles and one role many users can have. In my opinion, the most suitable relationship is Many to Many Relationship, am I correct? Then, is the function I made right?
App\User;
public function roles()
{
return $this->belongsToMany('App\Role');
}
App\Role;
public function users()
{
return $this->belongsToMany('App\User');
}
Then how do I display the two interconnected data in one blade file? Thanks.
Define relations as users() and roles(). You can display all roles of the user with something like this:
#foreach ($user->roles as $role)
{{ $role->name }}
#endforeach

Laravel 5.1 users, roles and actions

I am creating an application using Laravel 5.1 with users, roles and actions.
The table setup is like so:
user
id name
1 John Smith
2 Fred Smith
role
id name
1 Administrator
2 Customer
role_user
user_id role_id
1 1
2 1
action
id name description path
1 dashboard ability to access dashboard /admin
2 editAdmin ability to edit admins /admin/users/administrators/{id}/edit
action_role
action_id role_id
1 1
2 1
The user table holds ALL users on the site, including administrators and customers.
The role table holds all the possible roles a user can have. For example Administrator or Customer.
The role_user table is a pivot table which links role to user.
The action table lists all of the actions possible (i.e. urls or routes) on the app.
The action_role is a pivot table which links action to role.
So to summarise:
Users have roles
Roles have actions
A user can have many roles
A role can have many actions
I want to have a middleware setup which checks on page load if the user has permissions to view the current page. In order to do this, I need to be able to access a users actions, using a call like this:
$user->roles()->actions();
How do I setup my eloquent relationships to support this kind of call?
UPDATE
My relationships are setup like so in my models:
User
/**
* The roles that belong to the user.
*
* #return Object
*/
public function roles()
{
return $this->belongsToMany('App\Models\User\Role')->withTimestamps();
}
Role
/**
* The actions that belong to the role.
*
* #return Object
*/
public function actions()
{
return $this->belongsToMany('App\Models\User\Action');
}
/**
* The users that belong to the role.
*
* #return Object
*/
public function users()
{
return $this->belongsToMany('App\Models\User\User');
}
Action
/**
* The roles that belong to the action.
*
* #return Object
*/
public function roles()
{
return $this->belongsToMany('App\Models\User\Role');
}
Eloquent does not have a HasManyThrough relationship across 2 pivot tables.
1. You can get the actions by lazy eager loading the roles and actions, then extracting them:
$actions = $user->load('roles.actions')->roles->pluck('actions')->collapse()->unique();
2. You can check the action directly in the database, using a whereHas constraint:
$allowed = $user->roles()->whereHas('actions', function ($query) use ($action) {
$query->where('name', $action);
})->exists();
For handling user, user roles and user permissions you can simply use Toddish package.
There are lot of things this package does for you. like:
$user->is('Your Defined Role');
$user->can('add_user');
$user->level(7);
For installation just read it's documentation.
Although you have mentioned that your Eloquent models (and their relationships) are set up, I am assuming that you have the following in your application already:
User model
class User extends Eloquent {
public function roles() {
return $this->belongsToMany('App\Models\Role');
}
}
Role model
class Role extends Eloquent {
public function actions() {
return $this->belongsToMany('App\Models\Action');
}
public function users() {
return $this->belongsToMany('App\Models\User');
}
}
Action model
class Action extends Eloquent{
public function roles(){
return $this->belongsToMany('App\Models\Role');
}
}
Given the above set properly, you can't certainly make a call like the following as Laravel will assume you're making a call to a Query Builder method or whatever [which in fact doesn't exist]:
$userActions = App\Models\User::find(1)->roles()->actions();
Instead, you have to use Laravel's magical whereHas method to query relations where multiple nested relations are involved.
Now, having the user's id and the current allowed action [which indeed can be utilized in your middleware], it can be determined whether the user is allowed to see the page:
$hasAccess = App\Models\User::whereHas('roles.actions', function($q) use ($id, $action){
$q->where('users.id', $id);
$q->where('actions.name', $action);
})->get()->toArray();
if($hasAccess){ // or `count($hasAccess) > 0`. The former will work since any number > 0 evaluates to true in PHP
//user has access
}
Notice the nesting of relationships with ..
Relationship Existence in Laravel:
In Laravel the existence of a relationship between models is determined with has and whereHas methods. The has method is used to only determine if a relationship exists, e.g. by executing App\User::has('roles')->get() you'll always get a list/collection of users which at least have any roles.
More power to this can be added with whereHas with which you can add where clauses to the actual query.
Hi this is how I solved this.
I didn't use an actions table. Just users, roles and the user_role table.
After the solution, I pass my custom middleware a role array to every route I create like:
Route::get('insights',[
'as'=>'insights',
**'middleware'=>['access.level'],**
**'roles'=>['admin','customer'],**
'uses'=>'CustomersController#index'
]);
Files modified:
app\Http\Controllers\Controller.php
Custom middleware: CheckAccessLevel
app\Http\Kernel.php
app\Http\routes.php
Controller.php
In this file, I wanted to eager load the current logged in user with his roles and make it a global variable in all views as {{currentUser}} and in all my controllers as "$this->currentUser". this is the code:
protected $currentUser;
public function __construct() {
if(isset(Auth::user()->username)){
$this->currentUser = User::with('roles')->where(['username' => Auth::user()->username])->first();
// Share this property with all the views and controllers in your application.
view()->share('currentUser', $this->currentUser);
}
}
Custom Middleware: CheckAccessLevel.php
Over here in the middleware, I retrieve the roles array passed to the route and and also the roles assigned to the current user.
After i get these variables, I intersect them to see if there is a match before I pass the user on. check the code below:
//if user is not logged in, show them where to login :)
if (!Auth::check()) {
return redirect()->route('user::login');
}
//Otherwise get the roles for that route
$get_route_action = $request->route()->getAction();
$get_route_roles = $get_route_action['roles'];
//Eager load the user with their list of roles
$eager_user = User::with('roles')->where(['id'=>$request->user()->id])->first();
$user_roles = $eager_user->roles->pluck('role_name')->toArray();
//intersect the users roles with the route roles to see if there is a match
foreach ($user_roles as $user_role){
if(in_array($user_role, $get_route_roles)){
return $next($request);
}
}
Kernel.php
over here, i register my route as "access.level" inside the route middleware group
Route.php
then whenever I create a route, I just pass in the allowed role names to it and voala! It works for me..
I hope this helps.
You need a HasManyThrough relationship here.. Here's something to get you started.
Judging by your given tables I see it has a one-to-many relationship with user and roles. While action and roles also has many-to-many relationship.
But first you need to create models for each entities(user,role,action) to follow the MVC structure. You could easily make these models from the command line using the Laravel's artisan with this command.
php artisan make:model User
Make sure to also add or change columns in the newly created migrations. Assuming you also have your pivot tables set up for the 3 tables, you can now add the relationships.
class User extends Model {
//
protected $table = 'users';
/*
* #var table
*
*/
public function action()
{
return $this->hasManyThrough('App\Action', 'App\Role');
}
}
Now you have a HasManyThrough relationship. you can query like this directly no need to include role.
//this
$actions = User::find(1)->action();
//instead of
$actions = User::find(1)->role()->action();
//this will return all actions available to a user with id of 1
NOTE I also suggest you make your role and user models to be on a one to one relationship.

Categories