Laravel Nova: Partition to display other table's column - laravel

I'm using Laravel Nova partition to show an amount of items per category.
public function calculate(Request $request) {
return $this->count($request, Item::class, 'category_id');
}
This works fine, but displays on the screen the category_id of course.
I would rather want to show the category_name.
The model is built as follows:
class Item extends Model
{
public function category()
{
return $this->belongsTo('App\Category');
}
}
and
class Category extends Model
{
public function item()
{
return $this->hasMany('App\Item');
}
}
Also, I have in the Nova Category resource defined the following:
public static $title = 'category_name';
How can I show the category name instead of the category id?

From the documentation
Often, the column values that divide your partition metrics into
groups will be simple keys, and not something that is "human
friendly". Or, if you are displaying a partition metric grouped by a
column that is a boolean, Nova will display your group labels as "0"
and "1". For this reason, Nova allows you to provide a Closure that
formats the label into something more readable:
/**
* Calculate the value of the metric.
*
* #param \Illuminate\Http\Request $request
* #return mixed
*/
public function calculate(Request $request)
{
return $this->count($request, User::class, 'stripe_plan')
->label(function ($value) {
switch ($value) {
case null:
return 'None';
default:
return ucfirst($value);
}
});
}
So, in your case, it would be something like this:
/**
* Calculate the value of the metric.
*
* #param \Illuminate\Http\Request $request
* #return mixed
*/
public function calculate(Request $request)
{
return $this->count($request, Item::class, 'category_id');
->label(function ($value) {
// Get your category name here
// For example: return \App\Category::find($value)->name;
});
}

Related

Get nested relationship where use belongs to page and has the correct roles

So, I am trying to check if a user belongs to a page that owns a job.
The relationships are like so:
user.php
/**
* #return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function pages(): BelongsToMany
{
return $this->belongsToMany(Page::class);
}
page.php
/**
* #return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function users(): BelongsToMany
{
return $this->belongsToMany(User::class);
}
/**
* #return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function jobs(): HasMany
{
return $this->hasMany(Job::class);
}
job.php
/**
* #return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function page(): BelongsTo
{
return $this->belongsTo(Page::class);
}
Now, I want to see if a user belongs to a page that owns the job:
$job = Job::find(1); //belongs to page_id 1, has job_id 1
$user = User::find(1); // only owns 1 page and 1 job.
I can change my Job::find(1) to any idea, and the code below will always return true, even if User::find(1) doesn't belong to a page that owns that job.
The $job variable exists, and is a eloquent model for the Job.
return $job->page->whereHas('users', function($query) use($user) {
$query->where('page_user.user_id', $user->id);
$query->whereIn('page_user.role', ['admin', 'editor']);
})->exists();
What am I doing wrong?
The problem with your code is this part: $this->page->whereHas(...). $this->page is an Eloquent Collection and you're treating it like a Query Builder. To append a query you need to call the relationship method, in this case page() like in the example in the documentation.
return $job->page()
->whereHas('users', function ($query) use ($user) {
$query->where('page_user.user_id', $user->id);
$query->whereIn('page_user.role', ['admin', 'editor']);
})
->exists();

Eloquent relationship returning all when ID doesn't match

For some reason my relationship is fetching all from the corresponding table when I dump it, however dumping the result does not show these rows.
The slider ID does not match the slider_id within the settings table.
So the following works fine, as expected the settings is an empty array:
/**
* #return HasOne
*/
public function slider(): HasOne
{
return $this->hasOne(Slider::class)->withDefault(
(new Slider())->attributesToArray()
);
}
Result:
{
"name": "media-slider",
"settings": []
}
However when I dump within the attribute I get all the rows from the settings table, when this query should be getting all settings where the slider_id matches the current slider, which has a different ID.
<?php
namespace App\Models\Media;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Support\Collection;
class Slider extends Model
{
/** #var string[] */
protected $appends = [ 'settings' ];
protected $defaults = [
'test' => [
'id' => 0,
'name' => 'default name',
]
];
public function __construct(array $attributes = [])
{
parent::__construct($attributes);
$this->attributes = $this->defaults['test'];
}
/**
* #return HasMany
*/
public function settings(): HasMany
{
return $this->hasMany(SliderSetting::class);
}
/**
* Get the slider settings, extract the value and key by the key, also
* group if multiple setting groups are required.
*
* Perform this logic here so data can be used directly by the JavaScript.
*
* #return \Illuminate\Database\Eloquent\Collection|Collection
*/
public function getSettingsAttribute()
{
dd($this->settings()->get()); // This should be empty!
return $this->settings()->get()
->groupBy('group')
->map(static function ($group) {
$group = $group->keyBy('key');
return $group->map(static function ($setting) {
return $setting->getAttribute('value');
});
});
}
}
Edit
/**
* #return HasMany
*/
public function sliderSettings(): HasMany
{
dd($this->hasMany(SliderSetting::class)->toSql());
return $this->hasMany(SliderSetting::class);
}
The above outputs:
select * from slider_settings
Shouldn't it be the following?
select * from slider_settings where slider_settings.slider_id = ?

