Showing data Roles Spatie from eloquent relations get error in Laravel - php

i want to showing data from relation of User and Roles Spatie. But i've got error doesn't exist collections. Here is my code :
Model :
<?php
namespace App\Models;
// use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;
use Spatie\Permission\Traits\HasRoles;
class User extends Authenticatable
{
use HasApiTokens, HasFactory, Notifiable, HasRoles;
Controller :
public function index()
{
$data_user = User::with('roles')->get();
return view('role.role', [
'data_user' => $data_user
]);
}
role.blade.php :
<table class="table-hover table">
<thead>
<tr>
<th scope="col">No.</th>
<th scope="col">User</th>
<th scope="col">Email</th>
<th scope="col">Role</th>
</tr>
</thead>
#foreach ($data_user as $du)
<tbody>
<tr>
<td scope="row">{{ $loop->iteration }}</td>
<td>{{ $du->name }}</td>
<td>{{ $du->email }}</td>
<td>{{ $du->roles->name }}</td>
</tr>
</tbody>
#endforeach
</table>
Error:
Property [name] does not exist on this collection instance.

The roles relation is a collection of roles since the package allows a user to have multiple roles. So you cannot access the property name on the collection.
You need to get an individual role from the collection, for example
{{ optional($du->roles->first())->name }}
Edit
If you wish to show multiple roles, you could implode them
{{ $du->roles->implode('name', ', ') }}
If you wish to make it neater, you could write a loop to generate badges. Here's a simple example using bootstrap
<td>
#foreach($du->roles as $role)
<span class="badge bg-primary">{{ $role->name }}</span>
#endforeach
</td>

Related

Laravel 6 in index blade how can I show only users who have roles and their roles in the table

In index.blade.php, I wrote these codes to show users who have roles
<thead>
<tr>
<th scope="col">Name</th>
<th scope="col">Email</th>
<th scope="col">Roles</th>
<th scope="col">Actions</th>
</tr>
</thead>
<tbody>
#foreach($users as $user)
<tr>
<td>{{ $user->name }}</td>
<td>{{ $user->email }}</td>
<td>{{ $user->roles }}</td>
<td>Show</td>
</tr>
#endforeach
</tbody>
And I wrote these codes in UserController,
$userId = \DB::table('role_user')->get()->pluck('user_id');
$users = User::find($userId);
return view('admin.index', compact('users'));
And I got these in the website:
[{"id":1,"name":"User Administrator","description":null,"created_at":"2021-11-23 03:06:49","updated_at":"2021-11-23 03:06:49","pivot":{"user_id":1,"role_id":1}}]
[{"id":2,"name":"Moderator","description":null,"created_at":"2021-11-23 03:06:49","updated_at":"2021-11-23 03:06:49","pivot":{"user_id":2,"role_id":2}}]
How can I only display the names in the table role column?
When calling user->roles, you're most likely calling towards a relation on your User model. This means that you're returning a collection. If you place a collection in curly braces in blade ({{ $user->roles }}), Laravel automatically calls toArray() on each model, and a json_encode on the result, which results in the JSON strings you end up seeing.
You only want the names, however, so it'd be better to grab those values and convert them to a string. An option of doing so is by plucking the name, and imploding the result:
implode(', ', $user->roles()->pluck('name')->toArray());
You have to call toArray() on the pluck() result, else you'll have a collection instead of an array, which implode does not work with.
If the user is logged in and his role is to be displayed, you can use this in your blade:
{{ Auth::user()->roles->pluck('name') }}
Or you would like to display the rools of another user, then you can do it as follows:
// in Controller fetch the user:
$user = User::find(42);
// in your Blade:
{{ $user->roles->pluck('name') }}
In this context, you have a number of methods that you can use:
roles
hasRole
hasAnyRole
hasAllRoles
getRoleNames

How can I change a column time attribute to AM and PM for the blade view?

I have a table named time_entries and the column name is time_start.
I'm inserting Carbon::now(); on it. The data stored in the column is 2021-08-26 09:51:37 and blade.php shows same result.
Model TimeEntry:
namespace App\Models;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class TimeEntry extends Model
{
use HasFactory;
public function user()
{
return $this->belongsTo(User::class);
}
public function getTimeStartAttribute($value)
{
return Carbon::createFromFormat('H:i:s', $value)->TimeString();
}
}
Controller:
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Models\TimeEntry;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class AttendanceController extends Controller
{
public function index()
{
$data = TimeEntry::where('user_id', Auth::user()->id)->paginate(2);
return view('Admin.Attendance-History-page', compact('data'));
}
}
Blade view:
<tbody id="table_data">
#foreach ($data as $punch)
<tr>
<td>{{ $punch->user->name }}</td>
<td>{{ $punch->user->employee_id }}</td>
<td>19 Feb 2019</td>
<td>{{ $punch->time_start }} </td>
<td>{{ $punch->time_end }}</td>
<td>9 hrs</td>
<td>
<span class="badge bg-inverse-success">Perfect</span>
</td>
<td>0</td>
</tr>
#endforeach
</tbody>
I want to know how can I format the output from 2021-08-26 09:51:37 to something like 09:51:AM in Blade?
Thank you for your help.
There is a straight forward solution for this using the PHP date() method.
{{ date('h:m A', strtotime($punch->time_start)) }}
This will output 09:51 AM
If you want to output 09:51:AM then just add : after the m and remove the space, like so:
{{ date('h:m:A', strtotime($punch->time_start)) }}

Why do I get a "Trying to get property of non-object" error when using Sortable package in Laravel?

I've encountered a problem with the Kyslik\Column-sortable package for Laravel which has frustrated me for weeks now. :)
The sorting links displays correctly, but when I click on one of the sorting links, I get the following error:
🧨 Trying to get property 'title' of non-object (View: C:\wamp64\www\GeekCollector\resources\views\Lp\show.blade.php)
What's even more strange is that the route goes to the BrowseResults view, but the message sais that the error was encountered in the Show view.
If I remove all the sortable related stuff from the BrowseResults view, the Show view works perfectly.
Here is my model:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;use Illuminate\Database\Eloquent\Model;
use Kyslik\ColumnSortable\Sortable;
class Lp extends Model
{
use HasFactory;
use Sortable;
public $sortable = ['title', 'artist', 'year'];
}
Here is my BrowseResults controller method:
public function browseResults(Request $request)
{
$chosenCategory = $request->category;
$lps = Lp::where('category','like','%'.$chosenCategory.'%');
$result = $lps->sortable('title')->paginate(5);
return view('Lp.browseResults', compact('result'));
}
And here is my blade view:
<x-app-layout>
<x-slot name="header">
<h1 class="font-semibold text-xl text-gray-800 leading-tight">
Lp-skivor
</h1>
</x-slot>
#sortablelink('title')
#sortablelink('artist')
#sortablelink('year')
<table>
<tr>
<td>Titel</td>
<td>Artist</td>
<td>Kategori</td>
<td>Plats</td>
<td>Position</td>
</tr>
#foreach ($result as $lp)
<tr>
<td>
{{ $lp->title }}
</td>
<td>{{ $lp->artist }}</td>
<td> {{ $lp->category }}</td>
<td>{{ $lp->place }}</td>
<td>{{ $lp->position }}</td>
<td>
Uppdatera
</td>
<td>
<form action="{{ route('lp.destroy', $lp->id) }}" method="post">
#csrf
#method('DELETE')
<button type="submit">Ta bort</button>
</form>
</td>
</tr>
#endforeach
</table>
{!! $result->appends(\Request::except('page'))->render() !!}
</x-app-layout>
The route looks like this:
Route::post('/lp/browse-results', [LpController::class, 'browseResults'])->name('lp.browseResults');
Thanks very much in advance for your help!
All the best!

How to paginate and show all records using hasMany in laravel 5.6?

I have two tables one table for general information about the order named orders and a detail table for information like products, notes and delivery date.
Basically, I want to show in the same page the table orders and for each order can be multiple products, notes, dates from the table detail, and also I want to paginate in order to show exactly 20 orders on each page and every product, note, date row with the same id_order.
In conclusion, on each page there are 20 orders from table orders but there can be 40 rows from table detail with products, notes, delivery date, because one order can contain more than one product. in fact I want to use rowspan html in order to show on the same row the detail.
This is my Orders model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class order extends Model
{
public $timestamps = false;
protected $fillable = ['client','number_order','file'];
public function details()
{
return $this->hasMany('App\Detail','orders_id')->orderBy('id', 'desc');
}
}
Detail model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Detail extends Model
{
protected $table = 'detail';
public function order()
{
return $this->belongsTo('Detail','orders_id');
}
}
My controller:
public function index()
{
$orders = Order::first(); //This works only with one record I cant show all records, all() is not working
$orders->setRelation('details', $orders->details()->paginate(10));
return view('orders.index', compact('orders'));
}
View:
<tbody>
#foreach ($orders->details as $detail)
<tr id="{{ $detail->orders_id }}">
<td>{{ $detail->product }}</td>
</tr>
#endforeach
</tbody>
You can use eager load details on order like this
public function index()
{
$orders = Order::with('details')->paginate(20);
return view('orders.index', compact('orders'));
}
In view
<table>
<tbody>
#foreach($orders as $order)
<tr>
<td>{{ $order->created_at }}</td>
<td>... put any order info here</td>
<td>
<label>Order Details:</label>
<table>
#foreach ($order->details as $detail)
<tr id="{{ $detail->orders_id }}">
<td>{{ $detail->product }}</td>
<td>{{ $detail->note }}</td>
</tr>
#endforeach
</table>
<td>
</tr>
#endforeach
</tbody>
</table>

Laravel: Eloquent returning an object I can't iterate over

I have a mySQL DB schema like this:
table RECIPES:
int id, PK;
int salesman_id;
int doctor_id;
date order_date;
int status;
table RECIPE_STATUS:
int id, PK;
int recipe_status_code;
varchar recipe_status_name;
In Laravel I have the following php classes:
AdminRecipesController.php
namespace RatCMS\Controllers;
use App\Http\Controllers\Controller;
use Auth;
use RatCMS\Models\Recipes;
use RatCMS\Models\RecipeStatus;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Input;
class AdminRecipesController extends Controller
{
public function index()
{
$recipes = Recipes::with('recipeStatus')->get();
return view('admin.recipes.news', compact('recipes'));
}
}
Recipes.php
<?php
namespace RatCMS\Models;
use Illuminate\Database\Eloquent\Model;
class Recipes extends Model
{
protected $table = 'RECIPES';
protected $fillable = ['salesman_id', 'doctor_id', 'order_date', 'status'];
public function recipeStatus() {
return $this->hasOne(\RatCMS\Models\RecipeStatus::class, 'recipe_status_code', 'status');
}
}
RecipeStatus.php
<?php
namespace RatCMS\Models;
use Illuminate\Database\Eloquent\Model;
class RecipeStatus extends Model
{
protected $table = 'RECIPE_STATUS';
protected $fillable = [];
public function recipes() {
return $this->belongsTo(\RatCMS\Models\Recipes::class);
}
}
blade view
<div class="box-body">
#include('admin.partials.session_success')
#if($recipes->isEmpty())
<p class="text-center">No recipes available.</p>
#else
<table class="table table-bordered">
<tr>
<th style="width: 10px">#</th>
<th>Salesman</th>
<th>Doctor</th>
<th>Date</th>
<th>Status</th>
<th style="width:100px">Actions</th>
</tr>
#foreach($recipes as $recipe)
{{ $recipe }}
<tr>
<td>{{ $recipe->id }}</td>
<td>{{ $recipe->salesman_id }}</td>
<td>{{ $recipe->doctor_id }}</td>
<td>{{ $recipe->order_date }}</td>
<td>{{ $recipe->recipe_status->recipe_status_name }}</td>
<td>
<form style="display: inline-block" action="{{ url('admin/recipes/' . $recipe->id) }}" method="POST">
{{ csrf_field() }}
<input name="_method" type="hidden" value="DELETE">
<button type="submit" class="btn btn-danger"><i class="fa fa-close" aria-hidden="true"></i> Delete</button>
</form>
</td>
</tr>
#endforeach
</table>
#endif
</div>
When I do {{ $recipe }} in the view, I get the following result:
{"id":1,"salesman_id":"4","doctor_id":"3","order_date":null,"status":"0","recipe_status":{"id":1,"recipe_status_code":"0","recipe_status_name":"Not Recieved"}}
so there is some data being return by Eloquent regarding the recipe status (Not Recieved text), but when I do {{ $recipe->recipe_status }} it fails every time. Even $recipes['recipe_status'] is no help.
Could someone help? Thanks
Relationship should be belongsTo():
public function recipeStatus() {
return $this->belongsTo(\RatCMS\Models\RecipeStatus::class, 'status', 'recipe_status_code');
}
With correct relationship your code will add relationship data to collection, so you'll be able to get status:
$recipe->recipeStatus->recipe_status_name

Categories