1
PHP程式設計討論區 / 回覆: 我在測試Zend_View時發生錯誤
« 於: 2010-05-09 13:58 »
試一下把view render關掉.
$this->_helper->viewRenderer->setNoRender(true);
$this->_helper->viewRenderer->setNoRender(true);
這裡允許您檢視這個會員的所有文章。請注意, 您只能看見您有權限閱讀的文章。
<?
//建立Zend_Acl Object,權限控制
。。。。。
//建立Zend_Auth Object
。。。。
//把helper path加進去,因為controller plugin需要使用到My_Plugin_Auth class
$view = new Zend_View();
$view->addHelperPath(APPLICATION_DIRECTORY.'/library/My/View/Helper','My_View_Helper');
$viewRender = new Zend_Controller_Action_Helper_ViewRenderer();
$viewRender->setView($view);
Zend_Controller_Action_HelperBroker::addHelper($viewRender);
$controller = Zend_Controller_Front::getInstance();
$controller->addControllerDirectory('application/auth/controllers','auth');
$controller->addControllerDirectory('application/admin/controllers','admin');
//加入controller plugin,檢查使用者權限
$controller->registerPlugin(new My_Plugin_Auth($auth,$acl));
?>
/**
* 檢查使用者是否登入
*/
class My_Acl_AuthAssert implements Zend_Acl_Assert_Interface {
/*
* @param Object
*/
private $_auth;
/*
* @param Object Zend_Auth
*/
public function __construct(Zend_Auth $auth)
{
$this->_auth = $auth;
}
/*
* @param Object Zend_Acl
* @param Object Zend_Acl_Role_Interface
* @param Object Zend_Acl_Resourece_interface
*
* @return boolean
*/
public function assert(Zend_Acl $acl, Zend_Acl_Role_Interface $role = null, Zend_Acl_Resource_Interface $resource = null, $privilege = null) {
return $this->_isLogin();
}
/*
* check user login status
*
* @return boolean
*/
private function _isLogin()
{
//你所需要的檢查程式碼
}
}
?>
<?php
/*
* 在preDispatch中去檢查使用者是否對該controller/action有權限
*/
class My_Plugin_Auth extends Zend_Controller_Plugin_Abstract {
/*
*@param Object
*/
private $_auth;
/*
* @param Object
*/
private $_acl;
/*
* @param Array
*/
private $_no_auth = array(
'module' => 'auth',
'controller' => 'index',
'action' => 'index'
);
/*
* @param Array
*/
private $_no_acl = array(
'module' => 'admin',
'controller' => 'index',
'action' => 'index'
);
public function __construct(Zend_Auth $auth,Zend_Acl $acl)
{
$this->_auth = $auth;
$this->_acl = $acl;
}
public function preDispatch()
{
$request = $this->getRequest();
$module = $request->getModuleName();
$controller = $request->getControllerName();
$action = $request->getActionName();
$resource = $module.'_'.$controller;
$acl = $this->_acl;
//設定使用者角色,如果登入的話,把使用者設定成admin角色
if(isset($_SESSION['AUTH'])) :
$role = 'admin';
else :
$role = 'guest';
endif;
//檢查資源是否加入到acl object
if($acl->has($resource)) :
//如果使用者没有對該資源的權限,把使用者redirect
if(!$acl->isAllowed($role,$resource,$action)) :
switch($role) :
case 'admin':
$module = $this->_no_acl['module'];
$controller = $this->_no_acl['controller'];
$action = $this->_no_acl['action'];
break;
default:
$module = $this->_no_auth['module'];
$controller = $this->_no_auth['controller'];
$action = $this->_no_auth['action'];
break;
endswitch;
endif;
//設定redirect的module/controller/action
$request->setModuleName($module);
$request->setControllerName($controller);
$request->setActionName($action);
else :
//設定redirect的module/controller/action
if($role == 'admin') :
$module = $this->_no_acl['module'];
$controller = $this->_no_acl['controller'];
$action = $this->_no_acl['action'];
else :
$module = $this->_no_auth['module'];
$controller = $this->_no_auth['controller'];
$action = $this->_no_auth['action'];
endif;
$request->setModuleName($module);
$request->setControllerName($controller);
$request->setActionName($action);
endif;
}
}
?>
setControllerDirectory 可以接受陣列 (多模組) ,所以發問者的寫法是沒錯的。
不過兩種寫法都沒差,而我建議採用 setControllerDirectory 加陣列的方式比較方便。
小弟目前著手一個新的案子打算嘗試以framework的方式來改變自己程式風格...但研究了兩三天在應用上還是有點棘手
所謂MVC架構我是把他想成:
- 舉凡有關資料存取的程式介面都放在models內。
有關系統功能邏輯,自己開發的類別等都應放在controllers內。
而樣板、頁面表現都放在view下面。
但是我看了uberr前輩所發表的教學第一篇跟第二篇(有關資料庫存取),在比對官方手冊上提供的對應範例,感覺不太對的起來,發現對於實際要架構程式碼不知道該如何規劃:
先提我對教學部份的疑問,uberr前輩示範如何使用controllers是像這樣代碼: [選擇]$frontController = Zend_Controller_front::getInstance(); // create一個Front Object
$frontController->setControllerDirectory('./application/controllers'); // 設定Controller目錄的路徑
$frontController->dispatch();
//然後在controllers下以這個來實做
class IndexController extends Zend_Controller_Action
{
public function indexAction()
{
$this->view->message = "Zend Framework tutorial"; // 回傳 message
}
public function helloAction()
{
$this->view->message = "Hello World"; // 回傳 message
}
}
而這是官網針對controlle使用的範例,看得出是把靜訊息都放在index.phtml顯示....代碼: [選擇]require_once 'Zend/Controller/Front.php';
Zend_Controller_Front::run('/path/to/app/controllers');
但不懂呼叫run()方法跟dispatch()方法上得差異點在哪?只感覺使用run的話是把目錄直接給進去....
而我發現程式進入點index.php僅僅將處理導向controllers內的程式,所以意思是要區分不同的功能頁面就以網址上的連結來操作嗎?
比如說我首頁提供編輯功能(EditControllers)、修改功能(ChangeControllers),當我點選了編輯要指引連結到http://domainname/edit 、選修改的話則是 http://domainname/change 他會執行到Controller內的方法?
我想這部份我是對uberr前輩所示範index、hello感到疑惑....
我希望引入smarty到Zend_View,我知道官網有提供一個範例使用class Zend_View_Smarty implements Zend_View_Interface的方式,但我想不通這個程式碼是該放在哪個架構下並怎麼引用他?放在controllers內、放在views內?
而smarty所需的template跟template_c是放在views內比較符合MVC的精神嗎?
由於初學Zend_framework也剛接觸MVC觀念....不知道我的問題會不會太基本...但研究了兩三天還是感覺不太適應中,希望前輩指教一下~~感謝
<?php
$a = 60.200 + 89.700;
$b = 150;
echo 'orginal result:'.($b-$a)."<br>";
$c = 60.200;
$d = 89.700;
$x = bcadd($c,$d,3);
echo 'bcadd result:'.$x."<br>";
echo 'bcmath result:'.bcsub($b,$x,1);
?>
Class InvoiceController extends Zend_Controller_Action {
Public function addAction() {
// 如果新增成功,寫進log File裡頭
If() {
// 呼叫Log Action,同時重設Dispatch的flag
$this->_forward(‘log’);
}
}
Public function logAction() {
//寫入到log file
}
}
$controller = Zend_Controller_Front::getInstance();
$controller->setDirectory(‘./application/controllers’);
$controller->throwExceptions(false);
$controller->returnResponse(‘true’); // 要求回傳response,由自己處理
$response = $controller->dispatch();
// 處理回傳的response
If($response->isException()) :
Endif;
$response->sendResponse(); // Output你的header和body
請問一下:Zend Framework 的優點跟特色是什麼?
CREATE TABLE `user` (
`id` mediumint(9) NOT NULL auto_increment,
`first_name` varchar(255) default NULL,
`last_name` varchar(255) default NULL,
`age` int(3) default NULL,
PRIMARY KEY (`id`)
)
<?php
set_include_path('.'.PATH_SEPARATOR.'./library/'.PATH_SEPARATOR.'./application/models/');
include "Zend/Loader.php";
Zend_Loader::loadClass('Zend_Controller_Front');
Zend_Loader::loadClass('Zend_Db');
Zend_Loader::loadClass('Zend_Config_Ini');
Zend_Loader::loadClass('Zend_Registry');
Zend_Loader::loadClass('Zend_Validate_NotEmpty');// 滙入Validate Not Empty Class
Zend_Loader::loadClass('Zend_Validate_Between');// 滙入Validate Between Class
Zend_Loader::loadClass('Zend_Filter_Input');// 滙入Filter Input Class
$config = new Zend_Config_Ini('./application/config/config.ini','general');
$dbAdapter = Zend_Db::factory($config->db->adapter,$config->db->config->toArray());
Zend_Registry::set('dbAdapter',$dbAdapter);
$frontController = Zend_Controller_front::getInstance();
$frontController->setControllerDirectory('./application/controllers');
$frontController->dispatch();
<?php
/** Zend_Controller_Action */
require_once('Zend/Controller/Action.php');
require_once('My/class.DataManager.php');// 滙入DataManager Class
require_once('My/class.User.php');// 滙入User Class
class IndexController extends Zend_Controller_Action {
public function init() {
$this->view->baseUrl = $this->_request->getBaseUrl();
}
public function indexAction() {
$this->view->entities = DataManager::getAllUserAsObject(); // 拿取user list,return每一個user object
}
public function addAction() {
if($this->getRequest()->isPost()) : //如果是由post傳送過來的data,就新増使用者
$first_name = $this->_request->getParams('first_name'); //拿取的data是用array,所以$first_name,$last_name,$age都是array來,因為Zend_Filter_Input是要你道入array才會幫你做験証。請記得getParam和getParams是不同的東西,一個回傳String,另一個回傳array
$last_name = $this->_request->getParams('last_name');
$age = $this->_request->getParams('age');
$user = new User(); //create使用者 user object
$user->setTable('user'); //設定新増到哪一個table
$user->setField('first_name',$first_name); //把使用者輸入的data,設定成user object的variable
$user->setField('last_name',$last_name);
$user->setField('age',$age);
$validate_handle = $user->validate(); //****做験証**** 請留意class.User.php裡頭validate function
if($validate_handle) : //如果験証回傳true,就新増使用者,然後redirect去index/index,顯示使用者information
$user->save();
$this->_redirect('/');
else : //如果回傳false,就顯示error
$this->view->errors = $user->getErrors();
endif;
endif;
}
}
<h4>Add User Form</h4>
<form method="post" name="adduserform" action="<? echo $this->baseUrl; ?>/index/add">
first name: <input name="first_name" type="text" /> * must not empty <br>
last name: <input name="last_name" type="text" /> * must not empty <br>
age: <input name="age" type="text" /> // must between 1-140 <br>
<input type="submit" value="Add User" />
</form>
<?
if($this->errors):
foreach($this->errors as $error) :
echo $error."<br>";
endforeach;
endif;
?>
<script>
function redirect($a) {
window.location = $a;
}
</script>
<input type="button" value="Add User" onclick='redirect("<? echo $this->baseUrl; ?>/index/add");' />
<?php
if($this->entities) :
foreach($this->entities as $entity) :
echo "<h4>User</h4>";
echo $entity->__toString()."<br>"; // magic function convert object to string __string(),php 5.2 之後才support magic function,如果 php 5.2之前的version就要加上->__toString()
echo "<hr>";
endforeach;
else :
echo 'no user found';
endif;
?>
<?php
require_once('My/class.GenericObject.php');
class User extends GenericObject {
private $_errors;
public function __construct($user_id = null) {
$this->_errors = array();
$this->_user_id = $user_id;
}
public function __toString() {
$result_rows = parent::getAllFields();
$s = '';
foreach($result_rows as $key => $value) :
$s .= $key.' : '.$value.'<br>';
endforeach;
return $s;
}
//*********************************Important***********************************************
public function validate() {
$first_name = $this->_Modify_fields['first_name'];
$last_name = $this->_Modify_fields['last_name'];
$age = $this->_Modify_fields['age'];
$filter = array( //create一個filter
'*' => array( //對所input都進行過濾
"StringTrim", //過濾空白
"StripTags" //過濾html,php tags
));
$defaultChain = new Zend_Validate(); //create 認證物件,套用到first_name,last_name
$defaultChain->addValidator(new Zend_Validate_NotEmpty(),false); //加入Not Empty認證功能
$validators = array(
'first_name' => $defaultChain
);
$first_name = new Zend_Filter_Input($filter,$validators,$first_name); //把filter,validate連在一起,然後對first_name作認証工作。
$validators = array(
'last_name' => $defaultChain
);
$last_name = new Zend_Filter_Input($filter,$validators,$last_name);//把filter,validate連在一起,然後對last_name作認証工作。
//因為age一定是數字,和有限制,所以不可以把defaultChain套用到age
$ageChain = new Zend_Validate(); //新増一個認證物件,套用到age
$ageChain->addValidator(new Zend_Validate_Between('1','140'));//加入Between認證功能,限制age在1-140歳
$validators = array(
'age' => $ageChain
);
$age = new Zend_Filter_Input($filter,$validators,$age);//把filter,validate連在一起,然後對$age作認証工作。
//検查験証是否有錯誤出現
if ($first_name->hasInvalid() || $first_name->hasMissing()) :
foreach ($first_name->getMessages() as $message) :
array_push($this->_errors,$message[0]); //把錯誤寫入到 $this->errors
endforeach;
elseif ($last_name->hasInvalid() || $last_name->hasMissing()) :
foreach ($last_name->getMessages() as $message) :
array_push($this->_errors,$message[0]); //把錯誤寫入到 $this->errors
endforeach;
elseif ($age->hasInvalid() || $age->hasMissing()) :
foreach ($age->getMessages() as $message) :
array_push($this->_errors,$message[0]); //把錯誤寫入到 $this->errors
endforeach;
endif;
if(sizeof($this->_errors) > 0) : //検查$this->errors裡頭有没有東西
return false;
else :
return true;
endif;
}
public function getErrors() {
return $this->_errors;
}
}
?>
<?php
class DataManager {
public static function getAllUserAsObject() {
$db = Zend_Registry::get('dbAdapter');
$select = $db->select();
$select->from('user','*');
$result_rows = $db->fetchAll($select);
$obj_array = array();
if($result_rows) :
foreach($result_rows as $rows) :
$refObjArray = &$obj_array[];
$refObjArray = new User($rows['id']);
$refObjArray->forceReloaded();
foreach($rows as $key => $value) :
$refObjArray->setField($key,$value);
endforeach;
endforeach;
return $obj_array;
else :
return array();
endif;
}
}
?>
<?php
class GenericObject {
private $_isLoaded = false;
private $_table_name;
private $_class_name;
private $_result_rows = array();
private $_user_id;
protected $_Modify_fields = array();
private function _load() {
DataManager::getAllUserAsObject();
}
private function _checkLoaded() {
if(!$this->_isLoaded) :
$this->_load();
endif;
}
public function forceReloaded() {
$this->_isLoaded = true;
}
public function setTable($table_name) {
$this->_table_name = $table_name;
}
public function getField($field_name) {
$this->_checkLoaded();
return $this->_result_rows[$field_name];
}
public function getAllfields() {
$this->_checkLoaded();
return $this->_result_rows;
}
public function setField($field_name,$value) {
$this->_checkLoaded();
$this->_Modify_fields[$field_name] = $value;
$this->_result_rows[$field_name] = $value;
}
public function numberOfItem() {
$this->_checkLoaded();
return sizeof($this->_result_rows);
}
public function save() {
$user_id = $this->_user_id;
$table_name = $this->_table_name;
$data = array();
foreach($this->_Modify_fields as $key => $value) :
$data[$key] = $value[$key];
endforeach;
$db = Zend_Registry::get('dbAdapter');
try {
if(!$user_id) :
$query_handle = $db->insert($table_name,$data);
else :
$where = "id = ".$user_id;
$query_handle = $db->update($table_name,$data,$where);
endif;
}
catch (Exception $e) {
echo "Error: ".$e->getMessage();
}
}
}
?>
用php設計的上傳檔案程式:
用echo $_FILES['uploadFile']['type']; 在不同的Client上會顯示有所不同, 例如:
mpeg檔: 有些顯示為:video/mpg, 有些則顯示為: video/mpeg
mov檔: 有些顯示為:video/quicktime, 有些則顯示為: application/octet-stream
mp3檔: 有些顯示為:audio/mp3, 有些則顯示為: audio/mpeg
aac檔: 有些顯示為:'audio/aac, 有些則顯示為: application/octet-stream
怎會這樣? 請指點一下, THX .....
<?php
set_include_path('.'.PATH_SEPARATOR.'./library/'.PATH_SEPARATOR.'./application/m odels/'); // 設定module的位置
include "Zend/Loader.php"; // 必需要include的module,它是把需要的module導入
Zend_Loader::loadClass('Zend_Controller_Front'); // Zend_Controller_Front是必需的module,它是用來控制route
Zend_Loader::loadClass('Zend_Db');
Zend_Loader::loadClass('Zend_Config_Ini');
Zend_Loader::loadClass('Zend_Registry');
Zend_Loader::loadClass('Zend_Auth'); // 加入 Auth Module
Zend_Loader::loadClass('Zend_Auth_Adapter_DbTable'); //加入 Auth Adapter Table Module
$config = new Zend_Config_Ini('./application/config/config.ini','general'); // 引入資料庫config檔案
// 設定資料庫介面
$dbAdapter = Zend_Db::factory($config->db->adapter,$config->db->config->toArray());
Zend_Registry::set('dbAdapter',$dbAdapter);
$frontController = Zend_Controller_front::getInstance(); // create一個Front Object
$frontController->setControllerDirectory('./application/controllers'); // 設定Controller目錄的路徑
$frontController->dispatch();
<?php
class IndexController extends Zend_Controller_Action
{
public function init() {
$this->view->baseUrl = $this->_request->getBaseUrl(); // 設定baseUrl
}
public function indexAction()
{
// 檢查使用者是否登入
$auth = Zend_Auth::getInstance();
if ($auth->hasIdentity()) : // 如果登入,重導使用者到success page
$this->_redirect('/index/success');
else :
$this->_redirect('/index/login'); // 重導使用者到login page
endif;
}
public function loginAction()
{
// 檢查使用者是否登入
$auth = Zend_Auth::getInstance(); // 建立一個Auth Object
if ($auth->hasIdentity()) : // 如果登入,重導使用者到success page
$this->_redirect('/index/success');
endif;
try {
if ($this->_request->isPost()) : // 如果資料是從post傳過來,就開始做認證
$db = Zend_Registry::get('dbAdapter'); // 引入資料庫介面
// 使用者輸入的資料
$username = $this->_request->getParam('username');
$password = $this->_request->getParam('password');
$authAdapter = new Zend_Auth_Adapter_DbTable($db,'users','username','password'); // 設定Auth介面.
//@ param1: database adapter
//@ param2: table
//@ param3: username column
//@ param 4: password column
// 把使用者輸入的username and password儲存到Auth介面
$authAdapter->setIdentity($username);
$authAdapter->setCredential($password);
// 開始做認證工作
$validate = $auth->authenticate($authAdapter); // 對比使用者輸入的資料跟資料庫是否一樣
// 如果認證成功,就把table裡頭的資料寫入到Storage裡,除了password
if ($validate->isValid()) :
$auth->getStorage()->write($authAdapter->getResultRowObject(null,'password')); // 寫入到Storage裡頭
//@param1 : null代表全部column,如果你只想寫入某些資料,例如 username and realname,可以使用array,array('username','realname')
//@param2 : 不需要寫入的column,password是一個很重要的資料,千萬不要把它寫到session裡頭去.
$this->_redirect('/index/success'); // 重導使用者到success page
else :
$this->view->errorMessage = 'Login failed,Please try again.'; //如果登入失敗.重導使用者到login page,顯示失敗訊息.
endif;
endif;
}
catch(Zend_Exception $e) {
echo "Error: ".$e->getMessage();
}
}
public function logoutAction()
{
try {
Zend_Auth::getInstance()->clearIdentity(); //清除Storage裡頭的資料
$this->_redirect('/'); //重導使用者到login page
}
catch(Zend_Exception $e) {
echo "Error: ".$e->getMessage();
}
}
public function successAction()
{
// 檢查使用者是否登入
$auth = Zend_Auth::getInstance();
if (!$auth->hasIdentity()) : // 如果沒有登入,重導使用者到login page
$this->_redirect('/index/login');
endif;
}
}
<? if (!empty($this->errorMessage)) :
echo $this->errorMessage; //顯示錯鋘訊息
endif;
?>
<form method="post" name="login" action="<?echo $this->baseUrl; ?>/index/login">
username:<input type="text" name="username" /><br>
password:<input type="password" name="password" /><br>
<input type="submit" value="login" />
</form>
<?
echo "Login successed";
?>
<form method="post" name="logout" action="<?echo $this->baseUrl; ?>/index/logout">
<input type="submit" value="logout" />
</form>
[general]
db.adapter = mysqli // 把它改成你的所使用的RDBMS
db.config.host = localhost // 資料庫的位置
db.config.username = username // 連接資料庫的用戶名
db.config.password = password // 連接資料庫的密碼
db.config.dbname = database // 資料庫的名稱
<?php
set_include_path('.'.PATH_SEPARATOR.'./library/'.PATH_SEPARATOR.'./application/m odels/'); // 設定module的位置
include "Zend/Loader.php"; // 必需要include的module,它是把需要的module導入
Zend_Loader::loadClass('Zend_Controller_Front'); // Zend_Controller_Front是必需的module,它是用來控制route
Zend_Loader::loadClass('Zend_Db');
Zend_Loader::loadClass('Zend_Config_Ini');
Zend_Loader::loadClass('Zend_Registry');
$config = new Zend_Config_Ini('./application/config/config.ini','general'); // 引入資料庫config檔案
// 設定資料庫介面
$dbAdapter = Zend_Db::factory($config->db->adapter,$config->db->config->toArray());
Zend_Registry::set('dbAdapter',$dbAdapter);
$frontController = Zend_Controller_front::getInstance(); // create一個Front Object
$frontController->setControllerDirectory('./application/controllers'); // 設定Controller目錄的路徑
$frontController->dispatch();
<?php
class IndexController extends Zend_Controller_Action
{
public function indexAction()
{
try {
$db = Zend_Registry::get('dbAdapter'); // 引入資料庫介面
$select = $db->select();
$select->from('bank','*') // or ('database',array('id','username'...etc)
->where('bank_code != ?','BBB')
->order('bank_code');
$result = $db->fetchAll($select); // 結果是以Array回傳
$this->view->data = $result;
}
catch(Zend_Exception $e) {
echo "Error: ".$e->getMessage();
}
}
}
<?php
foreach($this->data as $key => $value) :
echo "bankcode=".$value['bank_code']." : bank=".$value['bank']."<br>";
endforeach;
?>
class AuthController extends Zend_Controller_Action
{
public function loginAction()
{
// check username and password
}
}
<?php
set_include_path('.'.PATH_SEPARATOR.'./library/'.PATH_SEPARATOR.'./application/m odels/'); // 設定module的位置
include "Zend/Loader.php"; // 必需要include的module,它是把需要的module導入
Zend_Loader::loadClass('Zend_Controller_Front'); // Zend_Controller_Front是必需的module,它是用來控制route
$frontController = Zend_Controller_front::getInstance(); // create一個Front Object
$frontController->setControllerDirectory('./application/controllers'); // 設定Controller目錄的路徑
$frontController->dispatch();
<?php
class IndexController extends Zend_Controller_Action
{
public function indexAction()
{
$this->view->message = "Zend Framework tutorial"; // 回傳 message
}
public function helloAction()
{
$this->view->message = "Hello World"; // 回傳 message
}
}
<?php
echo $this->message;
?>
<?php
echo $this->message;
?>
uberr 說得好像跟hayaman212要的不太一樣,hayaman212要的似乎是在瀏覽器的檢視原始碼要有變更。
但是印象中,目前所有瀏覽器的檢視原始碼在 javascript 動作後,基本上都不會改變其內容。
可能要用像是 firefox webdeveloper 套件中的功能,檢視變更過的原始碼,才會看到變更的後的內容..