您好,登錄后才能下訂單哦!
如何在Zend Framework中實(shí)現(xiàn)一個(gè)簡(jiǎn)單工廠模式?很多新手對(duì)此不是很清楚,為了幫助大家解決這個(gè)難題,下面小編將為大家詳細(xì)講解,有這方面需求的人可以來學(xué)習(xí)下,希望你能有所收獲。
復(fù)習(xí)簡(jiǎn)單工廠模式
用類圖回憶一下,簡(jiǎn)單工廠類圖:
借用《研磨設(shè)計(jì)模式》作者的一張圖,可以看到Client通過factory來獲取對(duì)象,通過Api結(jié)構(gòu)來調(diào)用。用factory把具體的Api的創(chuàng)建隱藏起來。而其他所有使用者在使用時(shí),只需要知道用factory創(chuàng)建,通過Api結(jié)構(gòu)調(diào)用即可,簡(jiǎn)單復(fù)習(xí)完成??吹筋悎D應(yīng)該能想起簡(jiǎn)單工廠了,因?yàn)樗旧泶_實(shí)很簡(jiǎn)單。復(fù)習(xí)完簡(jiǎn)單工廠,思維稍微跳躍一下,直接來看看Zend_Db的使用。
1.復(fù)習(xí)Zend_Db的使用
如果不知道如何使用,準(zhǔn)備看XXX的源碼卻不知道怎么用XXX,這有點(diǎn)囧,所以先小小的看一下Zend_Db的使用,下面這段是在ZF官方文檔里面的(個(gè)人不是很喜歡ZF文檔,沒Yii易讀)
/public/index.php
復(fù)制代碼 代碼如下:
$db = Zend_Db::factory('Pdo_Mysql', array(
'host' => '127.0.0.1',
'username' => 'webuser',
'password' => 'xxxxxxxx',
'dbname' => 'test'
));
這里是把數(shù)據(jù)庫配置也放到代碼里面,看起來最簡(jiǎn)單(實(shí)際上其他也不難,只是數(shù)據(jù)庫放置的位置不同,便于管理罷了),但這樣在正常情況下不是最好的方式,但是為了突出重點(diǎn),這里選用這中最簡(jiǎn)單的方式。注意里面的Zend_Db::factory(‘Pdo_Mysql'…這段
上面生成了一個(gè)$db(一個(gè)Zend_Db對(duì)象),使用上面的$db進(jìn)行查詢?nèi)缦拢?
復(fù)制代碼 代碼如下:
$db->setFetchMode(Zend_Db::FETCH_OBJ);
$result = $db->fetchAssoc(
'SELECT bug_id, bug_description, bug_status FROM bugs'
);
繼續(xù)來自官網(wǎng)文檔,這是取記錄的模式為Object,再fetch,一切目前看起來都自然而然,但是至今還是把它Zend_Db當(dāng)作一個(gè)黑盒使用。下面可以進(jìn)入正題。
首先,查看一下zend/Db.php的代碼摘要:
復(fù)制代碼 代碼如下:
< ?php
class Zend_Db
{
/**
設(shè)定一些常量和默認(rèn)值
*/
/**
* Factory for Zend_Db_Adapter_Abstract classes.
*
* First argument may be a string containing the base of the adapter class
* name, e.g. 'Mysqli' corresponds to class Zend_Db_Adapter_Mysqli. This
* name is currently case-insensitive, but is not ideal to rely on this behavior.
* If your class is named 'My_Company_Pdo_Mysql', where 'My_Company' is the namespace
* and 'Pdo_Mysql' is the adapter name, it is best to use the name exactly as it
* is defined in the class. This will ensure proper use of the factory API.
*
* First argument may alternatively be an object of type Zend_Config.
* The adapter class base name is read from the 'adapter' property.
* The adapter config parameters are read from the 'params' property.
*
* Second argument is optional and may be an associative array of key-value
* pairs. This is used as the argument to the adapter constructor.
*
* If the first argument is of type Zend_Config, it is assumed to contain
* all parameters, and the second argument is ignored.
*
* @param mixed $adapter String name of base adapter class, or Zend_Config object.
* @param mixed $config OPTIONAL; an array or Zend_Config object with adapter parameters.
* @return Zend_Db_Adapter_Abstract
* @throws Zend_Db_Exception
*/
public static function factory ($adapter, $config = array())
{
//使用Zend_Config對(duì)象,上述方式?jīng)]有使用,直接使用Array
if ($config instanceof Zend_Config) {
$config = $config->toArray();
}
/*
* Convert Zend_Config argument to plain string
* adapter name and separate config object.
*/
if ($adapter instanceof Zend_Config) {
if (isset($adapter->params)) {
$config = $adapter->params->toArray();
}
if (isset($adapter->adapter)) {
$adapter = (string) $adapter->adapter;
} else {
$adapter = null;
}
}
/*
* Verify that adapter parameters are in an array.
*/
if (! is_array($config)) {
/**
* @see Zend_Db_Exception
*/
require_once 'Zend/Db/Exception.php';
throw new Zend_Db_Exception(
'Adapter parameters must be in an array or a Zend_Config object');
}
/*
* Verify that an adapter name has been specified.
*/
if (! is_string($adapter) || empty($adapter)) {
/**
* @see Zend_Db_Exception
*/
require_once 'Zend/Db/Exception.php';
throw new Zend_Db_Exception(
'Adapter name must be specified in a string');
}
/*
* Form full adapter class name
*/
$adapterNamespace = 'Zend_Db_Adapter';
if (isset($config['adapterNamespace'])) {
if ($config['adapterNamespace'] != '') {
$adapterNamespace = $config['adapterNamespace'];
}
unset($config['adapterNamespace']);
}
// Adapter no longer normalized- see http://framework.zend.com/issues/browse/ZF-5606
$adapterName = $adapterNamespace . '_';
$adapterName .= str_replace(' ', '_',
ucwords(str_replace('_', ' ', strtolower($adapter))));
/*
* Load the adapter class. This throws an exception
* if the specified class cannot be loaded.
*/
if (! class_exists($adapterName)) {
require_once 'Zend/Loader.php';
Zend_Loader::loadClass($adapterName);
}
/*
* Create an instance of the adapter class.
* Pass the config to the adapter class constructor.
*/
$dbAdapter = new $adapterName($config);
/*
* Verify that the object created is a descendent of the abstract adapter type.
*/
if (! $dbAdapter instanceof Zend_Db_Adapter_Abstract) {
/**
* @see Zend_Db_Exception
*/
require_once 'Zend/Db/Exception.php';
throw new Zend_Db_Exception(
"Adapter class '$adapterName' does not extend Zend_Db_Adapter_Abstract");
}
return $dbAdapter;
}
}
最上方的注釋非常值得看,它清楚的說明了這個(gè)工廠,另外一段比較重要的幾段代碼(忽略其中的異常處理)是:
復(fù)制代碼 代碼如下:
//factory有一個(gè)參數(shù)叫做$adapter
public static function factory($adapter, $config = array())
//確定namespace
$adapterNamespace = 'Zend_Db_Adapter';
//用namespace和上面?zhèn)魅氲?adapter構(gòu)造類名
$adapterName = $adapterNamespace . '_';
$adapterName .= str_replace(' ', '_', ucwords(str_replace('_', ' ', strtolower($adapter))));
//用上面生成的類名new出obj,看起來PHP比java方便那么一點(diǎn)點(diǎn)哈(Class.forName(‘XXX').newInstance())
$dbAdapter = new $adapterName($config);
在回想上面使用Zend_Db::factory生成$db的地方:
復(fù)制代碼 代碼如下:
$db = Zend_Db::factory('Pdo_Mysql', array(
'host' => '127.0.0.1',
'username' => 'webuser',
'password' => 'xxxxxxxx',
'dbname' => 'test'
));
factory方法的第一個(gè)參數(shù)即是$adapter為Pdo_Mysql,記住這里是Pdo_Mysql,再跳躍一下,根據(jù)上面的$adapterNamespace = ‘Zend_Db_Adapter';可以看到生成的找到$dbAdapter的值最終必為:Zend_Db_Adapter_Pdo_Mysql,ok,根據(jù)此名字找到zend/db/adapter/pdo目錄下,哈,這么多熟悉的面孔,看到了熟悉的MySql、Mssql、Sqlite這些老面孔了。
注意,注意,里面還有個(gè)低調(diào)的Abstract.php,里面他們的父類Zend_Db_Adapter_Pdo_Abstract。打開Mysql.php可以看到
class Zend_Db_Adapter_Pdo_Mysql extends Zend_Db_Adapter_Pdo_Abstract
嗯,類名Zend_Db_Adapter_Pdo_Mysql和上面生成的名字一樣滴,在看看其他幾個(gè)文件里面的類,他們都繼承自Zend_Db_Adapter_Pdo_Abstract,如果要畫類圖,那就應(yīng)該會(huì)有如下這么一張類圖:
接著再加入調(diào)用著Client和工廠函數(shù)所在的位置Zend_Db,這張簡(jiǎn)單的類圖就應(yīng)該是,
看完上述內(nèi)容是否對(duì)您有幫助呢?如果還想對(duì)相關(guān)知識(shí)有進(jìn)一步的了解或閱讀更多相關(guān)文章,請(qǐng)關(guān)注億速云行業(yè)資訊頻道,感謝您對(duì)億速云的支持。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。