0

Magento开发系列之八 后台配置开发

Posted by Alan on August 13, 2015 in Coding, Magento |

Magento系统中另一个强大的组件是后台Admin的系统配置部分,开发过程中需要让用户可以通过在后台配置系统和自建模块来进行设置。 首先创建一个app/code/local/Alanhou/Helloworld/etc/system.xml文件,和全局配置相似,系统配置信息将单独存储。如果想要查看系统配置文件 ,可以在任意控制器Action中添加如下 代码并执行(这里在前面创建的添加到Helloworld下的IndexController>indexAction方法内): loadModulesConfiguration方法会查找所有模块下的etc文件夹是否包含所传入的文件名称(这里传入的是system.xml)。Magento中实际上有很多配置文件如api.xml, wsdl.xml, wsdl2.xml, convert.xml, compilation.xml, install.xml等,开发者可以通过创建自己的配置文件来实现更多的功能。输出结果如下: 本例中我们首先将在系统配置中添加自己的选项卡,这里说的选项卡是指在后台System > Configuration下左边的导航,默认的有General, Catalog, Customers, Sales, Services和Advanced。我们将创建的选项卡名称为Hello Config,在system.xml中加入如下代码: 代码中的<helloconfig />标签名是任意选定的,但不应与其它选项卡重复,这用于标识配置应用于的选项卡。module=”helloworld”属性表示所属模块,<label>定义选项卡显示的名称。<sort_order>表示选项卡在左侧导航中显示的位置,此时访问后台System > Configuration,会出现如下报错: 和大多数流行的PHP MVC系统一样,Magento也会使用Helper类,主要用于处理一些不宜放在Model, View或Controller处理的任务。Helper类是一种抽象类群的名称,也就是说系统用户可以重载默认类,此外模块开发者也需要在config.xml中添加一个代码块来指定Helper的基类名称。 很多系统代码都会假定每个模块有个默认的Helper类,所以出现上面报错的原因是因为在Helloworld模块中并没有默认Helper类而系统尝试调用该类。所似接下来我们在config.xml里加入如下代码: 基中的<helloworld />标签就是模块名,<class />标签则包含的是Helper类的基础名称,通常按照Packagename_Modulename_Helper的方式命名。Helper通过全局Mage对象的静态方法helper来加载,以本例而言 会加载以下文件中的以下类 Magento中还有一个模块默认类的概念,比如只传入模块名时 会加载以下文件中的以下类 也就是说下面两个是等价的 下面我们在app/code/local/Alanhou/Helloworld/Helper/Data.php中加入如下代码 现在我们清除缓存重新访问System > Configuration报错就会消失,但是并不会显示新创建的选项卡。那么接下来我们就来查看为什么新的选项卡没有显示,每个选项卡中都有多个版块(Section),比如Advanced下有Admin, System, Advanced和Developer。那如果选项卡没有添加版块选项也是不显示的,下面我们就在system.xml中添加 代码段 与标签相似,<helloworld />标签也是任意命名用于标识新的section;标签定义在后台显示的名称;用于指定section添加到哪个选项卡下,这里使用了新创建的;在其它的section有着特别的作用,但在这里没有特别的意义,Core模块中的section会用到这个标签,所以建议也照旧添加这个标签;标签决定了这个版块在垂直方向上的显示顺序;<show_in_default />,<show_in_website /> ,<show_in_store /> 中传入的为布尔值1或0,表明section的作用范围。 重新访问System > Configuration,就会在左侧导航中显示新添加的选项卡和section: 如果点击左侧的Hello World Config Options,会出现空白页面,并且左侧的导航会消失,这主要是因为Adminhtml应用在ACL(Access Control […]

Tags: , , ,

0

Magento开发系列之七 EAV-更高级的ORM

Posted by Alan on August 13, 2015 in Coding, Magento |

前面关于ORM的章节我们讲述了在Magento中有两种模型,一种是普通模型,另一种是EAV(Entity Atrribute Value)模型。本节我们就来进一步的了解EAV模型。 在Magento中所有与数据库交互的模型都继承自Mage_Core_Model_Abstract, Varien_Object,而普通模型与EAV模型的区别在于模型资源。所有的资源都继承基础类Mage_Core_Model_Resource_Abstract,普通模型有一个继承自Mage_Core_Model_Resource_Db_Abstract的资源,而EAV模型则有一个继承自Mage_Eav_Model_Entity_Abstract的资源。 那么什么是EAV呢?维基百科上的解释是: Entity–attribute–value model (EAV) is a data model to describe entities where the number of attributes (properties, parameters) that can be used to describe them is potentially vast, but the number that will actually apply to a given entity is relatively modest. In mathematics, this model is known as a […]

Tags: , , ,

0

Magento开发系列之六 安装、升级脚本

Posted by Alan on August 10, 2015 in Coding, Magento |

在任何高效的软件开发项目中,保持开发库和线上库同步都会是一件棘手的事情。Magento通过在系统中创建带有版本号的资源迁移脚本来让这种开发过程更加的顺畅。前面有关ORM的章节我们创建了一个weblog模型,那时我们使用CREATE TABLE语句直接在数据库中创建表格,今天通过对模块的资源配置(Setup Resource)来创建数据表。我们还会在模块中创建升级脚本来完成对已创建模型的升级。主要有以下几步: 在配置文件中添加Setup资源 创建资源类文件 创建安装脚本 创建升级脚本 我们还是在上一节创建的weblog模块中进行修改,在config.xml的<global />标签内添加以下代码: <weblog_setup>标签用于标识这个安装资源,通常也建议使用modelname_setup的命名机制。<module>Alanhou_Weblog</module>的内容应为模块的命名空间和模块名Packagename_Modulename。<class>标签中包含的是我们将要为Setup资源创建的类名,对于普通的setup脚本可以不自建类,但现在这么做会给以后的开发带来更大的灵活性。 添加完上面的代码后清除缓存并加载Magento中的任意页,会出现如下提示: 创建app/code/local/Alanhou/Weblog/Model/Resource/Setup.php并加入如下代码: 重新访问任意页,前面的报错会消失页面正常显示。 下面我们来创建安装脚本,这个脚本中将包含初始化模块时所需的CREATE TABLE及其它SQL语句。首先让我们来看一下config.xml文件 这段代码在所有的config.xml文件中都需要添加,主要用于确定模块及版本号。我们的安装脚本就需要用到版本号,本例将假设初使版本号为0.1.0。创建app/code/local/Alanhou/Weblog/sql/weblog_setup/mysql4-install-0.1.0.php文件并加入如下代码: 目录名weblog_setup需要与conifg.xml中的标签<weblog_setup />相同,而文件名称中的0.1.0则应与模块的版本号相同,刷新缓存并访问任意页面会得到如下提示: 注:如果看不到如上提示可能是由于之前访问过页面,执行如下语句再重新访问即可: 上面的提示说明升级脚本确实运行了,后面我们会加入SQL升级脚本,不过现在还是先了解下安装机制。删除die()语句,再次访问会在页面的头部出现Running this upgrade: Alanhou_Weblog_Model_Resource_Setup,重复再刷新一下提示就会消失而页面也显示正常。 Magento的安装资源让我们可以轻易地将安装或升级脚本放到服务器上,然后系统自动运行这些脚本,这样系统中所有的数据库迁移脚本都会保持连续性。 使用熟悉的数据库客户端输入如下语句查询core_table数据表: 这张表中包含所有已安装的模块及其版本号,在靠近下面的部分可以看到我们的模块 正是因为有这条记录,我们在第二次重新访问页面后安装脚本才没有运行,如果想要重新执行安装或升级脚本,比如在开发时想要查看效果,可以删除掉这条记录。那么现在我们就先删除掉这条记录并添加一条SQL语句来创建数据表,删除记录的代码为: 另外我们还要先删除在ORM一节中所创建的blog_post一表,执行如下语句 然后在安装脚本(mysql4-install-0.1.0.php)中添加如下代码: 删除缓存重新加载任意页就会创建blog_posts数据表并插入一行内容。 接下来我们就一起来分析一下上面代码的含义 这句代码中的this指的是什么呢?每个安装脚本都在Setup资源类的环境中运行,自然$this就指向这个类的实例化对象。习惯上我们都会像本例中那样在安装脚本中为$this取一个别名$installer,没有特殊原因建议你在开发过程中也照做。 紧接着的就是上面的代码段,如果查看app/code/core/Mage/Core/Model/Resource/Setup.php中的Mage_Core_Model_Setup类(也就是我们这个安装脚本所继承的类),会发现这些方法会进行了一些基本的SQL操作 查看Varien_Db_Adapter_Pdo_Mysql(lib/Varien/Db/Adapter/Pdo/Mysql.php)就可以找到上面用到的startSetup()和endSetup()方法 另外安装脚本中清空调用了run方法 该方法中传入了一个用于创建数据表的SQL语句,可传入多条SQL语句,只需使用分号进行分隔,可能大家还注意到了下面这条语句: 这个getTable方法中传入的是模型URI,并获取表名。虽然这里可以直接写入表名,但为避免因他人修改配置文件中的表名而导致脚本无法运行,建议养成使用这个方法的好习惯。Mage_Core_Model_Resource_Setup类中包含许多像这样有用的helper方法,最好的学习方法是去研究Magento中core模块的安装脚本。 从1.6开始,Magento就开始支持MySQL以外的数据库,既然我们的安装脚本中包含原生SQL语句,那有可能在其它的数据库系统比如MSSQL中无法执行。这也是为什么我们在文件名中添加了mysql4-作为前缀。 为确保安装脚本保持在多个数据库系统中兼容,Magento提供了一个DDL(Data Definition Language)数据表对象,以下我们对脚本进行修改来保证脚本能在所有Magento支持的关系型数据库中运行。 依然编辑app/code/local/Alanhou/Weblog/sql/weblog_setup/mysql4-install-0.1.0.php文件: 可以看到这里我们没有使用原生SQL语句,使用以上DDL形式的脚本可以保证咱们的模块在与各种数据库保持兼容。 现在我们已经掌握了如何通过脚本来创建数据表,可是如果我们想要对已有模块的数据表结构进行修改又该怎么做呢?Magento的安装资源允许我们通过版本号来自动运行脚本升级模块。一旦在Magento中运行了安装脚本,除非删除core_resource表中对应的记录,否则这个脚本就再也不会被运行。通过创建类似于安装脚本的升级脚本,我们就可以进行适当的升级操作。 创建app/code/local/Alanhou/Weblog/sql/weblog_setup/upgrade-0.1.0-0.2.0.php文件并加入以下代码: 升级脚本和安装脚本放在同一个文件夹内,文件名前面为upgrade,后面为升级前的版本号和升级后的版本后,中间用”-“来进行分隔。如果我们清除缓存重新访问页面这个脚本并不会运行,需要修改config.xml中的版本号都会运行升级脚本: 在这里我们的升级脚本也可以命名为mysql4-upgrade-0.1.0-0.2.0.php,当然这就表明了脚本针对的是MySQL。 在完善升级脚本前,还要一件需要注意的事情,先在同一个文件夹中创建app/code/local/Alanhou/Weblog/sql/weblog_setup/upgrade-0.1.0-01.5.php并加入代码:   重新访问页面会同时出现两条提示 这是因为当Magento发现模块的版本号发生变时,它会运行所有比当前版本号高的脚本,虽然我们并没有在模块配置文件中添加0.1.5,但该脚本依然会被执行。脚本的执行顺序是按版本号从低到高,此时再查看core_resource会得到如下结果: 可以看到版本号已经变成0.1.5了,这说明0.1.0到0.1.5的升级已经完成,并不是执行的0.1.0到0.2.0的升级。那么下面我们就来修改0.1.0-0.2.0的升级脚本:   重新刷新页面发现升级脚本并没有执行,post列依然允许使用空值,更重要的是die()语句并没有使用程序跳出运行,到底发生了什么呢?我们来一起捋一下前面的操作: 起初weblog_setup资源的版本号是0.1.0 […]

Tags: , ,

0

Magento开发系列之五 模型和ORM基础

Posted by Alan on August 9, 2015 in Coding, Magento |

模型层级的应用在MVC框架中是一个非常重要的部分,它包含应用程序所需的数据。在Magento中,Model起的作用甚至还要更大,因为其中还包含业务逻辑,在其它的MVC框架中,业务逻辑通常是放在Controller或Helper方法中的。 注:在调试过程中如果没有出现我们所提到的报错,请开启报错,步骤如下: a> 打开根目录下的index.php文件并取消如下注释: b> 打开.htaccess文件并在最后添加 SetEnv MAGE_IS_DEVELOPER_MODE “true” MVC模型 首先我们来看看PHP传统的MVC模型,如果说MVC的定义不够清楚,那么模型的定义就更加模糊了。在PHP开发者大规模采用MVC框架前,数据是通过原生的SQL语句或SQL抽象层来获取的。这时开发者需要书写SQL语句并考虑为哪些对象建模。 如今很多人已不太愿意去书写原生SQL语句了,但很多PHP框架依然是在大量使用SQL。Model是提供抽象层的对象,但事实上程序员还是书写SQL语句或者通过抽象方法来读写数据以调用SQL。 也有一些框架避开SQL的使用而采用ORM(Object Relational Mapping)来完成相关操作。这种方法开发者通过对象设定属性,在调用对象中的save方法时,数据会被自动写入数据库。 我们再来看看Magento的模型,Magento是支持ORM的,同时Zend框架中的SQL抽象也可用。Magento中大多数的数据通过其内置的模型或自开发的模型来处理。Magento中Model的概念也是超级灵活、高度抽象的。 Magento中大多数的模型可以被划分为两类,一种是类似ActiveRecord的一个对象一张表的模型,另一种就是大名鼎鼎的EAV(Entity Attribute Value)模型。每个模型都有一个模型集合,集合(Collection)是用于包含一系列Magento模型实例的PHP对象。Magento开发团队在PHP标准库接口中加入了IteratorAggregate和Countable来让每个Model类型获取它自己的集合类型。如果你不太了解PHP标准库,可以把模型集合看作带有方法的数组。 Magento模型中没有代码去连接数据库,而是通过模型资源类来与数据库服务器进行交互(读或写adapter对象)。通过分离逻辑模型与数据库交互代码,理论上就可以在保持模型不变的情况下写一个新的资源类来操作不同类型的数据库。 首先我们要创建一个基本的Magento模型,按照传统我们来做一个weblog博客建模,步骤如下: 创建一个Weblog模块 为我们的Model创建一个数据表 在配置文件中添加一个Blogpost模型 在配置文件中为Blogpost模型添加模型资源信息 在配置文件中为Blogpost模型添加一个读适配器(Adapter) 在配置文件中为Blogpost模型添加一个写适配器 为Blogpost模型添加一个PHP类文件 为Blogpost资源模型添加一个PHP类文件 实例化该模型 那下面我们就按这个步骤来进行操作吧,通过前面的学习你应该对创建Weblog模块已经相当熟悉了,不过考虑到有些朋友没有从头开始看,这里再赘述一下,首先创建如下目录 创建app/code/local/Alanhou/Weblog/etc/config.xml文件并加入如下代码 接着创建app/etc/modules/Alanhou_Weblog.xml文件并加入如下代码 执行以下步骤 清除缓存 在后台中,点击System > Configuration > Advanced > Advanced 在Disable modules output面板中查看Alanhou_Weblog是否出现 模块添加成功后我们来创建一个Action方法名为testModel的index控制器,首先在config.xml里添加router即加入如下代码: 在app/code/local/Alanhou/Weblog/controllers/IndexController.php中加入如下代码: 清除缓存并访问http://localhost/magento/weblog/index/testModel页面上会输出Setup! Magento拥有一套可自动创建和修改数据库的系统,不过现在我们先手动为这个模型创建数据表,在phpMyAdmin或任何数据库客户端中进入数据库执行如下语句创建数据表blog_posts 接着执行如下语句手动插入一条数据 配置模型文件我们需要在配置文件中 在模块中开启Model 在模块中开启Model资源 为Model资源添加一个entity数据表配置 在实例化一个模型时需要进行类似下面这样的调用 […]

Tags: , , , ,

0

Magento开发系列之四 布局、块和模板

Posted by Alan on August 9, 2015 in Coding, Magento |

刚刚接触Magento开发的人经常会搞不清布局(Layout)和视图(View)之间的分别。那么本节就来剖析Magento的布局/块,以及它们在Magento的MVC架构中所起到的作用。 和很多主流的MVC系统不同,Magento的Action控制器不向视图传递数据对象,并且通常也不会去设定视图对象中的属性值。而是由视图组件直接引用系统模型来获取所需显示的信息。 采用这种设计方法直接导致视图被分割成两个部分:块文件(Blocks)和模板文件(Templates),其中块是PHP对象,模板是混合了HTML和PHP的原生PHP文件,后缀名采用.phtml。每个块文件对应着一个模板文件,在模块文件中通过$this关键词来引用块文件中的对象。 先看看代码,打开app/design/frontend/base/default/template/catalog/product/list.phtml文件,会看到如下代码 其中getLoadedProductCollection方法来自块文件的Mage_Catalog_Block_Product_List类,具体位置在app/code/core/Mage/Catalog/Block/Product/List.php 块文件中的_getProductCollection会实例化模型并读取其中的数据,并将结果返回给模板文件。 块文件内置 块和模板文件真正的强大之处在于getChildHtml方法的使用,使用这个方法可以包含一级块、模板文件内的二级块、模板文件。页面上的HTML布局正是通过块文件不断地调用内嵌的块文件来创建的。下面我们就来看一看app/design/frontend/base/default/template/page/1column.phtml这个文件: 模板文件本身并不长,但通过多次调用$this->getChildHtml()方法包含并显示了多个块文件,这些块文件又会使用getChildHtml方法去调用其它块文件。 布局文件 这么看起来块文件和模板文件确实不错,那么如何让Magento知道在页面中使用哪一个块文件?先从哪一个块文件开始处理?又如何在getChildHtml中指定一个块文件呢?毕竟里面的参数看起来不太像是个块文件的名称。 这就需要讲到布局对象了,布局对象是一个指定了页面上将包含块文件的XML对象,它同时也指定了先处理哪一个块文件。在上节中我们在Action方法中使用了echo指令输出了一些内容,本节我们将会为Helloworld模块创建一个简单的HTML模板文件。首先创建一个app/design/frontend/base/default/layout/local.xml文件,加入如下代码 然后再创建一个app/design/frontend/base/default/template/alanhou/helloworld/simple_page.phtml文件并添加如下代码: 完成了上面的操作后,最后需要通过Action控制器来调用整个布局,那么我们需要对之前创建的indexAction方法进行如下调整: 清除缓存重新加载http://localhost/mgt/helloworld/index/index,就会显示刚刚在simple_page.phtml里所添加的内容,也就是整个屏幕都显示红色的背景。 你一定很好奇这背后到底发生了什么呢?下面就让我们一起来揭开这神秘的面纱。为方便观察首先安装一下Layoutviewer模块: 链接: http://pan.baidu.com/s/1qHTd8 密码: 2dya 只需解压缩然后拷贝到app目录中即可完成安装,这个模块类似于我们这前面小节里提到的Configviewer。安装完成后请访问http://localhost/magento/helloworld/index/index?showLayout=page 输出内容即为page请求的layout.xml,它由<block />, <reference /> 和<remove />等标签组成,当我们在调用loadLayout方法时,Magento实际完成的操作有: 生成Layout布局XML文件 实例化各<block />标签中的Block类,通过标签属性查找类并作为全局配置路径保存到布局对象的_blocks数组中,在该数组中以标签名作为数据的键 如若标签中包含输出属性,其值就会被添加到布局对象的_output数组中 然后在Action控制器中调用renderLayout方法时,Magento会遍历_output数组中的所有Block,将输出属性的值作为一个回调方法,这通常都是toHtml,也就是从块模板文件开始处理。接下我们会谈谈Block是怎么被实例化的,layout文件又是如何生成并完成输出的? Block的实例化 在生成的布局XML文件中,包含type属性的实际上是一个类群URI,比如 这些URI都引用全局配置文件中的一个地方,URI的前半部分(上例中都是page)会用于在全局配置文件中查询page的类名,而第二部分(分别是html和template_links)会被加到前面查询到的类名最后并形成Magento将要实例化的类。 以page/html为例,Magento会首先去依次查找全局配置文件中的global > blocks > page节点(参见Magento开发系列之二 配置文件) 查找到的结果即是上图中的 这里我们就得到了类名的前一部分Mage_Page_Block,然后将第二部分添加到后面就构成了将要实例化的类名Mage_Page_Block_Html。假如我们创建了一个和现有block同名的块文件,新的block会替换原来的实例,我们在前面创建的local.xml就做了这样的替换 名为root的block就被我们的创建的block所替换,指向了一个新phtml模板文件。 Reference标签 标签会将会将内部包含的所有XML声明以指定的名称放到现在的block中,它内部包含的节点会被作为所引用的父级block的子block 放在不同的layout文件中: 即便root block是在一个单独的布局XML文件中声明,新添加的block还是作为一个子block。Magento先创建一个名为root的page/html块,之后如果再遇到有对root的引用(reference),就会将新的块some.other.block.name作为root的子block。 Layout文件的生成过程 现在我们对于Layout XML文件已经有了更进一步的了解,但这个XML文件是从哪里来的呢?要解释这个问题就需要引入两个新的概念:指针(Handle)和安装包布局(Package Layout)。 Magento中的每个页面请求都会生成一些指针,我们前面创建的Layoutview模块将有助于形象化的展示这些指针,只需要访问http://localhost/magento/helloworld/index/index?showLayout=handles就会看到类似下面的结果(根据个人配置会略有差别) 以上输出的每一个都是指针,指针可以在Magento系统中的很多地方进行设置,这里我们着重讨论的是default和helloworld_index_index这两个。default指针在每个Magento的请求中都会出现,而helloworld_index_index是拼接了Router名称(helloworld)、Action控制器名称(index)和Action控制器方法名(index)所形成的一个字符串。这也就是说Action控制器中的每个方法都会对应一个指针。 […]

Tags: , , , , ,

0

Magento开发系列之三 控制器

Posted by Alan on August 7, 2015 in Coding, Magento |

MVC结构可以追溯到Smalltalk编程语言和Xerox Parc时代,从那时起很多系统都自称采用了MVC结构。这些系统又都与其它有着些许差别,不过总体而言都会将获取数据、业务逻辑和用户界面的代码进行分离。PHP中常见的MVC框架如下图所示: 一个称为前台控制器的PHP文件获取到URL 该PHP文件检测URL并获取控制器名和Action名(这一步常被称为routing) 实例化所获取到的控制器 与获取的Action名相匹配的方法将会被调用 这个Action方法会根据请求的变量实例化/调用model中的方法 该Action方法准备好数据结构然后传送给view 视图根据从控制器那里获取的数据结构生成HTML 这种模式显然比早期的一个页面对应一个PHP文件要先进了很多,但软件工程师们在工作中会经常抱怨: 前台控制器在全局命名空间中工作 配置的规则只能实现少量的模块化 URL routing不太灵活 即便系统允许重载默认方法,如果不进行大规模重构,这种模式会很难添加新的模型、视图或控制器。 基于此,Magento团队创建了更为抽象的MVC模式 由一个PHP文件获取到URL 该PHP文件实例化一个Magento应用 Magento应用实例化一个前台控制器对象 前台控制器实例化一到多个Router对象(通过全局配置文件指定) Router检测请求的URL是否匹配 如果发现到匹配,会获取到Action控制器和Action 实例化Action控制器并调用与Action名称相匹配的方法 Action方法根据请求实例化模型及调用方法 该Action控制器实例化Layout对象 Layout对象根据请求对象和系统属性(也称作指针)创建一系列Block对象 Layout还会在某些Block对象(启动内层渲染)上调用输出方法 每个Block都有一个对应的模板文件,Block中包含PHP逻辑,模板中包含HTML和PHP输出代码 Block从模型中调取数据,也就是说Action控制器并不会传输数据结构。 我们会逐步揭开层层面纱,不过本节我们主要讨论前台控制器 > Router > Action控制器几部分。 这么多理论,想必大家多年的失眠症都已经治愈了…(⊙_⊙;)… 还是老规矩,下面用实例来进行说明,主要有以下几步: 创建一个Hello World模块 使用Router配置该模块 为Router创建Action控制器 首先为Helloworld模块创建目录: 到这里大家估计已经是轻车熟路了,先创建app/code/local/Alanhou/Helloworld/etc/config.xml并加入如下代码: 紧接着创建app/etc/modules/Alanhou_Helloworld.xml文件来激活这个模块,加入如下代码: 使用老方法确认一下模块是否配置成功 过上面基本的框架已经搭建好了,执行以下步骤 清除缓存 在后台中,点击System > Configuration > Advanced > Advanced 在Disable modules […]

Tags: , , ,

0

Magento开发系列之二 配置文件

Posted by Alan on August 6, 2015 in Coding, Magento |

config文件可以说是Magento的发动机,它从整体上包含了几乎一切模块、模型、类、模板文件等。很多PHP开发者不太适应这种高度的抽象,在开发中也给他们带来了不少的困扰和麻烦,但一旦掌握这种对系统文件的重载机制将带来空前的灵活性。 本节我们将创建一个用于在浏览器中查看系统配置的模块,请尝试跟着我们一起做,这样有助于你更进一步的了解Magento以及主要的名称和用法。 构建模块目录结构 这里我们会创建一个Magento模块,模块由一组php和xml文件组成,用于继承系统类添加新功能或重载系统方法。比如可以是为追踪销售信息添加新的数据模型、修改已有类的方法或添加全新的功能等等。 值得一提的是Magento系统中通常都是基于同一个模块,如果查看app/code/core/Mage的话,会发现里面包含很多的文件夹,这些都是由Magento团队所创建的模块,也正是默认情况下前台所用到的所有模块。 对于自建的模块通常会放在app/code/local/Packagename内,其中Packagename作为唯一标识你所开发代码的命名空间。作为一个不成文的规定,通常建议使用公司的名称,比如app/code/local/Google,在本系列的例子中我们将使用Alanhou,并使用Configviewer作为模块名称,所以首先请创建如下目录结构: app/code/local/Alanhou/Configviewer/Block app/code/local/Alanhou/Configviewer/controllers app/code/local/Alanhou/Configviewer/etc app/code/local/Alanhou/Configviewer/Helper app/code/local/Alanhou/Configviewer/Model app/code/local/Alanhou/Configviewer/sql 我们在本节的模块中不会用到所有这些文件夹,但创建这些文件夹有助于对整个模块结构的了解。下一步我们会创建两个文件 第二个文件按照Packagename_Modulename.xml的规则来进行命名,在config.xml文件中放入如下代码: 然后在Alanhou_Configviewer.xml中添加如下代码 如果你现在对上面的代码还是一头雾水的话,大可不必担心,后面会有详细的介绍。通过上面基本的框架已经搭建好了,执行以下步骤 清除缓存 在后台中,点击System > Configuration > Advanced > Advanced 在Disable modules output面板中查看Alanhou_Configviewer是否出现 如果看到Alanhou_Configviewer,那么恭喜你已经成功创建第一个模块。 创建模块配置文件 你可能已经看到胜利的曙光了,不过截至目前这个模块还没有什么实质意义。这一模块我们计划完成的工作有 检查showConfig变量字段是否存在 如果showConfig存在,显示Magento的配置并中断其它的执行 检测是否存在其它的字符变量,showConfigFormat可以指定以纯文本或xml进行输出 首先我们将在config.xml文件中添加<global>代码块 然后创建一个app/code/local/Alanhou/Configviewer/Model/Observer.php文件,加入如下代码: 然后访问http://localhost/magento/?showConfig=true,就会出现像下面这样的一大串XML代码 代码中主要包含Magento的状态,其中列出了所有的模块、模型、类、事件监听器等内容。 例如在如上的XML输出中搜索Alanhou_Configviewer_Model_Observer就可以找到对应的类。Magento中所有模块的config.xml文件都会被解析并包含到全局设置中。 那这些有什么实际意义呢,你现在看到这些内容可能会被吓到,但配置文件对于理解Magento来说相当之重要。你创建的所有模块都会被加到这个配置文件中,并且你在任何时候调用系统core中的功能时,都会到这个配置文件中去进行查看。 举个例子,熟悉MVC的开发者一定实例化过类似这样的helper类 而Magento对于PHP的类声明进行了抽象化,所以上面的代码在Magento中会像这样 用通俗的话来讲,这个静态helper方法会完成如下动作 在Config中查找<helpers />代码段 在<helpers />代码段中查找<sales />代码段 在<sales />代码段中查找<class />代码段 将斜杠后的内容添加到上一步所查找到的内容后(本例采用默认值data) 实例化上一步中所查找到的类,即Mage_Sales_Helper_Data 看上去这样有些繁杂,但通过在配置文件中查找类,有助于我们在不修改core代码的情况下重载Magento的系统方法。而且相当的灵活,可以对部分系统方法进行继承修改。

Tags: , ,

0

Magento开发系列之一 基础知识

Posted by Alan on August 5, 2015 in Coding, Magento |

代码模块化 Magento采用Model-View-Controller(MVC)架构,Controller, Model都会放在单独的文件夹里,文件会根据功能进行分组,这种分组在Magento中称为模块(module)。 在Magento中通常一个模块会包含 Controllers, Models, Helpers, Blocks等目录,比如app/code/core/Mage/Checkout模板下的文件夹结构: 想要修改或继承Magento的代码时,不应在系统core代码上进行修改,而应在local或community代码池内新建一个模块 代码包(Package,或称为命名空间 – Namespace)用于区分开发代码的公司和组织,进而避免在进行代码分享时出现相互覆盖的情况。新建好模块后,还应在app/etc/modules内添加一个XML文件用于告知Magento你新建模块的位置。这个XML文件可用于指定单一模块,命名格式为Packagename_Modulename.xml,也可用于指定命名空间内的多个模块,命名格式为Packagename_All.xml,比如在app/etc/modules内在Mage_All.xml文件。但是并不推荐在单个文件中指定多个模块,因为这样就失去了分开定义模块的意义。 基于配置的MVC Magento是一套基于配置文件(configuration-based)的MVC系统,有别于传统的基于惯例(convention-based)的MVC系统。在基于惯例的MVC中,添加一个控制器或模型,只需创建一个文件或类,系统会自动运行。 而在像Magento这样的基于配置文件的MVC系统中,除了添加新文件或类外,还需要告知系统所创建的类或类群的名称,就是通过每个模块中的config.xml文件。 比如要在自己写的模块中使用一个模型,就需要在config.xml中添加一些代码告诉Magento你要使用模型以及基类的名称 Helpers, Blocks, Routes for your Controllers, Event Handlers等也同理,几乎在Magento系统中添加任何东西都需要在配置文件中做类似修改。 控制器 在任何PHP系统中,主入口文件仍然是PHP文件,因而Magento的主入口文件也不例外,具体的说就是index.php这个文件。但绝不要修改index.php文件,在MVC系统中,index.php用于 检测URL地址 基于既定规则,将URL解析成控制器类和Action方法(这步称为Routing) 实例化控制器类并调用Action方法(这步称为dispatching) 也就是说在Magento或其它的MVC系统入口是控制器文件中的一个方法,那么http://example.com/catalog/category/view/id/25这个URL会被解析为 Front Name: catalog URL中的第一段称为前台名称(front name),这会告知Magento在哪个模块去查找控制器,本例中前台名称就是catalog,对应的路径是app/code/core/Mage/Catalog Controller Name:category 紧接着的部分告知Magento应使用哪个控制器,每个模块中都有一个controllers文件夹用于存放该模块的控制器文件,本例中对应的文件是 其中的内容类似: 所有Magento前台的应用都继承Mage_Core_Controller_Front_Action这个类 Action Name:view URL的第三部分为动作名,本例中的view用于创建动作方法,具体对应viewAction 熟悉Zend框架的朋友对于这种命名规则一定也不会陌生。 Paramater/Value – id/25 在动作名后面的部分会被作为GET方法传入的键值对,本例中的id/25代表GET变量名为id,值为25。前面也提到如果要模块使用控制器的话,需在config文件中进行添加,下面就是在Catalog模块中应用控制器的代码 可能你现在还不理解上面各标签的具体意义,不过不用担心,后面会详细的说明。注意catalog这段是在URL中链接到指定模块的前台名。通常Magento的core模块中会使用与模块名相同的前台名称,但并非强制要这样做。  多路由(Routers) 前面所说的routing是针对Magento的cart应用(常称为前台frontend),当Magento在URL未发现有关的Controller/Action时,会再次尝试一套针对Admin应用的Routing规则,如果再次失败,则会使用一个名为Mage_Cms_IndexController的特殊控制器。 CMS控制器查找Magento的内容管理系统,来确定是否有什么内容可以加载,如果还找不到,则会返回404页面。 基于环境的URI模型载入 我们已经了解到Action方法的入口,下一步就是实例化类进行具体操作了,Magento有一套特别的方法来实例化Models, Helpers和Blocks,也就是全局的Mage类中的静态工厂方法,例如: […]

Tags: ,

0

Magento添加email退订功能

Posted by Alan on May 30, 2015 in Magento |

在Magento中默认提供了订阅邮件的代码,但退订则需要二次开发或安装插件,本帖旨在探讨邮件订阅和尤其是退订的相关代码实现方式。 使用系统所提供的方法 订阅和退订操作的数据表是newsletter_subscriber,对应的数据列为subscriber_status,值有1,2和3对应的意思如下: 1: Subscribed 2: Status Not Active 3: Unsubscribed 以下某邮箱退订后在数据表中的显示: Magento系统中提供了对应的方法来处理退订和订阅,示例代码如下: 直接对数据库进行操作 本方法通过在template目录下添加代码来处理退订,比如我们在app/design/frontend/default/模板名/template下建立一个unsub文件夹,并在unsub下创建一个unsubscribe.phtml文件来处理退订,这里为了简便,我们采用GET的方式来提交邮箱,您可以配合表单应用POST方式进行提交。示例代码如下: 以上代码添加完毕后,在CMS > Pages下添加一个页面用于处理退订及退订完成后显示的页面,并在其中添加如下代码: 其中name以及template的值对应前面创建的目录及文件名。

Tags: , ,

0

Magento二次开发知识帖

Posted by Alan on May 5, 2015 in Magento |

操作数据库 Magento连接数据库执行查询 执行时需要include或require一下app/Mage.php文件,若出现类似”Fatal error: Call to a member function getModelInstance() on a non-object in D:\xampp\htdocs\magento\app\Mage.php on line 463“报错,请尝试添加一句 Magento对数据库执行增删改查 判断用户登录状态 CMS代码 邮件订阅 自定义代码

Tags: ,

Copyright © 2012-2018 记录点滴生活 | Alan Hou的个人博客 All rights reserved.