How to get property or method in relationship ( laravel - eloquent )

in Post Model
function user()
{
return $this->belongsTo( \App\User::class);
}
in User Model
function posts()
{
return $this->hasMany( \App\Post::class);
}
function somedata()
{
return date('i') * 1000 + date('s');
}
in Controller
$posts = Post::query()
->where('id', 10)
->with('user')
->get();
but it does not get 'somedata' in user model .
How can I drag this data with posts ?
Try making it an attribute and append it in the model
Post.php
/**
* The accessors to append to the model's array form.
*
* #var array
*/
protected $appends = ['someData'];
/**
* Get the some data for the post.
*
* #return int
*/
public function getSomeDataAttribute()
{
return date('i') * 1000 + date('s');
}
You need to set an Accessor:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* Get the user's somedata.
*
* #return string
*/
public function getSomedataAttribute()
{
return 'somedata';
}
}
Also see: https://laravel.com/docs/5.8/eloquent-mutators

Block the access to a page students.index()

In my navbar I have 2 pages which are Student Add and Student Index.
When I click on Student Add, I have an error message Access Denied.
Great, no problem...
Now, I would like to make the even thing with the page Students Index and display the items, I have a problem.
I have access to the content...
In my Controller Student I have this:
class StudentController extends Controller
{
public function __construct()
{
$this->middleware(['auth', 'clearance'])
->except('index', 'show');
}
/**
* Display a listing of the resource.
*
* #return \Illuminate\Http\Response
*/
public function index()
{
$students = Student::orderby('id', 'desc')->paginate(5);
return view('students.index', compact('students'));
}
/**
* Show the form for creating a new resource.
*
* #return \Illuminate\Http\Response
*/
public function create()
{
return view('students.create');
}
/**
* Store a newly created resource in storage.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\Response
*/
public function store(Request $request)
{
$this->validate($request, [
'name'=>'required',
'firstname' =>'required',
]);
$name = $request['name'];
$firstname = $request['firstname'];
$student = Student::create($request->only('name', 'firstname'));
return redirect()->route('students.index')
->with('flash_message', 'Article,
'. $student->name.' created');
}
Then, in my Class ClearanceMiddleware I have this:
public function handle($request, Closure $next) {
if (Auth::user()->hasPermissionTo('Administer roles & permissions')) {
return $next($request);
}
if ($request->is('students/create')) {
if (!Auth::user()->hasPermissionTo('Create Student')) {
abort('401');
} else {
return $next($request);
}
}
if ($request->is('students/index')) {
if (!Auth::user()->hasPermissionTo('Index Student')) {
abort('401');
} else {
return $next($request);
}
}
I don't see the missed step. I have to block the access please.
2 things:
1) You need to adjust the middleware call in your controller's constructor. The except() method means the middleware will not run on those methods, so if you want the middleware to run on the index method, you will need to remove it from except().
This will call the middleware on every route method except show():
$this->middleware(['auth', 'clearance'])
->except('show');
2) Inside your middleware, you are using $request->is() to match on the path, but the url for index is not 'students/index'.
// The url path for the index route is '/students'
if ($request->is('students')) {
if (!Auth::user()->hasPermissionTo('Index Student')) {
abort('401');
} else {
return $next($request);
}
}
$this->middleware(['auth', 'clearance'])
->except('show');
Remove index from the except method. As it is you are exempting the index method from the middleware check.

How to set hidden attributes to an Controller method in Laravel5.0?

I want to hide some data which selected from database but reinitialize from some method in Controller not defined in its Models.
function ddd(){
return Client::select($this->_client)->with([
'Contact'=>function($s){
//$this->setHidden('use_id');
//$s->setHidden('use_id');
$s->select($this->_contact);
},
'Employer'=>function($s){$s->select($this->_employers);},
])->get();
}
You requirement is not very clear. However. I am assuming that you have 3 models Client hasOne Contact and belongsTo Employer.
In order to hide the use_id property of the Client model you can define a hidden property in your model
class Client extends Model
{
//will hide the `use_id` from the model's array and json representation.
protected $hidden = ['use_id'];
//Relations
/**
* Get the Contact which the given Client has.
* #return \Illuminate\Database\Eloquent\Relations\HasOne
* will return a App\Contact model
*/
public function contact()
{
return $this->hasOne('App\Contact');
}
/**
* Get the Employee to which the given Client belongs.
* #return \Illuminate\Database\Eloquent\Relations\BelongsTo
* will return a App\Employer model
*/
public function employer()
{
return $this->belongsTo('App\Employer');
}
}
Then in probably your ClientsController in some action ddd
public function ddd()
{
return Client::with('contact')->with('employer')->get();
}

Resources