New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
relatedModels in Crud.View? #402
Comments
related models is for sending the required data to the forms for generating select lists. Currently it has no effect on |
Thank you. That is clear regarding relatedmodels in docs, but I felt a need to confirm since elsewhere in the docs it states that actions are by default compatible with baked views. But views are correctly baked with contain logic, which the actions do not support ... |
Could someone please update the docs that in a view action, you will not get related entities in your returned entities? I just spent well over an hour banging my head against a wall wondering why the query for the related entity was returning, but was NOT being added to my output. I finally came in here read this and facedesked... |
@dingonv feel free to PR, documentation can be found in the |
See the Introduction paragraph in the docs http://crud.readthedocs.org/en/latest/listeners/related-models.html |
IMO the relatedModels docs are fine. Not to diminish the excellent work here, but the find()->contain logic is so fundamental to cake actions, that it is easily assumed that it must be supported by crud actions. Like dingonv, I banged my head against the wall for a while thinking I had some issue with my code. I submitted a PR updating the doc intro page, specifically noting this limitation (which I assume will be addressed in the future) where the intro claims compatibility with baked views. If you are not containing related objects in your queries, then you are not truly compatible with baked views IMO. |
Adding a contain is easy enough, but it would be nice to have a global option for the component to turn on getting related data by default, that's for sure. |
How do you add a contain? http://crud.readthedocs.org/en/latest/search.html?q=contain&check_keywords=yes&area=default |
You can use beforeFind or beforePaginate events. The whole of Crud is powered by events, so if you want to change it's behaviour somehow you'll want to listen for an event. public function index()
{
$this->Crud->on('beforePaginate', function(\Cake\Event\Event $event) {
$this->paginate['contain'] = ['Users'];
});
return $this->Crud->execute();
} |
Thank you! ... And I will close the PR. Maybe your example above (which I assume would be a common use case) could appear in the docs? This way my "contain" search of the docs would have provided a hint ... Also I like the idea of a global contain "switch" to mimic "bin/cake bake controller" functionality. I think my problem was that my ORM almost always contains lots of associations and I was so used to baking the controllers that I assumed similar "default" functionality. FWIW note that a baked controller's view action is probably shorter/simpler than the necessary customized view action required to use crud view with the beforeFind event if you want the contained data! But I get it ... crud is a lot more than just that! Anyway, keep up the good work! |
I copied and pasted it from the docs, just changed the array that's all. If you add the RelatedModels listener globally, that will take care of about 90% of the related data needs. |
To be clear: We are on the same team here ... However, just sayin': If you need relatedModels globally, that implies you have relations. If you have relations, relatedModels does not take care of 90% of your needs: You are more than likely going to need customized actions with beforeFind / beforePaginate events in your controller(s). And if you are using default baked views, both the view and edit actions will definitely require customized actions with beforeFind events to be compatible with those views. FWIW I am a RTFM guy, but when I evaluated crud, I gave it 30 minutes for a "hello world", and find()->contain is "hello world" for any project I am working on. I searched both the docs and repository code for "contain" to attempt to reverse engineer what I assumed was my issue. Saw events in docs, but did not think I would need to go there to just "light up" my baked views. Sounds like the other user in the thread (dingonv) found the same rabbit hole ... |
I actually had a stab at this myself, #304 Reckon that might need adding to the docs. I'll create a new issue for this update to the docs. |
Hey guys, just so its out there. What i was looking for was the associated data for an event, which links to organizations and locations. on a get to /events/:id i wanted the event and the associated sub entities of organization and location attached as properties to the event. What i ended up doing was flat out copying the relatedModels listener, changing it's namespace to App\Listener, editing it to change the find method to all instead of list. public function initialize() {
parent::initialize();
$this->Crud->addListener('relatedModels','App.RelatedModels');
$this->Auth->allow([]);
} and since i only wanted this in my view action, i made my beforeFilter look like this: public function beforeFilter(\Cake\Event\Event $event) {
parent::beforeFilter($event);
$this->Crud->listener('relatedModels')->relatedModels(['Organizatons','Locations'], 'view') ;
} Then finally, to get the details on the Organization and Location, and to filter the fields i wanted to show, this is how my view action came out: public function view($id = null) {
$user = $this->Auth->identify();
$event = $this->Events->get($id);
$related['organization'] = $event->organization_id;
$related['location'] = $event->location_id;
$this->Crud->on('relatedModel', function($event) use ($related) {
if($event->subject()->association->name() === 'Organizations') {
$event->subject()->query->where(['Organizations.id' => $related['organization']]);
}
if($event->subject()->association->name() === 'Locations') {
$event->subject()->query->where(['Locations.id' => $related['location'] ])
->select(['id','name','address1','address2','city','state','zip']);
}
});
$this->Crud->on('beforeRender', function($event) {
});
return $this->Crud->execute();
} I don't know if there is a simpler way to do this, but this is straightforward enough for me at the moment, and gets the entities i expect, and the fields i expect. |
Doh! I think you just need something like:
|
I tried that. it wasn't processing the contain properly. It may be that i was missing something else and just tired, but at 10 at night after putting dents in the wall, when you find a solution, you go with it ;) I may try that again, but at this point, I am moving on because I want to finish this project and get my life back ;) |
👍 |
I think a small blurb at the end of the quickstart pointing out baseline On Tue, Mar 22, 2016 at 12:18 PM, David Yell notifications@github.com
|
To add contains to a beforeFind you need to add them to the query. $this->Crud->on('beforeFind', function(\Cake\Event\Event $event) {
$event->subject()->query->contain(['Organizations', 'Locations']);
}); http://crud.readthedocs.org/en/latest/events.html#crud-beforefind |
Turns out you're right @thumbtech. Crud will do this for |
... nor for edit, in my experience |
AppController includes:
I have a belongsToMany relationship that is correctly handled by Crud.Add & Crud.Edit (i.e., the related data is displayed in a multi-select list and the selected items are saved to the DB).
Now I just want to view the related data in the view. The baked view template is looking for the data, but Crud.View is not querying for it. This seems to be the (odd) default behavior according to doc ...
So now I am setting my AppController to:
But still no related data.
This seems pretty hard vs. just baking the controller ... Or?
So if src/Model/Table/ContactsTable.php =
then the baked controller's view action obviously includes the contain:
Should Crud.View know to do the same?
The text was updated successfully, but these errors were encountered: