Laravel nova and belongsToThrough? - laravel

Is there a way to display in Laravel Nova Resource a relation like this ?
$report->meter->user
where
- a report belongs to a meter
- a meter belongs to a user
I am in report ressource and I want to display related user

I struggled with this lately. What we seek is a BelongsToThrough relationship field. That type of relationship isn't natively supported by Laravel, which means there's no field for it in Nova either. However, you can easily implement it in Laravel by installing this package: https://github.com/staudenmeir/belongs-to-through
You can then add your report relationship to the User model.
// App\Models\Report
use \Znck\Eloquent\Traits\BelongsToThrough;
public function report()
{
return $this->belongsToThrough('App\Models\User','App\Models\Meter');
}
And you can use a regular BelongsTo relationship within Nova.
// App\Nova\Report
public function fields(Request $request)
{
return [
BelongsTo::make('User')
]
}
Note: This would work for the Report index/details views, but you'll want to exclude it from the edit form. (Consider a computed Text field, if you want to display the user on the edit form.)

Related

Laravel BelongsTo works fine but in Nova not displaying data

I have an application with many question responses. I am not using the traditional foreign key naming conventions but when I query either object, the relationships pull up correctly. Using the current Laravel Nova v4.
class Application extends Model
{
public function questionResponses(): HasMany
{
return $this->hasMany(QuestionResponse::class, 'application_ec_id', 'ec_id');
}
}
class QuestionResponse extends Model
{
public function application(): BelongsTo
{
return $this->belongsTo(Application::class, 'application_ec_id', 'ec_id');
}
}
Within Laravel Nova, when I open an Application, I see the references to multiple question responses. However when I open an individual QuestionResponse, the application relationship just shows a hyphen like it's missing; it does not display the Application reference.
This is from the Application Nova Resource
HasMany::make('Question Responses'), // WORKS
But this does not work in the QuestionResponse Resource
BelongsTo::make('Application'), // does not work
BelongsTo::make('Application', 'application', Application::class), // doesn't work either
Text::make('application ec id'), // just to make sure the correct ID is in place
Even when I check the browser console, I see this request pulling the correct data. I am not sure what else to check.
// this URL returns a fields array and the correct record ID for application is present
domain.test/nova-api/question-responses/58649?relationshipType=

Display relationship of relationship in response

