Backpack for Laravel: identifiableAttribute - laravel

I'm struggling with an identifiableAttribute function in a parent model.
In the child controller, this works fine:
CRUD::field('supporter_id')-> // child column for foreign key to parent
type('select')-> // the type of Backpack field you want
entity('supporter')-> // function that defines parent relationship in child Model
attribute('name_last_1') // column of parent shown in Select field
;
Each Address (the child table) is identified by the Last Name of the Supporter (the parent table).
But of course just Last Name isn't good enough. So I added this to the Supporter (parent) model:
public function identifiableAttribute() // for Backpack's dropdown fields
{
return $this->name_last_1 . ', ' . $this->name_first_1 ;
}
and eliminated the attribute('name_last_1') line from the child controller
But instead of the Supporter field showing last-name-comma-first-name, the Supporter field is empty for each child row. And if you drop down the Supporter field, it appears to have the right number of elements to select from, but they each are blank. So apparently the dropdown is working fine, but it's not getting the identifiable attribute it needs from identifiableAttribute().
I also tried return 'test' ; in identifiableAttribute() to see if that would change the symptom, but it didn't ... still nothing but blanks.
There must be something I'm not understanding about identifiableAttribute() and how to implement it. Can you see where I've gone wrong?

Thanks for the questions.
If you would like to concatenate strings, please use an acessor as the identifiable attribute.
In your model:
protected $appends = ['full_name'];
public function getFullNameAttribute() {
return $this->first . ' ' . $this->last;
}
An then use in your field definition:
'attribute' => 'full_name'
Hope it helps.
Cheers

Related

Customised Laravel Nova views - include full child details

I have a Laravel application that contains an entity with a HasOne relationship from parent to child.
I'm now introducing Laravel Nova, and would like the parent's detail view to include all the fields from the child without my user having to click into it as you do with a Nova BelongsTo or HasOne field. They would look like a single record.
Assuming that I cannot modify the structure of the application, is there an existing method to do this? Can I override the detail screen with my own code? The Nova documentation doesn't address this specific use case, nor can I find any other questions on this topic online.
I don't care about needing to create or edit the entries, Nova will just be used to view them in this case.
Thanks
There is not an easy way to display all of the child's details in the parent's details view.
The best solution is to use the title attribute on the child. This lets you customize the text representation of the child in the parent's index view and details view.
By default, you have:
public static $title = 'id';
Can be replaced this with:
public static $title = 'name';
Or:
public function title()
{
return $this->name . '(' . $this->email . ')';
}
Source: https://nova.laravel.com/docs/1.0/resources/relationships.html#title-attributes

How to access child 'model' data using parent 'model' to show in grid in extjs

Scenario : I have two grid on UI 1st is live-offence 2nd Disposed-offence there is on field in 1st grid 'nextDate' ,model of first grid is 'offence' There is another model which is child of offence model that result model ,and the field next-date is inside result model, and result model is in require of offence model. how to access next-date on grid.
If i understand correctly, you can use the column renderer function, which gives you the row's record as a parameter, and access the child result record from there. I'm not sure how the relationship is setup so you'll have to work that bit out yourself!
renderer: function (value, metaData, record) {
var resultRecord = record.getResultRecord(); // replace this with correct code!
return resultRecord.get('next-date');
}

Yii2: How to avoid required fields in a view?

