Alan Hou的个人博客

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

Magento系统中另一个强大的组件是后台Admin的系统配置部分,开发过程中需要让用户可以通过在后台配置系统和自建模块来进行设置。

首先创建一个app/code/local/Alanhou/Helloworld/etc/system.xml文件,和全局配置相似,系统配置信息将单独存储。如果想要查看系统配置文件 ,可以在任意控制器Action中添加如下 代码并执行(这里在前面创建的添加到Helloworld下的IndexController>indexAction方法内):

header('Content-Type: text/xml');
echo $config = Mage::getConfig()
->loadModulesConfiguration("system.xml")
->getNode()
->asXML();
exit;

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中加入如下代码:

<config>
	<tabs>
		<helloconfig translate="label" module="helloworld">
			<label>Hello Config</label>
			<sort_order>99999</sort_order>
		</helloconfig>
	</tabs>
</config>

代码中的<helloconfig />标签名是任意选定的,但不应与其它选项卡重复,这用于标识配置应用于的选项卡。module=”helloworld”属性表示所属模块,<label>定义选项卡显示的名称。<sort_order>表示选项卡在左侧导航中显示的位置,此时访问后台System > Configuration,会出现如下报错:

Fatal error: Class 'Mage_Helloworld_Helper_Data' not found in D:\xampp\htdocs\magento\app\Mage.php on line 547

和大多数流行的PHP MVC系统一样,Magento也会使用Helper类,主要用于处理一些不宜放在Model, View或Controller处理的任务。Helper类是一种抽象类群的名称,也就是说系统用户可以重载默认类,此外模块开发者也需要在config.xml中添加一个代码块来指定Helper的基类名称。

很多系统代码都会假定每个模块有个默认的Helper类,所以出现上面报错的原因是因为在Helloworld模块中并没有默认Helper类而系统尝试调用该类。所似接下来我们在config.xml里加入如下代码:

<global>
	<helpers>
		<helloworld>
			<class>Alanhou_Helloworld_Helper</class>
		</helloworld>
	</helpers>
</global>

基中的<helloworld />标签就是模块名,<class />标签则包含的是Helper类的基础名称,通常按照Packagename_Modulename_Helper的方式命名。Helper通过全局Mage对象的静态方法helper来加载,以本例而言

Mage::helper('helloworld/foo');

会加载以下文件中的以下类

app/code/local/Alanhou/Helloworld/Helper/Foo.php
class Alanhou_Helloworld_Helper_Foo

Magento中还有一个模块默认类的概念,比如只传入模块名时

Mage::helper('helloworld');

会加载以下文件中的以下类

app/code/local/Alanhou/Helloworld/Helper/Data.php
class Alanhou_Helloworld_Helper_Data

也就是说下面两个是等价的

Mage::helper('helloworld');
Mage::helper('helloworld/data');

下面我们在app/code/local/Alanhou/Helloworld/Helper/Data.php中加入如下代码

<?php
class Alanhou_Helloworld_Helper_Data extends Mage_Core_Helper_Abstract{

}

现在我们清除缓存重新访问System > Configuration报错就会消失,但是并不会显示新创建的选项卡。那么接下来我们就来查看为什么新的选项卡没有显示,每个选项卡中都有多个版块(Section),比如Advanced下有Admin, System, Advanced和Developer。那如果选项卡没有添加版块选项也是不显示的,下面我们就在system.xml中添加

代码段

<config>
	<tabs>
		<helloconfig translate="label" module="helloworld">
			<label>Hello Config</label>
			<sort_order>99999</sort_order>
		</helloconfig>
	</tabs>
	<sections>
		<helloworld_options translate="label" module="helloworld">
			<label>Hello World Config Options</label>
			<tab>helloconfig</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>
		</helloworld_options>
	</sections>
</config>

与标签相似,<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 List)中找不到我们新加的Section。系统中有一些资源是需要经过验证才可以使用的,比如后台中的一个页面,使用一些功能。在Magento中系统配置就受到ACL的保护。
资源是通过URI来定义的,比如General下的web版块就是通过admin/system/config/web来定义的,我们创建的helloworld_options对应的URI是admin/system/config/helloworld_options。Admin应用(常被称作Adminhtml)是用与store应用(常被称作frontend)相同的框架构建的,在Adminhtml的action控制器中,无论何时用户要获取受ACL保护的资源,都要:

  1. 获取终端用户想要访问资源的URI
  2. 到ACL中去进行查看,决定登录的用户是否有访问这一资源的权限
  3. 如果用户有相应权限,继续执行,如果没有,就中断执行或采取适当措施

所以我们需要为新的section定义ACL资源,这一操作只针对新添加的section,在已有的section中增加配置无需动到ACL。在config.xml中添加如下代码:

<config>
... ...
<adminhtml>
	<acl>
		<resources>
			<admin>
				<children>
					<system>
						<children>
							<config>
								<children>
									<helloworld_options>
										<title>Store Hello World Module Section</title>
									</helloworld_options>
								</children>
							</config>
						</children>
					</system>
				</children>
			</admin>
		</resources>
	</acl>
</adminhtml>
... ...
</config>

上面的代码信息量有些大,我们来逐一讲解,首先,所有的资源都放在以下节点中

<adminhtml>
    <acl>
        <resources>
        </resource>
    </acl>
</adminhtml>

在资源中,每下一级节点都代表URI的一部分,

