官术网_书友最值得收藏!

The Magento version of MVC

If you are familiar with traditional MVC implementations such as CakePHP or Symfony, you may know that the most common implementation is called a convention-based MVC. With a convention-based MVC to add a new Model, or let's say a Controller, you only need to create the file/class (following the framework conventions); the system will pick it up automatically.

Magento on the other hand uses a configuration-based MVC pattern, which means creating our file/class is not enough; we have to tell Magento explicitly that we have added a new class using configuration files written in XML.

Each Magento module has a config.xml file that is located under the module's etc/ directory and contains all the relevant module configurations. For example, if we want to add a new module that includes a new model, we need to define a node in the configuration file that tells Magento where to find our model. Here's an example:

<global>
…
<models>
     <group_classname>
          <class>Namespace_Modulename_Model</class>
     <group_classname>
</models>
...
</global>

Although this might look like additional work, it also gives us a huge amount of flexibility and power. For example, we can rewrite another class by using the rewrite node:

<global>
…
<models>
     <modulenamemodulename>
      <rewrite>
             <groupgroup_classname>Namespace_Modulename_Model</groupgroup_classname>
      </rewrite>
     <//modulename>
</models>
...
</global>

Magento will then load all the config.xml files and merge them at runtime, creating a single configuration tree.

Additionally, modules can also have a system.xml file that is used to specify configuration options in the Magento backend, which end users can in turn use to configure the module functionality. A snippet of a system.xml file will look like this:

<config>
  <sections>
    <section_name translate="label">
      <label>Section Description</label>
      <tab>general</tab>
      <frontend_type>text</frontend_type>
      <sort_order>1000</sort_order>
      <show_in_default>1</show_in_default>
      <show_in_website>1</show_in_website>
      <show_in_store>1</show_in_store>
      <groups>
       <group_name translate="label">
         <label>Demo Of Config Fields</label>
         <frontend_type>text</frontend_type>
         <sort_order>1</sort_order>
         <show_in_default>1</show_in_default>
         <show_in_website>1</show_in_website>
         <show_in_store>1</show_in_store>  
   <fields>
          <field_name translate="label comment">
             <label>Enabled</label>
             <comment>
               <![CDATA[Comments can contain <strong>HTML</strong>]]>
             </comment>
             <frontend_type>select</frontend_type>
             <source_model>adminhtml/system_config_source_yesno</source_model>
             <sort_order>10</sort_order>
             <show_in_default>1</show_in_default>
             <show_in_website>1</show_in_website>
             <show_in_store>1</show_in_store>
          </field_name>
         </fields>
        </group_name>
       </groups>
    </section_name>
  </sections>
</config>

Let's break down each node function:

  • section_name: This is just an arbitrary name that we use to identify our configuration section. Inside this node, we will specify all the fields and groups for the configuration section.
  • group: Groups, as the name implies, are used to group configuration options and display them inside an accordion section.
  • label: This defines the title or label to be used on the field/section/group.
  • tab: This defines the tab on which the section should be displayed.
  • frontend_type: This node allows us to specify which renderer to use for our custom option field. Some of the available options are as follows:
    • Button
    • Checkboxes
    • Checkbox
    • Date
    • File
    • Hidden
    • Image
    • Label
    • Link
    • Multiline
    • Multiselect
    • Password
    • Radio
    • Radios
    • Select
    • Submit
    • Textarea
    • Text
    • Time
  • sort_order: This specifies the position of the field, group, or section.
  • source_model: Certain type of fields, such as a select field, can take options from a source model. Magento already provides several useful classes under Mage/Adminhtml/Model/System/Config/Source. Some of the classes we can find are as follows:
    • YesNo
    • Country
    • Currency
    • AllRegions
    • Category
    • Language

Just by using XML, we can build complex configuration options for our modules right on the Magento backend without having to worry about setting up templates, populating fields, or validating data.

Magento is also kind enough to provide a comprehensive amount of form field validation models that we can use with the <validate> tag. Among the field validators we have the following options:

  • validate-email
  • validate-length
  • validate-url
  • validate-select
  • validate-password

As with any other part of Magento, we can extend source_models, frontend_types, and validators, and even create new ones. We will be tackling this task in a later chapter, where we will create a new type of each. For now, we will explore the concepts of models, views, file layouts, and controllers.

Models

Magento makes use of the ORM approach, although we can still use Zend_Db to access the database directly. We will be using models to access our data most of the time. For this type of task, Magento provides the following two types of models:

  • Simple models: These model implementations are a simple mapping of one object to one table, meaning our object attributes match each field and our table structure
  • Entity Attribute Value (EAV) models: These type of models are used to describe entities with a dynamic number of attributes

Magento splits the model layer in two parts: a model handling the business logic and a resource handling the database interaction. This design decision allows Magento to support multiple database platforms without having to change any of the logic inside the models.

Magento ORM uses one of PHP's magic class methods to provide dynamic access to object properties. In the next chapter, we will look into models, the Magento ORM, and the data collections in more detail.

Note

Magento models don't necessarily have to be related to any type table in the database or an EAV entity. Observers, which we will be reviewing later, are perfect examples of these type of Magento models.

Views

The view layer is one of the areas where Magento truly sets itself apart from other MVC applications. Unlike traditional MVC systems, Magento's view layer is pided into three different components:

  • Layouts: These are XML files that define block structures and properties, such as name and which template file to use. Each Magento module has its own set of layout files.
  • Blocks: These are used in Magento to reduce the burden on the controller by moving most of the logic into blocks.
  • Templates: These are PHTML files that contain the HTML code and PHP tags required.

