I am new to ZF and I have problem with even simple tasks.
I would like to have dynamically generated menu on every page. To do that I should fill $this->view with data. OK, but to do that, I would have to fill view separately in every controller I made. This would lead to code duplication.
The most natural solution, that I see, is to create base controller class for all my controllers, but I read, that this is not a good practice in ZF. So how should I do that? Even if it is only one line of duplicated code (eg. $this->view->menu = $reusableObject->generateMenuData()), I don't like it.
What is the best practice for such a solution? How could you solve this problem?
I am using ZF 1.11.
EDIT: I would like to mention, that I would be happy to know how to do that using some kind of phtml file rather than concatinating html tags.
EDIT2: The point is, I am not really interested in only navigation links. Instead of menu with links that could be eg. list of latest post, but on every page, so in every controller. I am particularly interested in "how to this kind of stuff in ZF".
Zend Framework has a Navigation component:
Zend_Navigation is a component for managing trees of pointers to web pages. Simply put: It can be used for creating menus, breadcrumbs, links, and sitemaps, or serve as a model for other navigation related purposes.
It also has some ViewHelpers to render various navigational elements out of it:
Breadcrumbs, used for rendering the path to the currently active page.
Links, used for rendering navigational head links (e.g. )
Menu, used for rendering menus.
Sitemap, used for rendering sitemaps conforming to the ยป Sitemaps XML format.
Navigation, used for proxying calls to other navigational helpers.
To prevent code duplication, use a Controller plugin that configures the Zend_Navigation instance and sets it to View or use Zend_Application_Resource_Navigation to configure it from your application.ini, which will then automatically assign it to the View Helpers.
Re your EDITs
You can use Zend_Navigation for arbitrary menues, not just the main navigation. Just configure it as you see fit and then render it with the appropriate helper. And if none of the Navigation helpers are what you are looking for, just write a helper or a partial that does the required output.
Whether you use a Controller Plugin to configure and inject it into the View or use a Helper that queries the Model for your Blog Post in the View Layout is up to you. Both is equally fine and possible.
Use Zend_Navigation. You can even configure it from your configuration file using the application resource plugin.
Related
I am looking for a way to have a site navigation menu which will be used primarily in a layout file which is then extended in templates.
In zend I would create a view helper which would fetch the relevant items and render the links. I currently have the menu hard coded within a twig template which is extended by others (like a layout in zend). It doesn't feel like this is the best way to do it.
I'm effectively trying to split out the code into something separate as I am using the twig url helper to generate the links.
I have looked into twig functions but they seem to be primarily used for getting data rather than rendering html snippets that can be re-used. I have also thought about creating a service which gets the array of data with titles, routes etc but I think I would then have to use this in each action where the template needed the nav menu and it feels like too much duplication as symfony doesn't have controller init methods like in zend where you could do it once for all actions.
SO my question is, what's the recommended symfony2/twig way to do this kind of thing.
I don't use Zend but in Symfony you can easily have reusable twig snippets. All you need to do is write a specific controller method and its associated twig template then call it from wherever using the render() method. Example call from a twig template with one argument:
{{ render(controller("AcmeCategoryBundle:Category:menu", { 'position': 1 })) }}
Hope this helps you.
Really not sure if the title of the question suits the question overall. But here goes.
What I have currently is an existing SaaS project. That we want to roll out a new template over time. Think of how google introduces new features. Or some other sites might with "Try our new Beta Version".. type of thing. Well we want to do the same, and then we will eventually phase out the old look and feel.
With that, this application is built on top of Zend Framework, so looking through docs I can figure out how to override the template on a given controller. But what I want to basically do, is likely going to make use of the sessions. If it exists, use this template. If not, use the old one.
Is it possible to override the default template in such a fashion? Right now for example, the default loaded file, is "tops.phtml" if the session exists I'd like to load "tops_v2.phtml" for example. So it can use that as the template instead of "tops.phtml" when the session is found.
Zend Framework 1.x solution:
You can disable ViewRenderer plugin in the action, and choose template manually:
public function indexAction(){
$this->_helper->viewRenderer->setNoRender(true);
echo $this->view->render("path/to/template/template.phtml");
}
I think that layouts are the thing you probably want to use, as was briefly touched on by Richie. Based on the question, I'm guessing you aren't already using them. Ultimately you can design a layout that defines the overall website look and then each of your action templates will only then render a fragment of the page (which will be dynamically placed in the content portion of the layout).
Using whatever logic you choose, you can then assign one of any number of layouts to be used on a given page load and of course you could store this as a user preference or something.
I have searched the web and found only styling code posts. I want to write site using Code Igniter and I wonder how should I maintain my code.
For example:
Should I use one class for static pages and methods for each page or separate file for every static page. Should I use the same file to load dynamic pages or different one?
Can I use some common code and include it automatically to every class?
How can I have lets say header_view footer_view etc and then just load->view('whatever') and footer, header and other files would load automatically. Maybe there is better way to do that?
In generall what are the best practices when coding using CodeIgniter.
You can use one single class for static pages (and use one method for each page).
You can use the same one to load dynamic pages, but it is better IMO to load them with a separate class. It will be easier to maintain later.
Using common code: You can always override the CI_Controller with your own, and instantiating controllers from yours. Here is an example about how to do it.
You can load multiple views in a single controller function. A view doesn't have to be a full html document. You can also load the same view multiple times (for example in a loop).
Best practices: CodeIgniter is an MVC framework. IMO, MVC is a best practice. Always use the framework's documented features if they are suitable for what you want to achieve (CodeIgniter's documentation is very good. That link is momentarily offline, so please try this one).
Codeigniter is a MVC based framework, MVC is basically used for organizing your code, so at last its up to you how you are going to use it so ease you on the long term.
Basically when I design large projects in codeigniter I tried to to make unit of functionality at one place lets take example of any simple users, messages based project.
I tried to make functionality by grouping main topics, in this example user will be a controller, in that controller there will be methods like login, register, edit, listing, forgot_password now I'll create single model with all the methods which will give data for these above methods. by using this methods our urls will be also meaningfull like /user/login, /user/register etc
like that if its messages I will create controller message and add all related methods in it so that my related functionality will be in a single group.
as far as the question of static pages you can also group them in a single controller if they can be a part of group.
you can also use codeigniter's caching technique for static pages so that your pages will load faster
Started an project using kostache.
I have made some partials like banner,navigatons and footer in my class View_Layout with extends kostache_layout . Partials work fine on each page.
One problem. The navigation show always the same links. My goal is to show links that are appropriate to the user who is logged. How can I put logic in the partial of navigation? I know I can write functions in the View_Layout class but View_Layout must know the user role?
Hope somebody can help me.
In mustache, partials inherit from the surrounding template's variable stack. You'd need to do this logic in your view class. If different pages need different links, do that in your specific view class.
Option 1: evolve your views
The best option would be to expand the capabilities of your views. Actually in MVC-inspired patterns the views should be instances which handle UI logic and can choose from which (usually, more then one) templates to create the response. If that response even needs to be a HTML .. maybe a simple HTP header would be enough.
The default toolset in Kohana is geared towards very simple usecases, but it is possible to expand it.
My recommendation would be start using fully implemented views.
Option 2: use HMVC
Alternatively, you can utilize HMVC capabilities in Kohana. This would mean, that you have one or few "main controllers", which then create sub-requests. The responses from those requests is passed in/bound to the template, which said controller supervise.
In you particular case the menu would be governed by separate sub-controller.
I'm using the Yii framework to develop a site that uses a 2-column layout. One column is the actual content, while the other is a menu with site links, some information about the logged in user and a list of the latest posts. The menu is present on all the pages, but it has no information that is related to the current page (or route).
Every time I render the menu I need to retrieve the list of latest posts and user-related data from the database. I'm not sure how it would be best to render this menu so that I don't repeat the code that fetches the data in every action on the site.
I have thought of a few approaches and I would like to know which one of them (if any) is the right way to handle this situation.
Fetch the data in the Controller::beforeRender method, then render the menu in a partial view which displays the data in a CClipWidget block. Then, in the layout view, display the block where the menu is supposed to be. This method works, but I feel that it's quite clunky because of the beforeRender. If I ever add a page that doesn't have the menu on it, I need to include a check for that. Also, after reading the Yii documentation, I don't understand if beforeRender() is called for renderPartial() as well, or just for render().
Keep a partial view of the menu and render it from the layout view. The data is fetched in the menu view from a static method placed somewhere else (possibly in a model). This involves writing very little code, but I'm not sure if it's good practice for the MVC paradigm. Fetching the data in the view makes me cringe a little, even though it's just calling a static function.
Turn the menu into a widget. The data is fetched in the run() method and rendered from a widget view. However, using a widget imposes a few additional restrictions. If I want to use the view that renders the latest posts in a controller, I would run into issues. Widgets cannot use renderPartial() and are forced to use render() all the time. I could work around this if I figure out how to check what is rendering the view (widget or controller) and call render() or renderPartial() appropriately. Also, the widget views have to be separate from the site views, but I could work around that by specifying the full view path, like application.views.controller.view, as clunky as it may be. Furthermore, I'm still not sure if widgets should fetch database data by themselves.
All of these methods work, but they all come with a few catches. I'm sure many sites are in the same situation and I'd like to see what the best option is.
You should be able to avoid most of the performance hit for re-requesting this data by simply caching the database results (either in memory or in files it's up to you and your set up). Here's a small, simple example:
$posts = Post::model()->cache(600)->with('comments')->findAll(array('blah=blahdyblah'));
This will cache the data returned for 10 minutes.
Here's a link to the Yii caching guide again only for completeness:
Caching Guide
To actual get this data on every page, you would better off placing the code in your own widget, and having it called somewhere in the layout file.
The widget restrictions you list can be dealt with:
Firstly when the widget renders it will only render(), but without a layout. This is fine for most cases, but if you do want a page with just that on, say you want a real render(), then do exactly that, just create a view that only calls that widget.
Secondly, There's no reason widgets have to be entirely abstracted from your application and not use its data + models. Yes it is a very nice feature that they can be 'pluggable', but it doesn't mean they have to be, you're just using them to separate code.
Lastly, if you do want to use 'some' of the data from the widget but not all, or change it slightly, the methods and views you use within the widget should be built with just enough abstraction that you can use the pieces you need separately. A good way to do this is to make good use of scopes on ActiveRecords, mini view files, and using components for larger chunks of non-data logic.
Of course if you're running really on the limit of performance and need to trim thousandths of a second off your request time then you should be looking into view caching and using fragment caching of views: