Too few arguments Laravel Nova relatable query - laravel

I have a relationship that needs to be filtered differently depending on the Laravel Nova field it is being used to populate.
A single Process_type has one or more Process_justifications attached as options (BelongsToMany)
A single Process_type also has a single Process_justification set as a default (BelongsTo)
I'm using a relatable query to filter the available options for each of these two fields.
The two fields in my Process_type resource are as follows:
BelongsTo::make('Default', 'process_justification', Process_justification::class)
BelongsToMany::make('Options', 'process_justifications', Process_justification::class)
The relatable query looks like this:
public static function relatableProcess_justifications(NovaRequest $request, $query, Field $field)
{
if ($field instanceof BelongsTo) {
//query builder to filter options
...........
} else {
//return all options
return $query;
}
}
This pattern came from Laravel Nova documentation on Dynamic Relatable Models (https://nova.laravel.com/docs/3.0/resources/authorization.html#dynamic-relatable-methods)
It describes adding the field as a third parameter to the relatable query, then using it in a conditional to choose filter logic.
The error I'm getting is
Too few arguments to function App\Nova\Process_type::relatableProcess_justifications(), 2 passed and exactly 3 expected
My make() calls have three parameters as per the documentation, any idea what I'm missing?
I'm on Laravel 7.x and Nova 3.x

Related

Get laravel relations value as attribute

I have two models, Portal and Tag and relation many-to-many between them with extra database portal_tag. All working great and I can access to portal->tag without problem.
But my goal is to get this model like "all values from model" and all relations value as one attribute, between commas. Is it possible?
Because I need it inside PortalsExport class in this form to use in export into CSV libary.
Now its look like this:
Portal::with('tags')
->select('url','type','topic','description','prohibited','visits','facebook_url','twitter_url','instagram_url')
->where('user_id', Auth::id())->get();
I have no idea how to make tags.name same as all other options from select.
If you want to get tags relations as comma separated string then One approach is, You will need to define a accessor in your Portal model which will append you tags array into string. like once I was did in one of my project:
Step 1:
public function getTagsAsStringAttribute(): string
{
$array = $this->tags->pluck('name')->all();
return implode(", ",
array_map(function ($k, $v) {
return $k;
}, array_keys($array), array_values($array))
);
}
In above closure functions, plz verify yourself that you tag name value is available in $k or $v variable.
Step 2:
add that accessor in Portal model append array like that:
protected $appends = [
'tags_as_string',
];
Step 3:
In the result of yours below query you will get tags_as_string attribute which contains comma separated tags as string.
Portal::with('tags')
->select('url','type','topic','description','prohibited','visits','facebook_url','twitter_url','instagram_url')
->where('user_id', Auth::id())->get();
If tags_as_string shown empty then try it above query without select() clause.

Laravel nova and belongsToThrough?

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.)

How to filter options for Laravel Nova select field

I have a resource of type Process_type.
It has a BelongsToMany relationship with Process_event
It also stores a default Process_event as a BelongsTo relationship - I want the possible options for this to be limited to those in the BelongsToMany relationship, not the entire set of process events in the database.
I was expecting to be able to limit the options on a BelongsTo::make() field, but can't find a way to do this. So I'm falling back to using a Select field, and passing in the options via the options() method.
This is how my fields method looks currently
public function fields(Request $request)
{
$options = [];
$options['process_events'] = \App\Process_event::all()->pluck('title','id');
return [
ID::make()->sortable(),
Text::make('Title')->sortable(),
Select::make('Process Event')->options($options['process_events']),
BelongsToMany::make('Process Events', 'process_events', Process_event::class)
];
}
As it stands, I still have all process events as options. How can I access the current entity via the $request object passed in, so I can look up the ->process_events() on the model. I can't find any documentation on this.
Is this possible? If not, what is a better way to do this?

Retrieving records from database using eloquent with optional query parameters

i have the following block of code in my Resource Controller:
$travel_company_id = Input::get('travel_company_id');
$transport_type = Input::get('transport_type');
$route_type = Input::get('route_type');
$travelRoutes = TravelRoute::where('travel_company_id', $travel_company_id)
->where('transport_type', $transport_type)
->where('route_type', $route_type)
->get();
Now what this does is it gets travelRoutes based on the parameters supplied. What i want is for it to do is perform a search based on the available parameters, that way if $route_type is empty the search will be performed only on travel_company_id and transport type.
Also if all the parameters are empty then it will simply do a get and return all available records.
I know i can do this with lots of if statements but then if i add a new parameter on the frontend i will have to add it to the backend as well, I was wondering if there was a much simpler and shorter way to do this in laravel.
The where method accepts an array of constraints:
$constraints = array_only(Input::all(), [
'travel_company_id',
'transport_type',
'route_type',
]);
$routes = TravelRoute::where($constraints)->get();
Warning: do not use Input::only() instead of array_only(). They're not the same.
Input::only() fills in any missing items with null, which is not what you want here.
This is pretty hacky and if you spend some time developing a solution I'm sure it could be much nicer. This assumes all the fields in the getSearchFields() function match the input names from the form and database.
/**
* Search fields to retrieve and search the database with. Assumed they match the
* column names in the database
*/
private function getSearchFields()
{
return ['travel_company_id', 'transport_type', 'route_type'];
}
public function search()
{
// Get a new query instance from the model
$query = TravelRoute::query();
// Loop through the fields checking if they've been input, if they have add
// them to the query.
foreach($this->getSearchFields() as $field)
{
if (Input::has($field))
{
$query->where($field, Input::get($field));
}
}
// Finally execute the query
$travelRoutes = $query->get();
}

laravel query builder, optional search parameters

Laravel newbie looking for guidance. Can anyone please show me the best way to add optional posted search parameters to the following Eloquent query and return all related data and paginated? The optional search parameters are the foreign keys; country_id, season_id and parameter_id.
$dataitems = Dataitem::orderBy('name')->with('country')->with('season')->with('parameter')->paginate(10);
I am reading the docs and have seen the fluent query builder I'm just struggling to recreate this nicely paginated query.
Many thanks.
I am not sure if I understand what you want. But i would do something like this :
Create your base eloquent query :
$query = Dataitem::orderBy('name');
If you have a specific parameter, add the condition to you existant query.
You can repeat this if block for all your optional parameters.
if (Input::has('country_id'))
{
$query->whereHas('country', function($q){
$q->where('id', '=' ,Input::get('country_id'));
});
}
When you're done, paginate:
$query->paginate(10);

Resources