Xem mẫu

Chapter 4 For each major entity, you should identify the tasks associated with each. You can use the table in the previous section, which identified common task and method names to help identify tasks. We have seen how to build models, views, and controllers but we have yet to see how we actually use them. To get started we need to create a PHP file named after the component in the component`s frontend folder and we need to create a PHP file named after the component and prefixed with admin.in the component`s backend folder. These files are executed when the component is invoked via the frontend and backend respectively. This example shows how we might implement one of these files: // Check to ensure this file is included in Joomla! defined(`_JEXEC`) or die(`Restricted Access`); // get the controller require_once(JPATH_COMPONENT.DS.`controller.php`); // instantiate and execute the controller $controller = new MyextensionController(); $controller->execute(JRequest::getCmd(`task`, `display`)); // redirect $controller->redirect(); You will often find that these files are relatively simple. In the above example we get the controller class file, instantiate a new controller, execute the task, and redirect the browser. The redirect() method will only redirect the browser if a redirect URI has been set; use setRedirect() to set a redirect URI and, optionally, a message. We can do far more with these files if we wish, but often we do not need to; generally, it is better to keep the processing encapsulated in controllers. It is common practice to use multiple controllers, one for each entity. These are generally stored in a folder called controllers in files named after the entity. Each controller class is named after the entity and prefixed with MyextensionController. When we use multiple controllers, we generally use the URI query request value c to determine the controller to instantiate. This demonstrates how we can deal with multiple controllers: // Check to ensure this file is included in Joomla! defined(`_JEXEC`) or die(`Restricted Access`); // get the base controller require_once(JPATH_COMPONENT.DS.`controller.php`); [ 83 ] Component Design // get controller if ($c = JRequest::getCmd(`c`, `DefaultEntity`)) { // determine path $path = JPATH_COMPONENT.DS.`controllers`.DS.$c.`.php`; jimport(`joomla.filesystem.file`); if (JFile::exists($path)) { // controller exists, get it! require_once($path); } else { // controller does not exist JError::raiseError(`500`, JText::_(`Unknown controller`)); } } // instantiate and execute the controller $c = `MyextensionController`.$c; $controller = new $c(); $controller->execute(JRequest::getCmd(`task`, `display`)); // redirect $controller->redirect(); An alternative method is to encapsulate this within another layer of inheritance. For example we could create the controller class MyextensionController and add a getInstance() method to it that will return an object of the desired subclass. This example demonstrates how we might implement such a method: /** * Gets a reference to a subclass of the controller. * * @static * @param string entity name * @param string controller prefix * @return MyextensionController extension controller */ function &getInstance($entity, $prefix=`MyExtensionController`) { // use a static array to store controller instances static $instances; if (!$instances) { $instances = array(); } // determine subclass name $class = $prefix.ucfirst($entity); [ 84 ] Chapter 4 // check if we already instantiated this controller if (!isset($instances[$class])) { // check if we need to find the controller class if (!class_exists( $class )) { jimport(`joomla.filesystem.file`); $path = JPATH_COMPONENT.DS.`controllers`, strtolower($entity).`.php`; // search for the file in the controllers path if (JFile::exists($path) { // include the class file require_once $path; if (!class_exists( $class )) { // class file does not include the class return JError::raiseWarning(`SOME_ERROR`, JText::_(`Invalid controller`)); } } else { // class file not found return JError::raiseWarning(`SOME_ERROR`, JText::_(`Unknown controller`)); } } // create controller instance $instances[$class] = new $class(); } // return a reference to the controller return $instances[$class]; } We can now alter the component root file to use the getInstance() method: // Check to ensure this file is included in Joomla! defined(`_JEXEC`) or die(`Restricted Access`); // get the base controller require_once(JPATH_COMPONENT.DS.`controller.php`); $c = JRequest::getCmd(`c`, `DefaultEntity`) $controller = MyextensionController::getInstance($c); $controller->execute(JRequest::getCmd(`task`, `display`)); // redirect $controller->redirect(); [ 85 ] Component Design This list details some important things to consider when designing and building controllers: • If you have one major entity, you should consider building one controller. • If you have a number of entities, you should consider using a separate controller for each. • To manage multiple controllers, it can be useful to create another controller, which instantiates the controllers and siphons tasks to them. • If you have a number of similar entities, you should consider building an abstract controller, which implements common tasks. Up to this point, we have hardly mentioned the back and frontends in relation to the MVC. The way in which the MVC library is constructed leads us to using separate controllers, views, and models for the front and back ends. Since we will generally be using the same data in the front and backend, we might want to use some of the same MVC elements in the frontend and backend. If you do choose to do this, it is normal to define the common MVC elements in the backend. To access models and views located in the backend from the frontend we can manually tell Joomla! about additional paths to look in. It is relatively unlikely that you would want to use the same view in the front and back-end. If you do want to do this, you should carefully consider your reasons. This is an example of an overridden controller constructor method. It tells the controller that there are other places to look for models and views. /** * Constructor * */ function __construct() { // execute parent`s constructor parent::__construct(); // use the same models as the back-end $path = JPATH_COMPONENT_ADMINISTRATOR.DS.`models`; $this->addModelPath($path); // use the same views as the back-end $path = JPATH_COMPONENT_ADMINISTRATOR.DS.`views` $this->addViewPath($path); } If we use this, the controller will look for models and views in the component`s backend folders, as well as the default frontend folders. In this example, the frontend models and views will take precedence. If we wanted the admin paths to take [ 86 ] Chapter 4 precedence, all we would need to do is move the parent::__construct() call to the end of the overridden constructor method. Rendering Other Document Types We mentioned earlier that you can create a view for the document types, feed, HTML, PDF, and RAW. We have already briefly explained how to implement views for the HTML document type. This section describes how to create feed, PDF, and RAW views. Every view, created in the views folder as a separate folder, can support any number of the document types. This table shows the naming convention we use for each. Document Type Feed HTML PDF RAW File Name View.feed.php view.html.php view.pdf.php view.raw.php Description Renders an RSS 2.0 or Atom feed. Renders a text/htmlview using the site template. Renders an application/pdf document. Renders any other type of document; defaults to text/html, but we can modify this. There is a fifth document type, error. We cannot create views within our components for this document type. The error document renders using a template from the site template or core error templates. To request a page as a different document type, we use the request value format. For example to request the component My Extension in feed format, we might use this URI: http://www.example.org/joomla/index.php?option=com_ myextension&format=feed The four document types might sound restricting. However, the RAW document type has a clever trick up its sleeve. When Joomla! encounters a unknown format, it uses the RAW document. This means that we can specify bespoke formats. We will discuss this in more detail in a moment. Feed Before you choose to create a feed view you should consider whether the data is worthy of a feed. The data in question should be itemized and it should be likely to change on a regular basis. Joomla! supports RSS 2.0 (Really Simple Syndication) and Atom (Atom Syndication Format) feeds; which is being used makes no difference as to how we build a feed view class. [ 87 ] ... - tailieumienphi.vn
nguon tai.lieu . vn