This took me a while to piece together how it works and all, so here's the guide how to easily put a management form for your relationships within your current form.
For this example i'm going to assume the following:
- You know how to make a backend form
- You know how to make a controller
- You know how to make a model
- You know how to make the database/schema structure
In this example we are trying to set up a hotel, and a hotel has a lot of facilities.
The facilities have the relationship: belongsTo hotel
public $belongsTo = [ 'hotel' => [ 'ExitControl\HotelManager\Models\HotelManagerModel', ], ];
The hotels have the relationship: hasMany facilities
public $hasMany = ['facilities' => [ 'Tschallacka\HotelManager\Models\HotelFacilityModel', 'key' => 'hotel_id' ], ];
They are linked togeter by
hotel_id in the facilities(foreign key in my setup but that's not required for this to work)
Important to know
When you edit via the form we are going to make it will default save the
hotel_id in the facilities table. So there is no need to have a hotel selection form in that form. Even if you include it, any selections you make in there will be blatantly ignored.
You need to define which fields are fillable in your model. If you do not define these you'll get an error saying something along the line of
Mass assignment failed for field 'something youforgot'.
If you get this error when trying to save, copy and paste that field name into the fillables.
You need to set the fillable array in the model the "subform" belongs to. In this case
HotelFacilityModel needs to have the fields it can save/update fillable.
It's important that you use the "model" field names here. So if you defined a relationship, you need to use the relationship name instead of the database name.
protected $fillable = ['active','facility'];
In my facilities I have two fields I need to set, if it's active(yes/no) and which facility it is. The hotel entry is missing here because as I stated before, that will be filled automatically.
Making the controller behave
In the HotelController.php we need to add the behaviour RelationController to it. So in the top we add
Backend.Behaviors.RelationController to the $implement array.
public $implement = [ 'Backend.Behaviors.FormController', 'Backend.Behaviors.ListController', 'Backend.Behaviors.RelationController' // <---- ];
And we define where we can find our relationship configuration file in the HotelController
public $relationConfig = 'config_relation.yaml';
Now to create this
config_relation.yaml file you go to your \controllers\hotelcontroller directory where also your config_form.yaml resides and all the views for the forms and create there a new file called
In it post
facilities: label: Facilities manage: form: $/tschallacka/hotelmanager/models/hotelfacilitymodel/relation_fields.yaml list: $/tschallacka/hotelmanager/models/hotelfacilitymodel/relation_columns.yaml view: list: $/tschallacka/hotelmanager/models/hotelfacilitymodel/relation_columns.yaml toolbarButtons: create|delete
For other types of relations read: http://octobercms.com/docs/backend/relations#relationship-types
As you might notice I have defined here
relation_columns.yaml and you might be wondering what these fields are.
These are the exact same fields in your model for building up your form minus the hotel choosing element. So basically copy over
columns.yaml and remove the hotel field and rename them to what you defined here in the
Adding the form to your hotel management form
Now go to your PluginName\hotelmanager\hotelmanagermodel folder and open up
facilities: label: facilities span: left type: partial tab: tschallacka.hotelmanager::lang.hotelmanagermodel.hotelfacilities path: ~/plugins/tschallacka/hotelmanager/controllers/hotelcontroller/_facilities.htm
You might notice we are using a partial here instead of just adding it to the form. This is because we need to call a special piece of php code to actually render the relationship editor we just defined.
Creating the "renderer"
Go back to your
hotelcontroller directory where also your
config_relation.yaml resides and create a new file
In it put the following code:
<?= $this->relationRender('facilities'); ?>
Make sure you use here the relationship name you defined in the
relation_config.yaml. In this case
And that's it. Now you have a subform in a form.
Important nice details
If you use a seperate database connection than than default OctoberCMS install database you need to copy over the
OctoberCMS.deferred_bindings table to your other database for things to work properly.
Thanks for this, very helpful indeed!
How can you pass some data/variable to the subform?
Im trying to pass the form id so as to dynamically set the values of a dropdown in the subform.
This is a great tutorial Tschallacka - something that's very relevant to a lot of people I'm sure.
One thing I'm confused about is where it's forcing the hotel entry in the example. It is not forcing anything in the situation where I am using a relationship form and I'm not sure if it's because I'm missing something that is not explicitly stated in the tutorial.
Thanks for that tutorial:)
Tschallacka, thanks for the tutorial. When I try to create a model with a hasMany relation, the hasMany relation is created in the database but it does not display in the list view until after I save the parent model. Have you had this problem?
All other relations (besides hasMany) appear in the view upon creating the parent model. It's just the hasMany relations that don't show.
In update of the parent model, all of the hasMany relations are listed as expected. This is quite a problem when you need to enter various data and you don't remember what was already entered.
I am using a separate database so I wonder if this may cause this problem.
Could you or someone please point me in the right direction for how to solve this?
Thanks, LukeTowers. I'll do that.
But what if I have a one-to-one relationship and just want to add a set of fields (subform for the related item) inside the form instead of having a list with add/update buttons on the top?
I don't know who you are. I don't know what you do. But what I do have are a very particular set of skills; skills I have acquired over a very long career. I will look for you, I will find you, and I will buy you anything you want.
1-11 of 11