ORM 對(duì)象映射法是在ZF2開(kāi)發(fā)指南中引用的一種模型編寫(xiě)方法,可以當(dāng)作是ZF2的推薦寫(xiě)法,此方法的實(shí)現(xiàn)主要通過(guò)TableGateway(作者稱(chēng)為數(shù)據(jù)庫(kù)網(wǎng)關(guān));此方法通過(guò)Di來(lái)實(shí)現(xiàn),對(duì)其進(jìn)行引用前需要對(duì)他做相關(guān)配置工作;總的來(lái)說(shuō)引用簡(jiǎn)單、模型與模塊關(guān)聯(lián)性較強(qiáng)。
在編寫(xiě)模型代碼前先進(jìn)行數(shù)據(jù)表的設(shè)計(jì),數(shù)據(jù)表創(chuàng)建在Mysql數(shù)據(jù)庫(kù)的test默認(rèn)數(shù)據(jù)庫(kù)里表名為news;以下里數(shù)據(jù)表的設(shè)計(jì)及多條測(cè)試數(shù)據(jù)。
~~~
CREATE TABLE news (id int(10) NOT NULL AUTO_INCREMENT,title varchar(100) NOT NULL,content varchar(1000) NOT NULL,PRIMARY KEY(id));
INSERT INTO news(title,content) VALUES(‘First news’,’This is the first news’);
INSERT INTO news(title,content) VALUES(‘Second news’,’This is the second news’);
INSERT INTO news(title,content) VALUES(‘Third news’,’This is the third news’);
INSERT INTO news(title,content) VALUES(‘fourth news’,’This is the fourth news’);
INSERT INTO news(title,content) VALUES(‘Fifth news’,’This is the fifth news’);
INSERT INTO news(title,content) VALUES(‘Sixth news’,’This is the sixth news’);
~~~
已經(jīng)有了數(shù)據(jù)庫(kù)、數(shù)據(jù)表、數(shù)據(jù)需要對(duì)數(shù)據(jù)庫(kù)的訪(fǎng)問(wèn)屬性(數(shù)據(jù)庫(kù)適配器Adapter)進(jìn)行設(shè)置后模型才能夠正常的連接到我們的數(shù)據(jù)庫(kù),找到文件 `/config/autoload/global.php` 文件內(nèi)容如下:
~~~
return array(
'db' => array(
'driver' => 'Pdo',
'dsn' => 'mysql:dbname=test;host=localhost',
'driver_options' => array(
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\''
),
),
'service_manager' => array(
'factories' => array(
'Zend\Db\Adapter\Adapter' => 'Zend\Db\Adapter\AdapterServiceFactory'
),
),
);
~~~
* db 表示數(shù)據(jù)庫(kù)配置信息節(jié)點(diǎn)
* driver 表示數(shù)據(jù)庫(kù)使用的驅(qū)動(dòng)程序類(lèi)型
* dsn 數(shù)據(jù)庫(kù)連接串,也稱(chēng)為數(shù)據(jù)源
* driver_options 數(shù)據(jù)庫(kù)驅(qū)動(dòng)選項(xiàng)
* service_manager 表示服務(wù)器管理器節(jié)點(diǎn)
* factories 表示服務(wù)器管理器需要加載的工廠(chǎng)類(lèi)
為要安全起見(jiàn),將數(shù)據(jù)庫(kù)的用戶(hù)名與密碼寫(xiě)入到 /config/autoload/local.php 文件,你同樣也可以將他寫(xiě)入到global文件的db 節(jié)點(diǎn)中。local.php文件內(nèi)容如下:
~~~
return array(
'db' => array(
'username' => 'root',
'password' => ''
),
);
~~~
### 6.1.1 創(chuàng)建 News 類(lèi)
News 類(lèi)主要包括數(shù)據(jù)表中個(gè)各字段的映射,以及實(shí)現(xiàn)數(shù)組與對(duì)象之間的數(shù)據(jù)轉(zhuǎn)換
路徑:`/module/Application/src/Application/Model/News.php`
在文件中添加收下代碼:
~~~
namespace Application\Model;
class News {
public $id;
public $title;
public $content;
public function exchangeArray($data){
$this->id = (isset($data['id'])) ? $data['id'] : null;
$this->artist = (isset($data['title'])) ? $data['title'] : null;
$this->title = (isset($data['content'])) ? $data['content'] : null;
}
public function getArrayCopy(){
return get_object_vars($this);
}
}
~~~
代碼講解:
public $id,$title,$content 這些公共變量與數(shù)據(jù)表字段一一對(duì)應(yīng)
public function exchangeArray($data) 對(duì)數(shù)組數(shù)據(jù)進(jìn)行轉(zhuǎn)換或都說(shuō)是提取數(shù)組數(shù)據(jù)
public function getArrayCopy() 將類(lèi)屬性轉(zhuǎn)化為一個(gè)關(guān)聯(lián)數(shù)組,方便后續(xù)的使用
### 6.1.2 創(chuàng)建 NewsTable 類(lèi)
NewsTable 類(lèi)的主要是通過(guò)TableGateway 數(shù)據(jù)網(wǎng)關(guān)來(lái)實(shí)現(xiàn)對(duì)數(shù)據(jù)庫(kù)操作。
路徑:`/module/Application/src/Application/Model/NewsTable.php`
在文件中添加以下代碼:
~~~
namespace Application\Model;
use Zend\Db\TableGateway\TableGateway;
use Zend\Db\ResultSet\ResultSet;
use Zend\Db\Sql\Select;
class NewsTable {
protected $tableGateway;
public function __construct(TableGateway $tg)
{
$this->tableGateway = $tg;
}
public function fetchAll()
{
$resultSet = $this->tableGateway->select();
return $resultSet;
}
}
~~~
public function __construct(TableGateway $tg) 構(gòu)造函數(shù)
public funciton fetchAll() 獲取數(shù)據(jù)表的數(shù)據(jù)
### 6.1.3 使用模型讀取數(shù)據(jù)庫(kù)數(shù)據(jù)
在使用模型的時(shí)候需要對(duì)其他進(jìn)行模塊配置,以便ZF2能夠地運(yùn)行的時(shí)候自動(dòng)加載。
#### 6.1.3.1 模塊配置
找到文件 `/module/Application/Module.php` ,在添加函數(shù)的時(shí)候注意導(dǎo)入相關(guān)的命名空間,添加函數(shù) `public function getServiceConfig(){}`,函數(shù)名稱(chēng)是固定的,ZF2會(huì)在運(yùn)行的時(shí)候自動(dòng)調(diào)用Module 中的全部方法。添加內(nèi)容后的文件如下:
~~~
namespace Application;
use Zend\Mvc\ModuleRouteListener;
use Zend\Mvc\MvcEvent;
use Zend\Db\ResultSet\ResultSet;
use Zend\Db\TableGateway\TableGateway;
use Application\Model\News;
use Application\Model\NewsTable;
class Module {
public function onBootstrap(MvcEvent $e){
$eventManager = $e->getApplication()->getEventManager();
$moduleRouteListener = new ModuleRouteListener();
$moduleRouteListener->attach($eventManager);
}
public function getConfig(){
return include __DIR__ . '/config/module.config.php';
}
public function getAutoloaderConfig(){
return array(
'Zend\Loader\StandardAutoloader'=>array(
'namespaces'=>array(
__NAMESPACE__ => __DIR__ . '/src/' . __NAMESPACE__
)
)
);
}
public function getServiceConfig(){
return array(
'factories'=>array(
'Application\Model\NewsTable'=>function($sm){
$tg = $sm->get('NewsTableGateway');
$table = new NewsTable($tg);
return $table;
},
'NewsTableGateway'=>function($sm){
$adapter = $sm->get('Zend\Db\Adapter\Adapter');
$rs = new ResultSet();
$rs->setArrayObjectPrototype(new News());
return new TableGateway('news',$adapter,null,$rs);
}
),
);
}
}
~~~
通過(guò)以上的函數(shù)就配置好了模塊對(duì)模型的引用,從函數(shù)getServiceConfig 的內(nèi)容中可以看出函數(shù)本身只返回一個(gè)關(guān)聯(lián)數(shù)組,這個(gè)關(guān)聯(lián)數(shù)據(jù)的 鍵-值 都將在后續(xù)中被引用;同時(shí)也可以看出我們目錄的配置是針對(duì)news 表的操作,也是為什么我們?cè)谏厦娴哪P椭衒etchAll()函數(shù)里沒(méi)有看到數(shù)據(jù)表的原因。
#### 6.1.3.2 控制器中使用模型
找到文件 `/module/Application/src/Application/Controller/NewsController.php`,添加函數(shù) `public function getNewsTable(){}`,同時(shí)修改 `public function listAction(){}`函數(shù)內(nèi)容,注意導(dǎo)入相關(guān)包;文件修改后如下:
~~~
namespace Application\Controller;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
use Application\Model\NewsTable;
class NewsController extends AbstractActionController{
protected $newsTalbe;
public function __construct(){
}
public function indexAction(){
$view = new ViewModel();
return $view;
}
public function listAction(){
$paginator = $this->getNewsTalbe()->fetchAll();
var_dump($paginator);
exit;
}
public function addAction(){
echo 'NewsController addAction';
exit;
}
public function editAction(){
echo 'NewsController editAction';
exit;
}
public function deleteAction(){
echo 'NewsController deleteAction';
exit;
}
public function getNewsTalbe(){
if(!$this->newsTalbe){
$sm = $this->getServiceLocator();
$this->newsTalbe = $sm->get('Application\Model\NewsTable');
}
return $this->newsTalbe;
}
}
~~~
public function getNewsTalbe(){} 的主要工作就是完成對(duì)數(shù)據(jù)網(wǎng)關(guān)的實(shí)例化
$sm = $this->getServiceLocator() 獲取本地已經(jīng)初化的服務(wù)管理器及服務(wù)
$this->newsTalbe = $sm->get('Application\Model\NewsTable') 獲取在模塊文件中的相關(guān)函數(shù)
$paginator = $this->getNewsTalbe()->fetchAll() 通過(guò)模型(數(shù)據(jù)網(wǎng)關(guān))訪(fǎng)問(wèn)數(shù)據(jù)庫(kù)
通過(guò)添加以上代碼就可以通過(guò) http://localhost/news/list 來(lái)查看模型對(duì)數(shù)據(jù)庫(kù)的相關(guān)操作信息了。在此處只是通過(guò) var_dump 函數(shù)對(duì)模型的操作結(jié)果進(jìn)行打印輸出,而并沒(méi)有通過(guò)模板來(lái)呈現(xiàn);要想通過(guò)模板來(lái)呈現(xiàn)模型對(duì)數(shù)據(jù)庫(kù)查詢(xún)的結(jié)果還需要進(jìn)行一些小的修改。
#### 6.1.3.3 通過(guò)模板顯示數(shù)據(jù)庫(kù)查詢(xún)結(jié)果
模板是匯集網(wǎng)站應(yīng)用所有操作的一個(gè)最終集合點(diǎn),最終將所有匯集的數(shù)據(jù)集中展現(xiàn)給用戶(hù)。在使用模板前我們還得修改下控制器,以便控制器能將模型操作的結(jié)果傳遞到模板中去。修改 listAction 控制器內(nèi)容為:
~~~
public function listAction(){
$paginator = $this->getNewsTalbe()->fetchAll();
$view = new ViewModel();
$view->setTemplate('application/news/list.phtml');
$view->setVariable('paginator', $paginator);
return $view;
}
~~~
$paginator = $this->getNewsTalbe()->fetchAll() 獲取模型查詢(xún)的數(shù)據(jù)
$view = new ViewModel() 實(shí)例化一個(gè)視圖模型
$view->setTemplate('application/news/list.phtml') 設(shè)置視圖模型所使用的模板
$view->setVariable('paginator', $paginator) 給視圖傳遞數(shù)據(jù)
return $view 將視圖模型返回給前端控制器
或者是使用以下代碼:
~~~
public function listAction(){
$paginator = $this->getNewsTalbe()->fetchAll();
return new ViewModel(array('paginator'=>$paginator));
}
~~~
以后兩種方法的最終結(jié)果是一樣的。
接下來(lái)修改我們的模板文件 `/module/Application/view/application/news/list.phtml`,模板的內(nèi)容如下:
~~~
<table>
<tr>
<th>Title</th>
<th>Content</th>
<th>Add news</a></th>
</tr>
<?php foreach ($paginator as $news) : ?>
<tr>
<td><?php echo $this->escapeHtml($news->title); ?></td>
<td><?php echo $this->escapeHtml($news->content); ?></td>
<td>
<a href="<?php echo $this->url('news', array('action' => 'edit', 'id' => $news->id));?>"><?php echo $this->translate("Edit") ?></a>
<a href="<?php echo $this->url('news', array('action' => 'delete', 'id' => $news->id));?>"><?php echo $this->translate("Delete") ?></a>
</td>
</tr>
<?php endforeach; ?>
</table>
~~~
foreach ($paginator as $news) 使用foreach 來(lái)循環(huán)模型查詢(xún)結(jié)果的數(shù)據(jù)行
echo $this->escapeHtml($news->title) 通過(guò)對(duì)象操作方式輸出新聞標(biāo)題
echo $this->escapeHtml($news->content) 通過(guò)對(duì)象操作方式輸出新聞內(nèi)容
echo $this->url('news', array('action' => 'edit', 'id' => $news->id)) 通過(guò)url 方法構(gòu)造編輯新的鏈接
echo $this->url('news', array('action' => 'delete', 'id' => $news->id)) 通過(guò)url 方法構(gòu)造刪除新的鏈接
現(xiàn)在通過(guò) http://localhost/news/list 看看是不是已經(jīng)把之前我們插入到數(shù)據(jù)的數(shù)據(jù)已經(jīng)全部輸出了呢。結(jié)果如下所示:
~~~
header
Title
Content
Add news
First news
This is the first news
Edit Delete
Second news
This is the second news
Edit Delete
Third news
This is the third news
Edit Delete
fourth news
This is the fourth news
Edit Delete
Fifth news
This is the fifth news
Edit Delete
Sixth news
This is the sixth news
Edit Delete
footer
~~~
#### 6.1.3.4 插入數(shù)據(jù)
插入數(shù)據(jù)的功能通過(guò)添加新聞的方式來(lái)進(jìn)行講解,在使用插入數(shù)據(jù)的功能時(shí)同時(shí)涉及到過(guò)濾器、表單生成的相關(guān)內(nèi)容,本小節(jié)將這三個(gè)內(nèi)容進(jìn)行結(jié)合講解。
6.1.3.4.1 創(chuàng)建表單文件
添加表單文件,路徑:`/module/Application/src/Application/Form/NewsForm.php`
內(nèi)容如下:
~~~
namespace Application\Form;
use Zend\Form\Form;
class NewsForm extends Form{
public function __construct($name='news')
{
parent::__construct($name);
$this->setAttribute('method', 'post');
$this->add(array(
'name'=>'id',
'type'=>'Hidden'
));
$this->add(array(
'name'=>'title',
'type'=>'Text',
'options'=>array(
'label'=>'Title'
),
));
$this->add(array(
'name'=>'content',
'type'=>'Text',
'options'=>array(
'label'=>'Content'
),
));
$this->add(array(
'name'=>'submit',
'type'=>'submit',
'attributes'=>array(
'value'=>'Go',
'id'=>'submit'
),
));
}
}
~~~
代碼解析:
public function __construct($name='news') 就是一個(gè)普通的構(gòu)造函數(shù),$name 為表單名稱(chēng)
$this->setAttribute('method', 'post') 設(shè)置表單屬性
$this->add(array('name'=>'id','type'=>'Hidden')); 添加一個(gè)表單隱藏域,作為新聞ID
$this->add(array('name'=>'title','type'=>'Text','options'=>array('label'=>'Title' ))); 添加一個(gè)input 標(biāo)簽,作為新聞標(biāo)題輸入
$this->add(array('name'=>'content','type'=>'Text','options'=>array('label'=>'Content'))); 添加一個(gè)input標(biāo)簽,作為新聞內(nèi)容輸入
$this->add(array('name'=>'submit','type'=>'submit','attributes'=>array('value'=>'Go','id'=>'submit'))); 添加一個(gè)提交按鈕
以上代碼就包含了一個(gè)新聞?dòng)涗浰璧娜勘韱卧亍?
6.1.3.4.2 添加過(guò)濾器
文件:`/module/Application/src/Application/Model/News.php` 在此文件原來(lái)的基礎(chǔ)上添加了內(nèi)容,文件內(nèi)容:
~~~
namespace Application\Model;
use Zend\InputFilter\Factory as InputFactory;// 新加導(dǎo)入包
use Zend\InputFilter\InputFilter;// 新加導(dǎo)入包
use Zend\InputFilter\InputFilterAwareInterface;// 新加導(dǎo)入包
use Zend\InputFilter\InputFilterInterface;// 新加導(dǎo)入包
class News implements InputFilterAwareInterface {// 添加了接口
public $id;
public $content;
public $title;
protected $inputFilter;
public function exchangeArray($data){
$this->id = (isset($data['id'])) ? $data['id'] : null;
$this->content = (isset($data['content'])) ? $data['content'] : null;
$this->title = (isset($data['title'])) ? $data['title'] : null;
}
public function getArrayCopy(){
return get_object_vars($this);
}
public function getInputFilter() {// 新添加,實(shí)現(xiàn)接口方法
if(!$this->inputFilter){
$this->inputFilter = new InputFilter();
$factory = new InputFactory();
$this->inputFilter->add($factory->createInput(array(
'name'=>'id',
'required'=>true,
'filters'=>array(
array('name'=>'Int'),
),
)));
$this->inputFilter->add($factory->createInput(array(
'name'=>'content',
'required'=>true,
'filters'=>array(
array('name'=>'StripTags'),
array('name'=>'StringTrim'),
),
'validators'=>array(
array(
'name'=>'StringLength',
'options'=>array(
'encoding'=>'UTF-8',
'min'=>5,
'max'=>100,
),
),
),
)));
$this->inputFilter->add($factory->createInput(array(
'name'=>'title',
'required'=>true,
'filters'=>array(
array('name'=>'StripTags'),
array('name'=>'StringTrim'),
),
'validators'=>array(
array(
'name'=>'StringLength',
'options'=>array(
'encoding'=>'UTF-8',
'min'=>5,
'max'=>100,
),
),
),
)));
}
return $this->inputFilter;
}
public function setInputFilter(InputFilterInterface $inputFilter) {// 新添加,實(shí)現(xiàn)接口方法
throw new \Exception('Not used');
}
~~~
代碼解析:
public function getInputFilter() 獲取收入類(lèi)型過(guò)濾器,對(duì)指定的表單元素進(jìn)行過(guò)濾。
$this->inputFilter = new InputFilter(); 實(shí)例化一個(gè)InputFilter過(guò)濾器
$factory= new InputFactory(); 實(shí)例化一個(gè)InputFactory 輸入工廠(chǎng)
$this->inputFilter->add($factory->createInput(array('name'=>'id','required'=>true,'filters'=>array(array('name'=>'Int'))))); 創(chuàng)建過(guò)濾規(guī)則并將附加到InputFilter上,規(guī)則內(nèi)容:name為id的標(biāo)簽為必填項(xiàng),并且限制為整形輸入
$this->inputFilter->add($factory->createInput(array('name'=>'content','required'=>true,'filters'=>array(array('name'=>'StripTags'),array('name'=>'StringTrim'))'validators'=>array(array('name'=>'StringLength','options'=>array('encoding'=>'UTF-8','min'=>5,'max'=>100))))));建過(guò)濾規(guī)則并將附加到InputFilter上,此處的過(guò)濾規(guī)則為一個(gè)過(guò)濾鏈,規(guī)則內(nèi)容:name 為 content的標(biāo)簽為必填項(xiàng),并對(duì)其他輸入進(jìn)行去HTML標(biāo)簽(StripTags)和去空格(StringTrim)處理,同時(shí)對(duì)輸入內(nèi)容進(jìn)一步校驗(yàn),校驗(yàn)規(guī)則為將輸入內(nèi)容限制為utf-8,同時(shí)長(zhǎng)度為5~100的個(gè)字符。
public function setInputFilter(InputFilterInterface $inputFilter) 設(shè)置過(guò)濾,實(shí)現(xiàn)接口的方法
6.1.3.4.3 創(chuàng)建表單
通過(guò)上面兩個(gè)小節(jié)的內(nèi)容已經(jīng)完成了創(chuàng)建表單的基本要素,下面將通過(guò)控制器中的方法來(lái)引用上面的內(nèi)容來(lái)生成一個(gè)新聞表單。
打開(kāi)文件:`/module/Application/src/Application/Controller/NewsController.php`,添加如下內(nèi)容:
導(dǎo)入包
~~~
use Application\Form\NewsForm;
use Application\Model\News;
~~~
修改public function addAction(){} 函數(shù)內(nèi)容,具體內(nèi)容如下:
~~~
public function addAction(){
$form = new NewsForm();
$form->get('submit')->setValue('Add');
$request = $this->getRequest();
if($request->isPost()){
$news= new News();
$form->setInputFilter($news->getInputFilter());
$form->setData($request->getPost());
if($form->isValid()){
$album->exchangeArray($form->getData());
$this->getNewsTalbe()->saveNews($news);
return $this->redirect()->toRoute('news');// 或者使用URL$this->redirect()->toUrl('/news/list');
}
}
return array('form'=>$form);
}
~~~
addAction 函數(shù)內(nèi)容代碼解釋?zhuān)?
$form = new NewsForm(); 實(shí)例化一個(gè)新聞表單
$form->get('submit')->setValue('Add');修改新聞表單的提交按鈕名稱(chēng)
$request = $this->getRequest(); 獲取用戶(hù)請(qǐng)求
if($request->isPost()){} 判斷 是否為 POST請(qǐng)求
$form->setInputFilter($news->getInputFilter()); 為表單添加過(guò)濾器
$form->setData($request->getPost()); 設(shè)置表單數(shù)據(jù)
if($form->isValid()){} 判斷表單是否通過(guò)校驗(yàn)
$news->exchangeArray($form->getData()); 能表單數(shù)據(jù)進(jìn)行轉(zhuǎn)換
$this->getNewsTalbe()->saveNews($news); 通過(guò)模型將表單提交的數(shù)據(jù)保存到數(shù)據(jù)庫(kù)里
return $this->redirect()->toRoute('news'); 實(shí)現(xiàn)路由跳轉(zhuǎn)
return array('form'=>$form); 返回一個(gè)表單對(duì)象
6.1.3.4.4 模板輸出表單
收到從控制器中傳遞過(guò)來(lái)數(shù)據(jù)并將數(shù)據(jù)在模板中輸出,打開(kāi)文件:/module/Application/view/application/news/add.phtml,文件具體內(nèi)容如下:
$form = $this->form; // 接收到控制器傳遞過(guò)來(lái)的表單對(duì)象
$form->setAttribute('action',$this->url('news',array('action'=>'add')));// 設(shè)置表單的action屬性
echo $this->form()->openTag($form);// 打開(kāi)form表單
echo $this->formCollection($this->form);// 輸出表單里的元素集合
echo $this->form()->closeTag();// 閉合form表單
此處是使用簡(jiǎn)潔法輸出表單,即通過(guò)打開(kāi)表單,輸出表單、閉合表單這個(gè)動(dòng)作一次性把表單里的所有元素輸出。這種方法的好處是只用3行代碼就能把表單里的全部元素輸出,缺點(diǎn)就是全部屬性都使用$form對(duì)象的默認(rèn)設(shè)置屬性,靈活度沒(méi)那么好。另一種表單輸出的方法就是對(duì)$form表單對(duì)象里的元素一個(gè)一個(gè)輸出,并且可以對(duì)表單對(duì)象元素進(jìn)行相關(guān)修改,靈活度較好,但代碼量較大。
通過(guò)前面四節(jié)的課內(nèi)容現(xiàn)在可以通過(guò) http://localhost/news/add 打開(kāi)新聞表單了,并可以通過(guò)表單將將數(shù)據(jù)提交到數(shù)據(jù)庫(kù)進(jìn)行保存。頁(yè)面結(jié)果如下:
~~~
header
窗體頂端
Title窗體底端
Content
footer
~~~
6.1.3.4.5 添加模型方法saveNews
要把新聞表單的數(shù)據(jù)能夠提交到數(shù)據(jù)庫(kù)中進(jìn)行保存,還需要在模型中添加保存新聞的模型方法,打開(kāi)模型文件 `/module/Application/src/Application/Model/NewsTables.php` 文件,添加如下方法:
~~~
public function saveNews(News $news)
{
$data = array(
'content' =>$news->content,
'title' =>$news->title
);
$id = (int) $news->id;
if($id == 0){
$this->tableGateway->insert($data);
}else{
if($this->getNews($id)){
$this->tableGateway->update($data,array('id'=>$id));
}else{
throw new \Exception("Could not find row {$id}");
}
}
}
~~~
代碼解釋?zhuān)?
$data = array( 'content' =>$news->content,'title' =>$news->title); 將傳遞過(guò)來(lái)的數(shù)據(jù)保存到數(shù)組中,因?yàn)樵赯F2中對(duì)數(shù)據(jù)的操作很多是通過(guò)數(shù)組來(lái)傳遞的
$this->tableGateway->insert($data); 如果id不存在的時(shí)候?qū)?shù)據(jù)里的數(shù)據(jù)插入到數(shù)據(jù)庫(kù),此處實(shí)現(xiàn)插入功能
$this->tableGateway->update($data,array('id'=>$id)); 如果id存在的時(shí)候,對(duì)數(shù)據(jù)庫(kù)里指定id的數(shù)據(jù)行進(jìn)行更新
throw new \Exception("Could not find row {$id}"); 如果更新出現(xiàn)錯(cuò)誤則拋出一個(gè)異常
public function saveNews(News $news){} 方法說(shuō)明 ,此方法不單用來(lái)保存添加新聞時(shí)的數(shù)據(jù),也將用來(lái)保存更新新聞內(nèi)容后的數(shù)據(jù),即包含了插入和更新功能。
模型方法saveNews 建立好后就可以通過(guò) http://loaclhost/news/add 來(lái)添加新聞并保存到數(shù)據(jù)庫(kù)了。
6.1.3.4.6 修改新聞內(nèi)容
上面一節(jié)內(nèi)容已經(jīng)講解了怎么通過(guò)表單將一個(gè)新插入到數(shù)據(jù)庫(kù)里,接下來(lái)就是要實(shí)現(xiàn)如果使用表單來(lái)修改一條新聞?dòng)涗洸⑺4娴綌?shù)據(jù)庫(kù)。在前一節(jié)講解內(nèi)容的時(shí)候已經(jīng)說(shuō)過(guò) saveNews 保存數(shù)據(jù)功能不僅用于添加新聞,也用于新聞的修改,表單也是重用之前內(nèi)容的表單,所以這些部分的內(nèi)容就不再重復(fù)進(jìn)行講解。下面將重點(diǎn)放在控制器的 editAction方法和edit.phtml模板中。
6.1.3.4.6.1修改模塊路由
在繼續(xù)制作editAction 和 edit.phtml 前我需要對(duì)我們的module.config.php 的模塊文件做一個(gè)小的修改,在修改前可以看一下之前輸出的新聞列表的最后一個(gè)列中 Edit 種 Delete 的鏈接,看看鏈接地址的后面是不是沒(méi)有出現(xiàn)我們平時(shí)做網(wǎng)站時(shí)應(yīng)該出現(xiàn)的id 值。這是由于我們之前對(duì)模塊路由的配置中并沒(méi)有包括對(duì)參數(shù)傳遞的功能,如果路由上沒(méi)有配置這些傳遞參數(shù)的功能,即使你強(qiáng)行在鏈接地址的后面加上去也會(huì)被路由匹配規(guī)則給過(guò)濾掉,最終可能導(dǎo)致一個(gè)404的錯(cuò)誤出現(xiàn)。
打開(kāi)文件:/module/Application/config/module.config.php 將路由 news 區(qū)段修改為如下內(nèi)容:
~~~
'news'=>array(
'type'=>'segment',
'options'=>array(
'route'=>'/news[/][:action][/:id]',
'constraints'=>array(
'action'=>'[a-zA-Z]*',
'id'=>'[0-9]+'
),
'defaults'=>array(
'controller'=>'Application\Controller\News',
'action'=>'index'
),
),
),
~~~
路由做過(guò)調(diào)整的地方:
'route'=>'/news[/][:action]' 修改為 route'=>'/news[/][:action][/:id]',
'id'=>'[0-9]+' 添加了路由中id 的匹配規(guī)則,只匹配數(shù)字類(lèi)型的id
添加模型方法 public function getNews($id){},此方法功能是根據(jù)$id查找數(shù)據(jù)庫(kù)中的新聞?dòng)涗洸⒎祷夭樵?xún)結(jié)果行。打開(kāi)文件:`/module/Application/src/Application/Model/NewsTable.php` 在文件原來(lái)的基礎(chǔ)上添加如下內(nèi)容:
~~~
public function getNews($id){
$id = (int) $id;
$rowset = $this->tableGateway->select(array('id'=>$id));
$row = $rowset->current();
if(!$row){
throw new \Exception("Could not find row {$id}");
}
return $row;
}
~~~
模型方法內(nèi)容解釋?zhuān)?
$id = (int) $id; 將傳遞過(guò)來(lái)的id強(qiáng)制轉(zhuǎn)換為整形
$rowset = $this->tableGateway->select(array('id'=>$id)); 根據(jù)id查詢(xún)新聞結(jié)果集
$row = $rowset->current(); 取出結(jié)果集的第一行記錄
if(!$row){} 判斷是否存在指定id 的新聞?dòng)涗浶?,如果不存在則拋出一個(gè)異常
return $row 返回查詢(xún)結(jié)果的新聞?dòng)涗浶?
6.1.3.4.6.2修改editAction 方法
打開(kāi)文件:`/module/Application/src/Application/Controller/NewsController.php`,找到editAction 方法并將內(nèi)容修改為如下:
~~~
public function editAction(){
$id = (Int) $this->params()->fromRoute('id',0);
if(!$id){
return $this->redirect()->toRoute('news',array('action'=>'add'));
}
try{
$news = $this->getNewsTalbe()->getNews($id);
}catch(\Exception $e){
return $this->redirect()->toRoute('news',array('action'=>'list'));
}
$form = new NewsForm();
$form->bind($news);
$form->get('submit')->setAttribute('value', 'Edit');
$request = $this->getRequest();
if($request->isPost()){
$form->setInputFilter($news->getInputFilter());
$form->setData($request->getPost());
if($form->isValid()){
$this->getNewsTalbe()->saveNews($news);
$this->redirect()->toUrl('/news/list');
}
}
return array('id'=>$id,'form'=>$form);
}
~~~
代碼解釋?zhuān)?
$id = (Int) $this->params()->fromRoute('id',0); 從路由中分離id,也就是獲取新聞id
if(!$id){} 如果id 不存在則直接跳轉(zhuǎn)到添加新聞頁(yè)面
$news = $this->getNewsTalbe()->getNews($id); 通過(guò)數(shù)據(jù)網(wǎng)關(guān)獲取指定id的新聞?dòng)涗?
return $this->redirect()->toRoute('news',array('action'=>'list')); 如果在獲取新聞?dòng)涗浿谐霈F(xiàn)異常則直接跳轉(zhuǎn)到列表頁(yè)
$form = new NewsForm(); 實(shí)例化一個(gè)新聞表單
$form->bind($news); 給表單綁定數(shù)據(jù)
$form->get('submit')->setAttribute('value', 'Edit');設(shè)置表單提交按鈕名稱(chēng)
$request = $this->getRequest(); 獲取用戶(hù)請(qǐng)求
if($request->isPost()){} 判斷是否通過(guò)post提交的請(qǐng)求
$form->setInputFilter($news->getInputFilter()); 為表單添加過(guò)濾器
$form->setData($request->getPost());為表單附加數(shù)據(jù)
if($form->isValid()){} 判斷表單數(shù)據(jù)是否通過(guò)校驗(yàn)
$this->getNewsTalbe()->saveNews($news);將編輯后的數(shù)據(jù)更新到數(shù)據(jù)庫(kù)
$this->redirect()->toUrl('/news/list'); 跳轉(zhuǎn)到新聞列表
return array('id'=>$id,'form'=>$form); 返回一個(gè)表單對(duì)象和新聞id到模板,此處的表單對(duì)象與前面章節(jié)中插入數(shù)據(jù)的表單有所區(qū)別,此表單里面的標(biāo)簽都已經(jīng)有數(shù)據(jù)的了,而之前插入新聞的表單只是一個(gè)空的表單。
6.1.3.4.6.3修改edit.phtml模板
打開(kāi)文件:`/module/Applicaiton/view/application/news/edit.phtml`,將文件內(nèi)容修改為如下:
~~~
$form = $this->form;
$form->setAttribute('action',$this->url('news',array('action'=>'edit','id'=>$this->id))); // 設(shè)置表單的action 屬性
echo $this->form()->openTag($form);// 打開(kāi)form 表單
echo $this->formCollection($this->form);// 生成表單元素
echo $this->form()->closeTag();// 關(guān)閉表單
~~~
到目前為止就已經(jīng)完成了新聞修改功能的全部工作,現(xiàn)在可以通過(guò)新聞列表中的 Edit 鏈接來(lái)打開(kāi)修改新聞的頁(yè)面了,修改新聞的頁(yè)面與添加新聞的頁(yè)面外觀(guān)上看上去是一樣的;只不過(guò)新聞修改頁(yè)面多了一重判斷,當(dāng)指定id的新聞?dòng)涗洿嬖跁r(shí)則可以進(jìn)行修改,如果指定的id還在,則進(jìn)行的是添加功能。
6.1.3.4.7 刪除新聞?dòng)涗?
本節(jié)將講解關(guān)于數(shù)據(jù)庫(kù)CURD中的最后一個(gè)是重要環(huán)節(jié)--數(shù)據(jù)庫(kù)的刪除操作,本章節(jié)所講解的主要任務(wù)是實(shí)現(xiàn)對(duì)指定新聞id的刪除功能。
6.1.3.4.7.1修改deleteAction 方法
打開(kāi)文件:`/module/Application/src/Application/Controller/NewsController.php`,找到deleteAction 方法并將內(nèi)容修改為如下:
~~~
public function deleteAction(){
$id = (Int) $this->params()->fromRoute('id',0);
if(!$id){
$this->redirect()->toUrl('/news/list');
}
$request = $this->getRequest();
if($request->isPost()){
$del = $request->getPost('del','No');
if($del=='Yes'){
$id = (Int)$request->getPost('id');
$this->getNewsTalbe()->deleteNews($id);
}
$this->redirect()->toUrl('/news/list');
}
return array('id'=>$id,'news'=>$this->getNewsTalbe()->getNews($id));
}
~~~
代碼解釋?zhuān)?
$id = (Int) $this->params()->fromRoute('id',0) 獲取新聞?dòng)涗沬d
if(!$id){$this->redirect()->toUrl('/news/list');} 判斷是否有傳遞id 值,如果沒(méi)有則直接跳轉(zhuǎn)到新聞列表頁(yè)面
if($request->isPost()){} 判斷用戶(hù)請(qǐng)求類(lèi)型是否為post 請(qǐng)求
$del = $request->getPost('del','No'); 獲取用戶(hù)處理動(dòng)作{Yes或No}
if($del=='Yes'){} 如果用戶(hù)操作就連Yes,則進(jìn)行刪除操作
$id = (Int)$request->getPost('id'); 獲取新聞id
$this->getNewsTalbe()->deleteNews($id); 刪除指定的新聞?dòng)涗?
$this->redirect()->toUrl('/news/list'); // 完成刪除后跳轉(zhuǎn)到新聞列表
return array('id'=>$id,'news'=>$this->getNewsTalbe()->getNews($id)); 如果用戶(hù)請(qǐng)求為非post 請(qǐng)求,則返回?cái)?shù)據(jù)給模板
6.1.3.4.7.2添加模型 deleteNews方法
打開(kāi)模型文件 `/module/Application/src/Application/Model/NewsTables.php` 文件,添加如下方法:
~~~
public function deleteNews($id){
$this->tableGateway->delete(array('id'=>$id));
}
~~~
代碼解釋?zhuān)?
$this->tableGateway->delete(array('id'=>$id)); 根據(jù)傳遞過(guò)來(lái)的id刪除新聞?dòng)涗?
6.1.3.4.7.2修改delete.phtml模板
打開(kāi)文件:/module/Applicaiton/view/application/news/delete.phtml,將文件內(nèi)容修改為如下:
~~~
$title = 'Delete news';
$this->headTitle($title);
?>
<h1><?php echo $this->escapeHtml($title); ?></h1>
<p>Are you sure that you want to delete
'<?php echo $this->escapeHtml($news->title); ?>' by
'<?php echo $this->escapeHtml($news->content); ?>'?
</p>
<?php
$url = $this->url('news', array(
'action' => 'delete',
'id' => $this->id,
));
?>
<form action="<?php echo $url; ?>" method="post">
<div>
<input type="hidden" name="id" value="<?php echo (int) $news->id; ?>" />
<input type="submit" name="del" value="Yes" />
<input type="submit" name="del" value="No" />
</div>
</form>
~~~
代碼解釋?zhuān)?
$this->headTitle($title); 設(shè)置文件標(biāo)題
echo $this->escapeHtml($news->title); 輸出新聞標(biāo)題
echo $this->escapeHtml($news->content); 輸出新聞內(nèi)容
$url = $this->url('news', array('action' => 'delete','id' => $this->id)); 構(gòu)造表單的action鏈接
以上為主要的php內(nèi)容,致以表單中其他的html代碼就不再做解釋。下面轉(zhuǎn)到新聞列表頁(yè)面,http://localhost/news/list
在新聞列表中點(diǎn)擊Delete將跳轉(zhuǎn)到刪除的確認(rèn)頁(yè)面,然后確認(rèn)是否刪除。
- 序言
- 第1章 Zend Framework2 簡(jiǎn)介
- 1.1 Zend Framework2 簡(jiǎn)介
- 1.2 下載安裝
- 1.3 搭建開(kāi)發(fā)環(huán)境
- 第2章 創(chuàng)建ZF2項(xiàng)目
- 2.1 新建一個(gè)項(xiàng)目
- 2.2 配置網(wǎng)站
- 2.3 偽靜態(tài) .htaccess文件
- 2.4 添加啟動(dòng)/入口文件
- 2.5 添加全局配置文件
- 2.6 添加自動(dòng)加載文件 init_autoloader.php
- 2.7 IndexController 控制器
- 第3章 創(chuàng)建模塊文件
- 3.1 Module 文件
- 3.2 module.config 文件
- 3.2.1 router 路由配置
- 3.2.2 controllers控制器配置
- 3.2.3 view_manager 視圖管理器
- 3.2.4 service_manager 服務(wù)管理器
- 3.2.5 translator 翻譯器
- 3.2.6 navigation 導(dǎo)航條
- 第4章 創(chuàng)建控制器
- 4.1 控制器簡(jiǎn)介
- 4.2 新建控制器
- 4.3 添加控制器的Action
- 第5章 創(chuàng)建視圖模板
- 5.1 創(chuàng)建模板
- 5.2 模板配置
- 5.3 編寫(xiě)布局和錯(cuò)誤異常模板
- 5.4 編寫(xiě)Action 對(duì)應(yīng)的模板文件
- 5.5 訪(fǎng)問(wèn) IndexAction
- 第6章 創(chuàng)建模型
- 6.1 ORM 對(duì)象映射法
- 6.2 使用分頁(yè)導(dǎo)航
- 6.3 自定模型
- 6.4 章節(jié)總結(jié)
- 第7章 實(shí)例應(yīng)用
- 7.1 建立Album 模塊
- 7.2 添加模塊文件
- 7.3 添加模塊配置文件
- 7.4 創(chuàng)建數(shù)據(jù)表 album
- 7.5 添加模型文件
- 7.6 添加表單 AlbumForm
- 7.7 添加控制器 AlbumController
- 7.8 添加模板文件
- 第8章 用戶(hù)認(rèn)證
- 8.1 建立數(shù)據(jù)表
- 8.2 新建認(rèn)證類(lèi)
- 8.3 引用認(rèn)證類(lèi)
- 第9章 結(jié)束語(yǔ)
