Relationships in Laravel Backpack - Not sure I understand - laravel

I installed backpack on the latest version of Laravel 6.
Upon running this command as a test:
php artisan make:migration:schema create_posts_table --schema="user_id:unsignedInteger:foreign,
name:string, slug:string, description:text, keywords:string:nullable"
The command created a Post model in Models/Post
I would like to see the names of the users from the "user" table in my "post" CRUD.
First question:
I generate my CRUD with:
php artisan backpack:crud post
I see the CRUD, at the top of the CRUD I would like to pass the users name from the User table in the select dropdown.
I tried this:
protected function setupCreateOperation()
{
$this->crud->setValidation(PostRequest::class);
// TODO: remove setFromDb() and manually define Fields
//$this->crud->setFromDb();
$this->crud->setColumnDetails([
'label' => 'User', // Table column heading
'type' => 'select',
'name' => 'user_id', // the column that contains the ID of that connected entity;
'entity' => 'backpackuser', // the method that defines the relationship in your Model
'attribute' => 'name', // foreign key attribute that is shown to user
'model' => 'App\Models\backpackuser' // foreign key model
]);
}
But I am getting the error:
Symfony\Component\Debug\Exception\FatalThrowableError
Too few arguments to function Backpack\CRUD\app\Library\CrudPanel\CrudPanel::setColumnDetails(), 1
passed in C:\laragon\www\backpack\app\Http\Controllers\Admin\PostCrudController.php on line 41 and
exactly 2 expected
My problem "I think" is related to the "'entity' => 'backpackuser',"
From what I understand I need to add the relation method here but what I don't get is that Backpack did not create it when running the first command, is this normal?
Also, which model shall I user to pass the user details into a select field?
App/User or App/Models/BackpackUser ?
Thank you.

setColumnDetails() has two parameters:
the name/key of the column you're modifying
the attributes you're modifying and their new values
It looks like you've only provided the second parameter. Hence the error "Too few arguments to function setColumnDetails(), 1
passed and
exactly 2 expected."
Try:
$this->crud->setColumnDetails('user_id', [
'label' => 'User', // Table column heading
'type' => 'select',
'entity' => 'backpackuser', // the method that defines the relationship in your Model
'attribute' => 'name', // foreign key attribute that is shown to user
]);
Pro tip: you don't need to specify the model. If on your Post model you have the backpackuser() relationship properly defined, Backpack will pick up the model from that relationship.

Yes, you should create a relationship manually and add it to the Post model.
In this case (see Users in the Posts CRUD), you need to add relation method into Post, not User.

Related

Having multiple columns (foreign keys) of the same n-n relation in Backpackforlaravel

I'm struggling with the following situation:
My entities Session & Registration are related with a many-to-many (n-n) relationship. In Registration, I have two foreign keys, player_id and hotel_id.
In the Session CrudController, I want to display the related name(s) of the Player(s) and Hotel(s).
For Player, it worked like this:
CRUD::addColumn([
// any type of relationship
'name' => 'registrations', // name of relationship method in the model
'type' => 'relationship',
'label' => 'Spieler', // Table column heading
// OPTIONAL
'entity' => 'registrations', // the method that defines the relationship in your Model
'attribute' => 'player.full_name', // foreign key attribute that is shown to user
'model' => App\Models\Registration::class, // foreign key model
]);
So I've continued to add the Hotel like this:
CRUD::addColumn([
// any type of relationship
'name' => 'registrations', // name of relationship method in the model
'type' => 'relationship',
'label' => 'Hotel', // Table column heading
// OPTIONAL
'entity' => 'registrations', // the method that defines the relationship in your Model
'attribute' => 'hotel.name', // foreign key attribute that is shown to user
'model' => App\Models\Registration::class, // foreign key model
]);
But unfortunately it doesn't work - I don't get an error message, it just keeps showing only the Player column. I think the reason for this is the same value in 'name' - because after commenting the 'name' value in Player, the Hotel information was visible. But I have no idea how to avoid it.
Currently I'm not sure if it's a bug or if I'm doing anything wrong. Would appreciate any kind of support - thanks in advance!
thank you #tabacitu, that works!
I've added
'key' => 'hotel'
and it showed up in the table.

Two fields overwriting each others values on saving in Backpack for Laravel CRUD (spatie/laravel-tags implementation issues)?