My stack is - Laravel, React, Vite. I have a relationship:
$messages = $user->profile->messages
and it works correctly, but messages have relationship with user. Propably it sound difficult but it's simple.
Profile contains more details about user and profile has relationsin hasMany for Messages. It's simple. But I need to display messages with username (this is in Username model). How I said Messages have an relationship with User model but it's not in my response.
public function user() {
return $this->belongsTo(User::class);
}
If I want to display only data from model with relationship I could use with, for example:
Book::with('author')->get()
But in this case it didn't work. For example
$user->profile->messages->with('user')
It display me the error
Method Illuminate\Database\Eloquent\Collection::with does not exist.
My question is - how could I add relationship (to user) to this query so that I can see that relationship in the response?
$user->profile->messages
not sure what query you are using, but you can write something like this if you wish which should work assuming that the messages and user relationships are correctly defined
$user = User::with(['profile',
'profile.messages',
'profile.messages.user:id,username'])
->where(//some condition)->get()

Laravel Nova Override BelongsTo Language field based on already translated resources

Imagine the following 3 models with fields:
Listing:
id
ListingTranslation:
id
listing_id
language_id
title
Language:
name
iso
Inside my ListingTranslation create/update form how can I filter the language selector to NOT SHOW the languages that have been already translated?
(i.e. If I have 2 languages ES (id 1) and EN (id 2) and if I have a listing with id 1 and this listing already has a listing_translation with id 1, listing_id 1 and language_id 1, the language selector should only show EN as an option).
Language selector:
BelongsTo::make('Language')
Laravel Nova documentation provides the following method to filter the queries that are used to populate relationship model selection menus:
public static function relatableQuery(NovaRequest $request, $query)
{
return $query->where('user_id', $request->user()->id);
}
However, I do not know how to access something like listing_id from this method.
Instead of creating Nova resource for pivot table ListingTranslation, you can make use of BelongsToMany relation.
Under Listing Nova resource fields add BelongsToMany::make('Languages'). Assuming you have already defined the relationship in Listing model.
At this point when you attach a language which is already attached, you will see an error message The language is already attached
But if you still want to stop listing the already attached languages you can add relatableQuery given below under Listing nova resource.
public static function relatableLanguages(NovaRequest $request, $query)
{
$listing = $request->findResourceOrFail();
return $query->whereNotIn('id', $listing->languages->pluck('id'));
}
Hope this will help you.

Problem in showing additional field of pivot table in Larvel Nova

I am using Laravel Nova for my admin side.
I have this problem that in my pivot table, I added additional field.
I have user table and event table. User can have many event, and event can have many users. So I created a pivot table for the 2 models. But I want to the status of the event of user. So I added additional field for status in pivot table.
My problem now is in the Laravel Nova.
In my event resource, I have this:
BelongsToMany::make('Pending Users', 'pendingUsers', 'App\Nova\User'),
It shows another table for pending clients. I can already get the list of users in specific event but I can't show to the table the status of the event of user. If the user is approved or still pending.
What strategy is best in my case? I am thinking to make a model for Event and User.
I don't know how to show the additional field of pivot table in BelongsToMany in Laravel Nova. It just shows what I added in User Resource of Nova. Like ID and name. But I don't know where the status of user's event will show. I want to show it in the table of BelongsToMany of events to users.
You need to make sure that you're defining the relationship in BOTH models, and then letting Nova know which fields you want to show like this:
In your event resource:
BelongsToMany::make('Users')
->fields(function() {
return [
Text::make('status')
];
}),
In your event model:
public function users()
{
return $this->belongsToMany(User::class)->withPivot('status');
}
In your user model:
public function events()
{
return $this->belongsToMany(Event::class)->withPivot('status');
}
I got this working by defining ->withPivot('filed name)' on the relationship it drove me insane for a long time.
BelongsToMany::make('your_relationship')
->fields(function () {
return [
Text::make('your_text'),
];
})
Your relation will be here something just like this what i said previous
public function users()
{
return $this->belongsToMany(User::class)->withPivot('filed name');
}

Laravel nova overriding/setting custom value for the Fields or Has Through relationship

I am developing a Web application using Laravel. For the admin panel, I am using Laravel Nova. What I am trying to do now is that I need to use data from the table which has relationship through another table. To be, clear, see my database structure below.
items
=====
id
name
price
sub_category_id
sub_categories
==============
id
name
parent_category_id
parent_categories
=================
id
name
What I am trying to achieve inside the Nova is that I want to display the parent category name of the item on the item index/list page. The first thing is that I do not want to create custom attribute something like this in the model
protected $appends = [
'parent_category_name'
];
function getParentCategoryNameAttribute()
{
//code here
}
Therefore, there are two solutions I can think of. The first solution is using the HasThrough relationship. But I cannot find it in Nova. So, I cannot use it. The second solution is that overriding the field value on render. Something like this.
Text::make("fieldname")->fillUsing(function($request, $model, $attribute, $requestAttribute) {
//$model->sub_category->parent_category - then I can return a value
return "Parent category name";
})->onlyOnIndex()
But the above code is not working. So, what would be the best approach to handle the has-through relationship in Nova?
Assuming you have defined the relationship sub_category & parent_category properly.
Define the relationship in Item model as below
public function parent_category()
{
return $this->sub_category->parent_category();
}
Then use it in Item resource as below.
BelongsTo::make('Parent Category')
->hideWhenCreating()
->hideWhenUpdating(),

Resources