cakePHP: how to combine two or more application views on one cakePHP layout page? - cakephp

Using cakePHP my goal is to combine the index view of two or more controllers in one layout page.
Example:
I have controllers for: news, events, links.
I want to show the last five entries from each table in one layout page.
Also, when one of the links from the views is selected it should take the user to the respective view for that record.
I have read through the books section on views but don't see how making a view into an element would accomplish this.
What confuses me is how to combine from three separate controller/views into one layout?
Thanks

Create methods in your News, Event and Link models for fetching the last 5 records. Then in your controller either include the models in the Controller::uses property, or in the action use ClassRegistry::init() to get access to the model, e.g.
function my_action() {
$news = ClassRegistry::init('News')->getRecent();
$events = ClassRegistry::init('Event')->getRecent();
$links = ClassRegistry::init('Link')->getRecent();
$this->set(compact('news', 'events', 'links'));
}
You can then call these model methods from any controller action, keeping your application DRY.
In your my_action.ctp view, and indeed many other views, just render the elements e.g.
// my_action.ctp
<?php
echo $this->element('recent_news');
echo $this->element('recent_events');
echo $this->element('recent_links');
?>
Your elements can then just iterate over the $news (or whatever) variable displaying the items with links to the 'view' actions in their respective controllers.
Just because a controller matches a model, doesn't mean you can't use other models in it.

First I would say that views and controllers are not necessarily tied together -- Cake will implicitly add the view specified by the file heirarchy / naming convention, but this doesn't necessarily have to be the case. So try to think of the views as decoupled from the controller (which is one of the main purposes for using the MVC architecture).
Assuming your three views (A,B,C) are exactly how you want them copied, put them into an element (which is just a view file located in the special APP/views/elements/ directory). Now you can use them in either layouts or other views, just by making a call to $this->element( 'elementName', array( 'options' ) ).
Basically, just abstract the code you want to display into elements, then insert those elements into the desired layouts.

You can set up your controller to use the RequestHandler and then make your view elements capable of fetching their own data from separate controllers in your application.
This link explains it better than I can
http://bakery.cakephp.org/articles/view/creating-reusable-elements-with-requestaction
One thing to keep in mind is that the controller actions you are calling should account for caching their own data so you don't do unnecessary database queries.

Related

Template and model reuse in Wagtail

I am building a fairly basic Wagtail site and have run into an issue regarding the reuse of models and templates.
Say my site has two kinds of entries:
blog posts and
events.
Both pages look the same and share many model fields (e.g., author, category, intro, etc.). However, there are some model fields that only make sense for the event entry type (e.g., event_date, event_venue).
What would be the ideal way of creating templates and models for this use-case without repeating myself in the code?
Right now, both blog and event entries use the same HTML template and the same model. However, when the user creates a blog post in the Wagtail admin, he or she has to "ignore" the event-specific fields (which may become even more in the future).
Do I have to create two separate template files and two separate models despite both blogs and events being 95% the same code? What would be the correct way to solve this in Wagtail?
If you want to maintain it the way it is, contained within one model and template, you could create separate model admins for each pseudo-type (Blogs and Events), and override the queryset function to make each separate modeladmin only show the ones you're looking for, and then edit the panels that are shown on create/edit/delete.
class EventAdmin(ModelAdmin):
...
panels = [
FieldPanel('your_field'),
...
]
def get_queryset(self, request):
qs = super().get_queryset(request)
events = qs.filter(your_field__isnull=False)
return events
More information at https://docs.wagtail.io/en/stable/reference/contrib/modeladmin/index.html

CAKEPHP - Including view into another view

I have a controller for posts and an element for comments. I want to include the posts view somehow in comment element. Is this possible to include the PostsController view into an element?
I know how to include elements but never heard or thought of including Controller views.
You can get the data for the PostsController view using requestAction. If you want to include view-layer code in two different places, pull it into an element - that's what they're for.

Cakephp 1.2 Pagination

I need a custom query pagination in CakePHP 1.2.
I have a reviews model and on one set of pages, it paginates the reviews model one way, and on another set of pages it does it another way with a different custom query. How do I overwrite paginate and paginateCount twice in the same model?
IMHO
I wouldn't do it in the same model.
I would have two different models with different overwrites depending on your requirements and use them in the paginate method accordingly.
Something like.
$this->paginate('Superreviews');
$this->paginate('Normalreviews');
Obviously in both model classes you would have:
var $name = 'Review';
HTH

cakephp AVOIDING repetitive .ctp files

Many models in my app are similar, and I've automated the creation of each CTP for the standard CRUD for each. In other words, the ctp files themselves for each model are identical. I pass the fields used to create the form as an array to a helper. I find though I'm just creating the same files over and over in separate view directories. Is there a way I can refer to say 1 add.ctp for each of the model controllers? I hope my question is clear enough. Thanks.
$this->render('/controller/view');
You can render any view from any controller, so if you want to create one "index" view and its generic enough that you are just passing $data in, you could render the same view each time.
You could take it one step further and create that view in your elements folder to completely detach it from your controllers.
http://book.cakephp.org/view/980/render
https://github.com/infinitas/infinitas/blob/beta/app_controller.php#L389

Has CakePHP anything like Symfony's partials?

If you want to reuse code in views Symfony has two basic mechanisms: partials and slots. Partials are nice because you can define global partials (you can use them in any module) and module partials (they are only available in a certain module).
However, in CakePHP you only have regular templates and elements, the latter being available in every view, no matter which model/controller you are in.
Does CakePHP have anything like Symfony's partials? It would nice for example to avoid duplicating forms code for a model. You can have two templates (add and edit) that "include" a common form.
I know you can still use elements, but having a "local" elements directory for a module seems to keep things more organized. Can you suggest a workaround to simulate this?
Thanks!
Why not create a view (module_partial.ctp) inside the controller specific view directory. This will keep the code specific to the controller you want it to pertain to. So lets say you have a books controller. You want to add a BooksController specific form to some of your books views.
Create a view in the views/books/ directory called: search_partial.ctp
The search_partial.ctp will contain the HTML code you want.
Then, in any view, just call:
<?php echo $this->render('search_partial'); ?>
This will not prevent other controllers views from loading it, but it keeps the code base readable and segregated as you expect.
ALL of the globals would go into views/elements.
You can put elements in plugins.
You can do something like $this->element('something'); in the layout and have the element in a plugin and/or the main app views folder like such...
App/plugins/a_plugin/views/elements/something.ctp //only called when a controller from 'a_plugin' is called.
App/views/elements/something.ctp // called if the current plugin does not have 'something.ctp' in the elements folder
For not duplicating views like add/edit look at this https://github.com/infinitas/infinitas/blob/beta/app_controller.php#L389

Resources