I have a view about holidays where a user uses a form to choose a place to travel and a hotel. It has two models: HolidaysPlaces and HolidaysHotels.
The user have to fill the form in this order using the view:
The user completes the fields called Place and City (related with the HolidaysPlaces model).
The user checked a checkbox if he/she wants to choose a hotel. It able a field called Hotel (related with HolidaysHotels model).
The user completes that field.
The user press a Create button.
The controller receives and saves both models.
But the problem is when the user doesn't select the checkbox (number 2 of the list): The Hotel fieldis still required (with the red asterisk as defined in its model file). So the Create button doesn't work in this case.
How can I disabled the required feature?
Add a scenario for this case in your HolidaysHotels model, and include only the fields that you want checked.
Example: If you have 3 fields name, date and age that are required, create a scenario for two only, and set the scenario in the controller. Only those two fields will be checked.
In model:
public function scenarios(){
$scenarios = parent::scenarios();
$scenarios['create'] = ['name', 'date'];
return $scenarios;
}
In controller:
$holiday = new HolidayHotels();
$holiday->scenario = 'create';
To know more about scenarios: http://www.yiiframework.com/doc-2.0/guide-structure-models.html#scenarios
You can add some condition based validation in your model rules. Here is the snippet for both client and server validation. You can many conditions inside the function block.
['field-1', 'required', 'when' => function ($model) {
return $model->check_box == '1';
}, 'whenClient' => "function (attribute, value) {
return $('#checkbox-id').is(':checked') ';
}"],
The easiest way to solve it is to send the model with empty strings. Then the controller checks if the strings are empty. If so, the model is not saved. Else, it is saved.
It was the only way that works for me.

Syntax for calling child relationship with a condition on the parent in Laravel

I have a model called 'Tag' which has a self-referencing 'hasMany' relationship on itself. So for example I have a tag called UK and this 'has many' child tags called London, Liverpool, Manchester etc.
Here is the relationship in the Tag model file:
public function children()
{
return $this->hasMany('App\Tag', 'tag_parent');
}
I simply want to get the list of child cities from the parent 'UK' tag. So I have this code:
$cities = Tag::where('title', 'UK')->get()->children;
I am getting an error saying children is unknown. The docs say I should do this which works as expected.
$cities = Tag::find($id)->children;
So how do I get that list of child cities with the 'where' condition? I thought Tag::find($id) was just a shortcut for Tag::where('id', $id)->get()?
UPDATE
Exact error:
ErrorException in TagController.php line 28:
Undefined property: Illuminate\Database\Eloquent\Collection::$children
As #revo mentioned, use the with method. It's called Eager Loading in Laravel.
Tag::with('children')->where('title', 'UK')->get();
This should gives you all the tags with title = UK, plus all the children that's related to each of every individual tags.
get() will always return a Collection, even if there is only one record. Since Collections do not have a children attribute, you get the "undefined property" error you are seeing.
The reason find() worked is because it returned a Tag model, which does have the children attribute.
If title is unique, you can simple change from get() to first(). first() will always return a Model instance; get() will always return a Collection.
$cities = Tag::where('title', 'UK')->first()->children;
If title is not unique, then you will need to loop through the Collection of returned Tags, and act on each set of children accordingly.
$tags = Tag::with('children')->where('title', 'UK')->get();
foreach($tags as $tag) {
$cities = $tag->children;
// do something with this set of children.
}
NB: the with('children') is added purely for performance reasons (eager loading). It does not affect the rest of the code, and could be removed without having to change anything else.

Attaching new relation and returning the model

I have a User that has many Positions. I want to update the User (the model and the relation Position), and then return the updated result.
The input will be an array of the format
{
first_name,
last_name,
email,
... (other user information),
positions : [
{
id,
name,
descriton
},
...
]
}
My update function currently is
public function update($id)
{
// This is a validation that works fine
if ( ! User::isValid(Input::all())) return $this->withValidation(User::$errors);
$user = User::with('positions')->find($id);
$new_ids = array_pluck(Input::get('positions'), 'id');
$user->positions()->sync($new_ids);
$user->update(Input::all());
return $user;
}
My User and its permissions are updated, but I still get the old $user's relationship back (i.e. the basic information is updated, and the new positions are updated in the DB, but the returned result is the NEW basic information with the OLD positions).
Right now to fix this, I recall the User::with('positions')->find($id) at the end and return that. But why isn't my code above working?
Correct, sync doesn't update related collection on the parent model.
However you should use $user->load('positions') to reload the relation, it will call only 1 query, without fetching the user again.
Also, you can call load on the Collection:
$user->positions->load('anotherRelation');
because here positions is a Collection, which have load method to lazy load all the related models for each item in the collection.
This would not work, since positions() returns relation object, not collection:
$user->positions()->load('anotherRelation');

Resources