Layouts give the Magento frontend an amazing amount of flexibility. Each module has its own layout XML files that tell Magento what to include and render on each page request. By using the layouts, we can move, add, or remove blocks from our store, without worrying about changing anything else other than our XML files.

Dissecting a layout file

Let's examine one of the Magento core layout files, in this case, the catalog.xml file:

<layout version="0.1.0">
<default>
    <reference name="left">
        <block type="core/template" name="left.permanent.callout" template="callouts/left_col.phtml">
            <action method="setImgSrc"><src>images/media/col_left_callout.jpg</src></action>
            <action method="setImgAlt" translate="alt" module="catalog"><alt>Our customer service is available 24/7.Call us at (555) 555-0123.</alt></action>
            <action method="setLinkUrl"><url>checkout/cart</url></action>
        </block>
    </reference>
    <reference name="right">
        <block type="catalog/product_compare_sidebar" before="cart_sidebar" name="catalog.compare.sidebar" template="catalog/product/compare/sidebar.phtml"/>
        <block type="core/template" name="right.permanent.callout" template="callouts/right_col.phtml">
            <action method="setImgSrc"><src>images/media/col_right_callout.jpg</src></action>
            <action method="setImgAlt" translate="alt" module="catalog"><alt>Visit our site and save A LOT!</alt></action>
        </block>
    </reference>
    <reference name="footer_links">
        <action method="addLink" translate="label title" module="catalog" ifconfig="catalog/seo/site_map"><label>Site Map</label><url helper="catalog/map/getCategoryUrl" /><title>Site Map</title></action>
    </reference>
    <block type="catalog/product_price_template" name="catalog_product_price_template" />
</default>

Layout blocks comprise three main XML nodes:

  • Handle: Each page request will have several unique handles. The layout uses these handles to tell Magento which blocks to load and render on a per page basis. The most commonly used handles are the default handle and the [frontname]_[controller]_[action] handle.
  • The default handle is especially useful to set global blocks, for example, adding CSS or JavaScript to all pages on the header block.
  • Reference: A <reference> node is use to make references to a block. It is useful for the specification of nested blocks or modifying an already existing block. In our example, we can see how a new child blocks being specified inside <reference name="left">.
  • Block: The <block> node is used to load our actual blocks. Each block node can have the following properties:
    • type: This is the identifier for the actual block class. For example, catalog/product_list makes reference to the Mage_Catalog_Block_Product_List.
    • name: This is the name used by other blocks to make a reference to this block.
    • before/after: These properties can be used to position the blocks relative to other block position. Both properties can use a hyphen as value to specify if the module should appear at the very top or the very bottom.
    • template: This property determines the .phtml template file that will be used to render the block.
    • action: Each block type has specific actions that affect the frontend functionality. For instance, the page/html_head block has actions to add CSS and js (addJs and addCss).
    • as: This is used to specify the unique identifier that we will be using to call the block from the template. For example, calling a child block by using getChildHtml('block_name').

Blocks are a new concept that Magento implements in order to reduce the controller load. They are basically data resources that communicate directly with the models that manipulate the data if needed and then pass it to the views.

Finally, we have our .phtml files. Templates contain HTML and PHP tags and are in charge of formatting and displaying the data from our models. Let's take a look at a snippet from the product view template:

<p class="product-view">
...
    <p class="product-name">
        <h1><?php echo $_helper->productAttribute($_product, $_product->getName(), 'name') ?></h1>
    </p>
...           
    <?php echo $this->getReviewsSummaryHtml($_product, false, true)?>
    <?php echo $this->getChildHtml('alert_urls') ?>
    <?php echo $this->getChildHtml('product_type_data') ?>
    <?php echo $this->getTierPriceHtml() ?>
    <?php echo $this->getChildHtml('extrahint') ?>
...

    <?php if ($_product->getShortDescription()):?>
        <p class="short-description">
            <h2><?php echo $this->__('Quick Overview') ?></h2>
            <p class="std"><?php echo $_helper->productAttribute($_product, nl2br($_product->getShortDescription()), 'short_description') ?></p>
        </p>
    <?php endif;?>
...
</p> 

The following is a diagram displaying the MVC model:

Controllers

The Magento MVC controllers are designed to be thin controllers. Thin controllers have little business logic and are mostly used to drive the application requests. A basic Magento controller action will just load and render the layout:

    public function viewAction()
    {
        $this->loadLayout();
        $this->renderLayout();
    }

From here, it is the job of the blocks to handle the display logic to get the data from our models, prepare the data, and send it to the views.

主站蜘蛛池模板: 石狮市| 平谷区| 昌黎县| 灵寿县| 祁门县| 大埔县| 油尖旺区| 盐城市| 东海县| 阿巴嘎旗| 合川市| 高雄市| 合阳县| 靖远县| 东辽县| 育儿| 新营市| 英吉沙县| 棋牌| 昭通市| 大竹县| 城口县| 青阳县| 体育| 营口市| 繁峙县| 朝阳县| 察隅县| 长岛县| 宁武县| 北流市| 绍兴市| 邢台市| 福泉市| 泸州市| 伽师县| 维西| 鄢陵县| 前郭尔| 堆龙德庆县| 利辛县|