<admin>
    <children>
        <system>
            <children>

上面的这段代码所对应的URI就是admin/system,再往下看

<helloworld_options>
	<title>Store Hello World Module Section</title>
</helloworld_options>

其中的title就是admin权限中显示的内容。清除缓存再次点击Hello World Config Options就会出现配置版块了(注意:可能需要登出再登录),此时右侧就会出现标题为Hello World Config Options的空白配置页


接下来我们再加组(group),组是将不同的配置选项放到一起并在后台显示,比如Advanced版块下就有一个名为Disable Modules Output的组。这里我们在system.xml中添加一个messages组

<config>
	<tabs>
		<helloconfig translate="label" module="helloworld">
			<label>Hello Config</label>
			<sort_order>99999</sort_order>
		</helloconfig>
	</tabs>
	<sections>
		<helloworld_options translate="label" module="helloworld">
			<label>Hello World Config Options</label>
			<tab>helloconfig</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>
				<messages 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>
				</messages>
			</groups>
		</helloworld_options>
	</sections>
</config>

可以看到组内的标签与section中基本是对应的,现在再重新打开Hello World Config Options就会出现一个空的弹出框


最后我们要添加一些配置项,主要是通过在中添加,下面我们就添一个名为hello_message的选项

... ...
<messages 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>
		<hello_message>
			<label>Message</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>
		</hello_message>
	</fields>
</messages>
... ...

同样,fields内的标签和其它节点也基本相似,但是这里具备了实际含义,系统通过其中的值来展示不同的表单元素。重新打开Hello World Config Options,就会在右侧多出一个文本框:


除了文本框外还可以添加其它内容,比如时间下拉框,下面添加一个

... ...
<fields>
	<hello_message>
		<label>Message</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>
	</hello_message>
	<hello_time>
		<label>Time</label>
		<frontend_type>time</frontend_type>
		<sort_order>2</sort_order>
		<show_in_default>1</show_in_default>
		<show_in_website>1</show_in_website>
		<show_in_store>1</show_in_store>
	</hello_time>
</fields>
... ...

注意这里用到的是

<frontend_type>time</frontend_type>



这里支持大多数的表单类(lib/Varien/Data/Form/Element),下面我们再添加一个下拉框:

... ...
<hello_select>
	<label>Select</label>
	<frontend_type>select</frontend_type>
	<sort_order>3</sort_order>
	<show_in_default>1</show_in_default>
	<show_in_website>1</show_in_website>
	<show_in_store>1</show_in_store>
</hello_select>
... ...

重新访问会发现下拉框中没有内容,这就需要为这个下拉框添加一个source model,修改上面的代码为:

<hello_select>
	<label>Select</label>
	<frontend_type>select</frontend_type>
	<source_model>helloworld/words</source_model>
	<sort_order>3</sort_order>
	<show_in_default>1</show_in_default>
	<show_in_website>1</show_in_website>
	<show_in_store>1</show_in_store>
</hello_select>

为模型类定义了一个URI,我们将用这个URI来获取select下拉框中的默认值,在config.xml中添加如下代码:

<global>
... ...
	<models>
		<helloworld>
			<class>Alanhou_Helloworld_Model</class>
		</helloworld>
	</models>
... ....
</global>

重新访问会出现如下报错

Warning: include(Alanhou/Helloworld/Model/Words.php)

创建app/code/local/Alanhou/Helloworld/Model/Words.php并加入如下代码:

<?php class Alanhou_Helloworld_Model_Words{ public function toOptionArray(){ return array( array('value'=>1, 'label'=>Mage::helper('helloworld')->__('Hello')),
			array('value'=>2, 'label'=>Mage::helper('helloworld')->__('Goodbye')),
			array('value'=>3, 'label'=>Mage::helper('helloworld')->__('Yes')),
			array('value'=>4, 'label'=>Mage::helper('helloworld')->__('No')),
		);
	}
}

Source Model是对toOptionsArray方法响应的类,这个方法会返回一组值供表单使用,对于select标签而言,这意味着定义一组值、标签对。上面的代码中,我们通过Helper的translation方法(__)传入标签,这也是推荐的做法。
再次访问页岩,select下拉框中就会正常显示值了


感兴趣的朋友可以查看app/code/core/Mage/Adminhtml/Block/System/Config/Form.php中的initFields方法来看看source Model是如何设定选项值的。
接下来我们再在系统已有版块中进行内容添加,在system.xml中加入如下代码:

<sections>
... ...
	<general>
		<groups>
			<example>
				<label>Example of Adding a Group</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>
			</example>
		</groups>
	</general>
... ...
</sections>

此时在General版块下就会多出一个名为Example of Adding a Group的组


前面我们已经讲过如何在配置中添加表单,要从客户应用或模块中获取值,我们将使用全局Mage对象中的getStoreConfig方法,比如要获得我们前面创建的select中的值,就可以使用:

Mage::getStoreConfig('helloworld_options/messages/hello_message');

getStoreConfig中的URI参数格式为

section_name/group_name/field_name

也可以通过指定部分路径来获取配置值的一个数组,如:
Mage::getStoreConfig(‘helloworld_options/messages’);
Mage::getStoreConfig(‘helloworld_options’);
最后,如果想要获取非当前店铺(store)的配置,可在getStoreConfig中传入一个店铺ID

Mage::getStoreConfig('helloworld_options',1);
退出移动版