We have taken on a site written in Zend framework. We didn't write the site and haven't use the Zend framework before so I'm interested in finding three things.
How do I add new views to the site, adding in a new folder to the application/views/scripts directory seems to do nothing
Are there any tutorials on how to add affiliate feeds and setups to a zend site that you can recomend?
Are there any good tutorials on learning the framework? So far all I've found is vast amounts of material that confuses me
to answer your questions in order:
You have to find the controller, that will emerge the view you want to add. There are two ways to get a view script rendered. The first one is a naming convention on the view script. The view has to be the same name as the action name of the controller. Like "indexAction" and index.phtml. The other way is to instanciate a view object within the controller and give a string with the view name at runtime. You may want to look at this excerpt:
$view = new Zend_View();
$view->a = "Hay";
$view->b = "Bee";
$view->c = "Sea";
echo $view->render('someView.php');
which I took from http://framework.zend.com/manual/en/zend.view.controllers.html#zend.view.controllers.render
I don't think that I understand what you mean by "affiliate feed"... are you talking about advertising or is it more like content syndication?
The first thing you should read may be the Zend Framework Study Guide which you find here: http://www.zend.com/community/downloads. There are many tutorials an howtos out there but, this guide is made from Zend directly and should cover the main topics.
Regards,
Mario
Are you adding the appropriate Zend_Controller as well? The Zend_Controller QuickStart is a good place to get started with MVC.
You might also look at Zend_Tool, which provides a script to help create the necessary structure.
Basically, views need corresponding controller actions. So the main index action (located, for example, in application/controllers/IndexController.php) would need a corresponding view at /application/views/scripts/index/index.phtml.
example: To reach an action within the Index Controller named fooAction() you would need a view file at /application/views/scripts/index/foo.phtml.
example: To reach the index action of contact controller you would need the controller at /application/controllers/ContactController.php (with an indexAction() inside it) and the view at /application/views/scripts/contact/index.phtml.
Getting beyond the absolute basics... view rendering can also be turned off or redirected but that is getting beyond the basics. Also if the app uses Zend_Layout there will be a layout file located somewhere like application/layouts/scripts/layout.phtml
Clear, concise and current ZF info can be strangely hard to come by. For tutorials check out:
The ZF Quickstart
Rob Allen's tutorial
Some screencasts
For adding feeds I suppose you should check out the framework's documentation for Zend_Feed
Related
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 googled alot and couldn't come up with an answer...
I'm using the tutorial-skeleton application. It automatically includes under 'view/album/album' the html files corresponding to my actions like add or index.
I'm using a submodule and the standard loading won't find my html-files. I followed this guide for setting a custom template path. This works for the index because here I use a ViewModel instance.
But my add/delete/edit actions just return an array like this one.
Is there a way to tell Zend that it should use a different directory to look for the views?
PS: I also tried this injectTemplate approach but no luck. It just sets the Controller namespace/path which is ok in my case.
This was an project specific issue...
I used MasterData as top namespace. When creating the directory tree in my module\MasterData\view I wrote masterdata instead of master-data. This caused the not finding of my views.
A dumb one... I know.
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 have an object oriented framework that uses a page design, where each page extends a view of the framework. So, for instance, my index page for a site is actually a class that implements the abstract class View provided by the framework. I hook the framework by including a startup script at the top of the page and after some processing the framework creates an instance of the page and processes its view data. To add flexibility to the system, I don't require the class name to be the name of the file itself. This allows me to create something like a support class and have it behave as the index for the /support/ subdomain.
I was initially passing the page's class name into the framework via the framework's constructor, but this added a few more steps to the top or bottom of the page. I currently obtain the class name via a pages table in the database identified by a filtered requested URI. I use this table to build navigation and adding an extra table column was practically free. This works OK as long as I have a database connection, but I'm trying to implement static page support for status messages and error reporting, and I need another method for creating an instance of the page's class. If I use the standard convention of naming the class the file's name, then I know I have a dependable way of extrapolating the class name. I don't really want to name all my classes index just for presentation reasons. What is some advice or some standards for how object oriented frameworks are initialized?
View.inc
<?php
abstract class View
{
abstract function getView();
}
?>
Startup.inc
<?php
require_once("View.inc");
require_once("CoreController.inc");
$Framework = new CoreController();
$Framework->Initialize();
exit;
?>
index.php
<?php
require_once("Startup.inc");
class Index extends View
{
public function getView()
{
echo "<pre>View Data</pre>";
}
}
?>
Within my framework I have a TemplateController that processes the page. The page class is known because it is mapped via another class. Without a database however, I would like to discover the class within, say, index.php without changing the way it's currently set up. Here is the actual code within the TemplateController.
//Get the View Class from Page
$view = $page->getPageClass();
//We need to catch View creation failure
$this->Page = new $view($this->Framework);
//Initialize the Page View
$this->Page->Initialize();
//Cache the Page View
$this->cacheView($this->Page, $page->getPageName(), $this->SiteID.TCS_PAGE_SORTID);
In the snippet above $view is the actual name of the class that was mapped from another controller. I'm passing a reference to the framework to the view's constructor and the rest is really irrelevant. I'm trying to come up with a similar mapping technique to identify the page class in the event the database is down. I like the one include line for the framework startup and would like to keep it that simple.
At the top of the TemplateController I have to also reinclude the actual page, since my startup script is at the top, the actual class is not included even though it is the requested page.
include($_SERVER['SCRIPT_FILENAME']);
Please review Stack Overflow question Identifying class names from $_SERVER['SCRIPT_FILENAME'] for more information on what I'm attempting to do.
Here is my checklist of page routing:
Adding new page must be quick
You must not be able to add page unintentionally
Application with million pages should not be slower or more bloated than application with 2 pages
Provide simple way and let people enhance it if they want
Allow easy re-factoring, such as moving several pages into different location
Make framework detect everything. Don't force user to specify base URL, etc.
Create simple to understand page names (hello/world).
Clean illegal characters from the URL
Make it possible to add static pages easy
Provide a way to generate URLs from page names.
Allow user to use pretty URLs by changing what appears before and after the page in the URL
And most importantly
- Stop copying, think about the best approach.
All of those suggestions I have used in the PHP UI framework - Agile Toolkit where I am a contributor.
Relevant sources: Agile Toolkit - a PHP Framework with jQuery, Agile Toolkit - PageManager.php, Agile Toolkit - URL.php and Agile Toolkit - PathFinder.php.
We wanted to make it really simple for developers. And secure too. And flexible. Therefore the "page" class is selected based on the URL. How? Quite easy:
/hello.html -> page_hello
/hello/world.html -> page_hello_world
Class then is mapped into filename. page/hello/world.php
Then there are cases when we want to use dynamic URLs too, such as: /article/234
Many frameworks implement a complex techniques here (arrays, regular expressions, front-controllers). We don't. There is mod_rewrite for this. Just rewrite this into page=article&id=234 and it works. And scales.
Apart from pages, there are other classes, but those classes can't be accessed directly. Therefore pages live under the /page/ folder, do distinguish them and maintain security.
Then comes the designer saying - "I won't write PHP". So we introduce static pages. If class page_hello_world is not defined, we'll look into template/skin/page/hello/world.html. That's a easy shortcut for designers and non-developers to add a new page.
What if a page is not found? Api->pageNotFound() is called. Feel free to redefine and load pages from SQL or display 404 page with a picture of a pink elephant.
And then there are some pages which come from add-ons. We don't want to enable them by default, but instead let users add them to their app somewhere. How?
class page_hello_world extends Page_MegaPage
Next question, is how we handle sub-pages of that page, since sometimes all the functionality can't fit on single page. Well, let's add support for page_edit() method (or any page_XX) as an alias for a sub-page inside those classes. Now add-on developer can include a multifunctional page which can be extended, customized and placed anywhere in the application.
Finally there are hackers, who want to do something really fast. For them we apply same technique to the API. You can define function page_hello_world in the API, and you don't need class.
Some might say that there are too many ways to do a simple thing. Oh well.
I hope that this was helpful.
Use __autoload(). Most major PHP frameworks use autoloading to streamline class loading.
You need some way to map a URL to an object, which is usually handled by a routing component in most frameworks. Might want to take a look at libraries such as https://github.com/chriso/klein.php, or the routing components of the major Frameworks out there (Zend, Symfony, etc.).
Why not to use information from URL to detect correct class? Since you won't use database for static pages, you have to somehow store mapping between URL and class in file. I.e. you will have a file mapping.php:
return array(
'about' => 'AboutView',
'copyright' => 'CopyrightView',
);
Here, about and copyright are URL components and values represent appropriate child classes of View. You can have URL's like http://example.com/index.php?page=about and use rewriting capabilities of webserver to make them look good.
You will change implementation of Page::getPageClass() in order to return correct view class. Depending on URL it will use static mappings from the file above or use database.
What's the problem with this approach?
I am trying to use the MVC architecture of sugarcrm to add a new action and with that a new view.
I have managed to create a controller with the action and also a class view, the only thing I can't figure out is how to create a simple html page.
Do I really have to use the metada way of sugarcrm?? I just want a simple form with two or three fields.
Are there alternatives to the metadata or do I really have to use it to create my simple page????
You will want to stay within the metadata framework to create your new page if possible. However, once you are in the view controllers, you can echo out anything you wish and still stay "upgrade safe" by overriding the display() function. But, the right way to do what you are wanting to accomplish above is to not only override the display() function but also create a new tpl file (custom/modules//tpls/view.tpl) and then perform whatever you need to perform PHP wise and then assign the variables via the smarty templating engine (I know this sounds complicated - but it's not. It's actually pretty straightforward once you understand Smarty).
One other thing - make sure you are doing all of this (including your controllers and view files) in the custom/modules directory. As this will also keep things upgrade safe. And keep you free from all kinds of headaches in the future. :)
Here is a link to the SugarCRM Developer's Guide online and also a link to their Developer's website. SugarCRM has a pretty good community of developers on the forums so feel free to ask questions there as well.
Developer's Guide:
http://developers.sugarcrm.com/docs/OS/5.2/-docs-Developer_Guides-Developer_Guide_5.2-toc.html
Developer's Site:
http://developers.sugarcrm.com/
Hope this all helps!
Try to do following:
create a new module
put your page into custom/modules/
using URL index.php?module=&action= (without php extension, of course) you can access to your page.
If you'd like to have different action name and page name then you should add the file action_file_map.php
into your module directory and specify inside the mapping:
$action_file_map['action_name'] = 'path_to_your_page';
Note that action_name must be all lowercase - the SugarController won't be able to to match mixed-case actions (true as of SugarCRM 6.1.2).