I am trying to use spatie/laravel-tags together with Backpack for Laravel. I have 2 types of tags defined. Currently I have extended the Tag model from spatie/laravel-tags as MyCategory and MyTag and added global scopes to separate the two tag types. This works to the extent that it will display the current categories and tags correctly in Backpack, but when I try to save any changes it will only save the entries in the last field, and delete everything in the first field.
Here is my current field configuration for my CRUD:
$this->crud->addField([
'name' => 'categories',
'label' => 'Categories',
'type' => 'select2_multiple',
'tab' => 'Overview',
'attribute' => 'name',
'model' => 'App\MyCategory',
'pivot' => true,
]);
$this->crud->addField([
'name' => 'tags',
'label' => 'Tags',
'type' => 'select2_multiple',
'tab' => 'Overview',
'attribute' => 'name',
'model' => 'App\MyTag',
'pivot' => true,
]);
When I check Laravel Telescope I see that the same thing happens for both fields. First all current tags (regardless of type) for the item I am saving are deleted, and the new tags from the field are added. This is then repeated for the second field, which of course deletes the tags from the first field that should also be kept.
It seems that GlobalScope on my extended Tag models does not stick around for this part. Is there any way to reintroduce the scopes into the queries run by backpack to get these tags to save correctly?
In my CrudController I created custom update and store functions. See the update example below. This seems to work fine. There are still 2 queries being run, with the second one undoing the first one, but for my purposes this is a good enough workaround to be able to have 2 fields with different tag types in the same form in Backpack, using spatie/laravel-tags.
public function update(UpdateRequest $request)
{
$request = request();
// Merge the values from the two tag fields together into the second field
$request->merge(['tags' => array_merge((array)$request->input('categories'), (array)$request->input('tags'))]);
$redirect_location = $this->traitUpdate($request);
return $redirect_location;
}

Adding Columns with nested relationships in backpack for laravel

I have 3 models created in backpack for laravel CRUD:
Driver, Municipality and Province.
Driver has a 'municipality_id' and the relationship function:
public function municipality()
{
return $this->belongsTo('App\Models\Municipality');
}
To get the province of the driver i need to use a relationship function inside Municipality model:
public function province()
{
return $this->belongsTo('App\Models\Province');
}
The driver model does not contain the province function so i have to to something like
$objdriver->municipality->province->name;
To get the province name.
Now the problem is that i have to add 2 columns in the table created by artisan that display the municipality name and the province name.
For the municipality it's easy and i did it like this:
$this->crud->addColumn('municipality_id', [
// 1-n relationship
'label' => "Comune", // Table column heading
'type' => "select",
'name' => 'municipality_id', // the column that contains the ID of that connected entity;
'entity' => 'municipality', // the method that defines the relationship in your Model
'attribute' => "name", // foreign key attribute that is shown to user
'model' => "App\Models\Municipality", // foreign key model
]);
And it works Fine, but how do i add a column for the Provinces? Since the method is not in the driver model i can't use the same approach.
I already tried using a custom function to fetch what i need from the province table, something like:
$this->crud->addColumn('province_id', [
// run a function on the CRUD model and show its return value
'name' => "province_id",
'label' => "Provincia", // Table column heading
'type' => "model_function",
'function_name' => 'GetProvinceName', // the method in your Model
])
where GetProvinceName is:
public function GetProvinceName()
{
return $this->municipality->province->name;
}
but that just gives out an error.
You could try the following code.
$this->crud->addColumn([
'name' => 'municipality.province.name', // the relationships are handled automatically
'label' => 'Provincia', // the grid's column heading
'type' => 'text'
]);

Laravel Backpack select2_multiple not Displaying Correctly

I'm working with Backpack for Laravel, and implemented a select2_multiple field. The field works correctly, though it doesn't display properly at all. It's defined as:
$this->crud->addField([ // Select2Multiple = n-n relationship (with pivot table)
'label' => "Categories",
'type' => 'select2_multiple',
'name' => 'categories', // the method that defines the relationship in your Model
'entity' => 'categories', // the method that defines the relationship in your Model
'attribute' => 'title', // foreign key attribute that is shown to user
'model' => "App\Models\Category", // foreign key model
'pivot' => true // on create&update, do you need to add/delete pivot table entries?
]);
The pivot tables exist, as do the relationships on the models. The field shows for a second, and then in quickly hidden on page load (I guess by some JS). You can see below the 'categories' label, there's just white space:
I can, however, click in the white space and it will then appear and allow me to select categories as expected (though it displays rather strangely):
This is all default functionality, I haven't edited the select2_multiple template or any of the JS. Why is this displaying so poorly?
I believe it was a bug that has since been fixed. A composer update should fix it for you.
Is the model correct?
Maybe should be
'model' => "App\Category", // foreign key model

Validate field as unique with scope in cakephp

I am creating a CakePHP application which have an edit form which contain one text box named air_id. In my table I am using project_id and air_id as composite primary key. So while updating air_id I need to validate uniqueness.
My table structure is like:
project_id air_id
1 test#test.com
1 test1#test.com
Currently I am using cakephp3.0 and I am using validateUnique rule with scope,
Following is my code:
$validator
->add('air_id', [
'unique' => [
'rule' => ['validateUnique', ['scope' => 'project_id']],
'provider' => 'table',
]
]);
And my controller is like this
$projectCustomers = $this->ProjectCustomers->newEntity($formData);
Now it is giving validation message every time. What I need is when I change the value test#test.com to test1#test.com it should raise the error and if I change it to some other value it should not raise the error. Is there something wrong in my validation?
CakePHP Unique Field Rules:
We have cakephp unique field rules that might be even better:
In your table(eg. UsersTable.php):
public function buildRules(RulesChecker $rules)
{
$rules->add($rules->isUnique(
['air_id', 'project_id'],
'Your validation error here.'
));
return $rules;
}
At the top of your table , don't forget to include this class:
use Cake\ORM\RulesChecker;
See Here (CakePHP Unique Fields Rules).

Resources