初学Phreeze
换了份工作,换了个框架,那就学学吧。。
我从网站上下载了phreeze-master,这是一个成功的案例,我自己写了一个案例,同样是成功的,现在我来说一下需要注意的地方。
Phreeze 同样是单一入口的文件,他和其它框架首先特别明显的不同点是他的三个文件:‘_app_config.php’,'_global_config.php','_machine_config.php',这三个文件是整个项目的配置文件,这三个文件的加载顺序是:
include_once("_global_config.php");//defines a singleton the setting
include_once("_app_config.php");//the php include path
include_once("_machine_config.php");//contains the setting the pertain to a specific server environment
1 <?php 2 /** 3 * @package Adserv 4 * 5 * MACHINE-SPECIFIC CONFIGURATION SETTINGS 6 * 7 * The configuration settings in this file can be changed to suit the 8 * machine on which the app is running (ex. local, staging or production). 9 * 10 * This file should not be added to version control, rather a template 11 * file should be added instead and then copied for each install 12 */ 13 14 require_once 'verysimple/Phreeze/ConnectionSetting.php'; 15 require_once("verysimple/HTTP/RequestUtil.php"); 16 17 /** 18 * Normally DB connection info would go here, but phreeze builder doesn't actually 19 * have any back-end schema 20 */ 21 GlobalConfig::$CONNECTION_SETTING = new ConnectionSetting(); 22 GlobalConfig::$CONNECTION_SETTING->ConnectionString = ""; 23 GlobalConfig::$CONNECTION_SETTING->DBName = ""; 24 GlobalConfig::$CONNECTION_SETTING->Username = ""; 25 GlobalConfig::$CONNECTION_SETTING->Password = ""; 26 27 /** the root url of the application with trailing slash, for example http://localhost/adserv/ */ 28 GlobalConfig::$ROOT_URL = RequestUtil::GetServerRootUrl() . 'phreeze/builder/'; 29 30 /** timezone */ 31 // date_default_timezone_set("UTC"); 32 33 /** functions for php 5.2 compatibility */ 34 if (!function_exists('lcfirst')) { 35 function lcfirst($string) { 36 return substr_replace($string, strtolower(substr($string, 0, 1)), 0, 1); 37 } 38 } 39 40 /** level 2 cache */ 41 42 /** additional machine-specific settings */ 43 44 ?>
1 <?php 2 3 GlobalConfig::$APP_ROOT=realpath('./'); 4 5 set_include_path( 6 GlobalConfig::$APP_ROOT.'/libs/'.PATH_SEPARATOR. 7 GlobalConfig::$APP_ROOT.'/../libs'.PATH_SEPARATOR. 8 get_include_path() 9 ); 10 11 require_once 'verysimple/Phreeze/SavantRenderEngine.php'; 12 GlobalConfig::$TEMPLATE_ENGINE = 'SmartyRenderEngine'; 13 GlobalConfig::$TEMPLATE_PATH = GlobalConfig::$APP_ROOT . '/templates/'; 14 GlobalConfig::$TEMPLATE_CACHE_PATH = ''; 15 16 17 GlobalConfig::$ROUTE_MAP = array( 18 19 'GET:' => array('route' => 'Default.Home'), 20 'POST:generate' => array('route' => 'Generator.Generate'), 21 'POST:hello' => array('route' => 'Hello.Say') 22 ); 23 24 ?>
1 <?php 2 /** 3 * @package Adserv 4 * 5 * GLOBAL CONFIGURATION 6 * 7 * This file defines a singleton class that is used for dependency injection 8 * into the framework dispatcher. 9 * 10 * For the most part the settings here shouldn't be changed. The static 11 * properties can be changed in either _app_config.php or _machine_config.php 12 * depending on whether the setting is application-wide or machine-specific 13 */ 14 15 /** 16 * GlobalConfig is a singleton containing the global variables. 17 * In general settings should not be changed in this file and should instead 18 * be made in either _app_config.php or _machine_config.php 19 * 20 * For unit testing this object can be swapped out with another object entirely 21 * to allow for mock data, mockput, etc as needed 22 * 23 * @package Adserv 24 * @author ClassBuilder 25 */ 26 class GlobalConfig 27 { 28 /** @var set to true to send debug info to the browser */ 29 public static $DEBUG_MODE = false; 30 31 /** @var default action is the controller.method fired when no route is specified */ 32 public static $DEFAULT_ACTION = "Default.Home"; 33 34 /** @var routemap is an array of patterns and routes */ 35 public static $ROUTE_MAP; 36 37 /** @var specify the template render engine (Smarty, Savant, PHP) */ 38 public static $TEMPLATE_ENGINE = 'SmartyRenderEngine'; 39 40 /** @var template path is the physical location of view template files */ 41 public static $TEMPLATE_PATH; 42 43 /** @var template cache path is the physical location where templates can be cached */ 44 public static $TEMPLATE_CACHE_PATH; 45 46 /** @var app root is the root directory of the application */ 47 public static $APP_ROOT; 48 49 /** @var root url of the application */ 50 public static $ROOT_URL; 51 52 /** @var ConnectionSetting object containign settings for the DB connection **/ 53 public static $CONNECTION_SETTING; 54 55 /** @var ICache (optional) object for level 2 caching (for example memcached) **/ 56 public static $LEVEL_2_CACHE; 57 58 /** @var string if level 2 cache is specified, a temp path for writing files */ 59 public static $LEVEL_2_CACHE_TEMP_PATH; 60 61 /** @var int if level 2 cache is specified, the timeout in seconds*/ 62 public static $LEVEL_2_CACHE_TIMEOUT = 15; 63 64 private static $INSTANCE; 65 private static $IS_INITIALIZED = false; 66 67 private $context; 68 private $router; 69 private $phreezer; 70 private $render_engine; 71 72 /** prevents external construction */ 73 private function __construct(){} 74 75 /** prevents external cloning */ 76 private function __clone() {} 77 78 /** 79 * Initialize the GlobalConfig object 80 */ 81 static function Init() 82 { 83 require_once 'verysimple/Phreeze/Controller.php'; 84 require_once 'verysimple/HTTP/RequestUtil.php'; 85 86 if (!self::$IS_INITIALIZED) 87 { 88 RequestUtil::NormalizeUrlRewrite(); 89 90 Controller::$SmartyViewPrefix = ''; 91 Controller::$DefaultRedirectMode = 'header'; 92 93 self::$IS_INITIALIZED = true; 94 } 95 96 } 97 98 /** 99 * Returns an instance of the GlobalConfig singleton 100 * @return GlobalConfig 101 */ 102 static function GetInstance() 103 { 104 if (!self::$IS_INITIALIZED) self::Init(); 105 106 if (!self::$INSTANCE instanceof self) self::$INSTANCE = new self; 107 108 return self::$INSTANCE; 109 } 110 111 /** 112 * Returns the context, used for storing session information 113 * @return Context 114 */ 115 function GetContext() 116 { 117 if ($this->context == null) 118 { 119 } 120 return $this->context; 121 122 } 123 124 /** 125 * Returns a URL Writer used to parse/generate URLs 126 * @return UrlWriter 127 */ 128 function GetRouter() 129 { 130 if ($this->router == null) 131 { 132 require_once("verysimple/Phreeze/GenericRouter.php"); 133 $this->router = new GenericRouter(self::$ROOT_URL,self::GetDefaultAction(),self::$ROUTE_MAP); 134 } 135 return $this->router; 136 } 137 138 139 /** 140 * Returns the requested action requested by the user 141 * @return string 142 */ 143 function GetAction() 144 { 145 list($controller,$method) = $this->GetRouter()->GetRoute(); 146 return $controller.'.'.$method; 147 } 148 149 /** 150 * Returns the default action if none is specified by the user 151 * @return string 152 */ 153 function GetDefaultAction() 154 { 155 return self::$DEFAULT_ACTION; 156 } 157 158 /** 159 * Returns the Phreezer persistance layer 160 * @return Phreezer 161 */ 162 function GetPhreezer() 163 { 164 if ($this->phreezer == null) 165 { 166 if (self::$DEBUG_MODE) 167 { 168 require_once("verysimple/Phreeze/ObserveToSmarty.php"); 169 $observer = new ObserveToSmarty($this->GetRenderEngine()); 170 $this->phreezer = new Phreezer(self::$CONNECTION_SETTING, $observer); 171 } 172 else 173 { 174 $this->phreezer = new Phreezer(self::$CONNECTION_SETTING); 175 } 176 177 if (self::$LEVEL_2_CACHE) 178 { 179 $this->phreezer->SetLevel2CacheProvider( self::$LEVEL_2_CACHE, SELF::LEVEL_2_CACHE_TEMP_PATH ); 180 $this->phreezer->ValueCacheTimeout = self::$LEVEL_2_CACHE_TIMEOUT; 181 } 182 } 183 184 return $this->phreezer; 185 } 186 187 /** 188 * @return IRenderEngine 189 */ 190 function GetRenderEngine() 191 { 192 if ($this->render_engine == null) 193 { 194 $engine_class = self::$TEMPLATE_ENGINE; 195 if (!class_exists($engine_class)) 196 { 197 require_once 'verysimple/Phreeze/'. $engine_class . '.php'; 198 } 199 $this->render_engine = new $engine_class(self::$TEMPLATE_PATH,self::$TEMPLATE_CACHE_PATH); 200 $this->render_engine->assign("ROOT_URL",self::$ROOT_URL); 201 $this->render_engine->assign("PHREEZE_VERSION",Phreezer::$Version); 202 $this->render_engine->assign("PHREEZE_PHAR",Phreezer::PharPath()); 203 } 204 205 return $this->render_engine; 206 } 207 208 } 209 210 ?>
这是三个文件,里面的内容可以根据自己的修改
1 <?php 2 /** @package Phreeze Builder */ 3 4 /* GlobalConfig object contains all configuration information for the app */ 5 include_once("_global_config.php"); 6 include_once("_app_config.php"); 7 include_once("_machine_config.php"); 8 9 /* require framework libs */ 10 require_once("verysimple/Phreeze/Dispatcher.php"); 11 12 // the global config is used for all dependency injection 13 $gc = GlobalConfig::GetInstance(); 14 15 try 16 { 17 Dispatcher::Dispatch( 18 $gc->GetPhreezer(), 19 $gc->GetRenderEngine(), 20 '', 21 $gc->GetContext(), 22 $gc->GetRouter() 23 ); 24 } 25 catch (exception $ex) 26 { 27 $gc->GetRenderEngine()->assign("message",$ex->getMessage()); 28 $gc->GetRenderEngine()->assign("stacktrace",$ex->getTraceAsString()); 29 $gc->GetRenderEngine()->assign("code",$ex->getCode()); 30 31 try 32 { 33 $gc->GetRenderEngine()->display("DefaultErrorFatal.tpl"); 34 } 35 catch (Exception $ex2) 36 { 37 // this means there is an error with the template, in which case we can't display it nicely 38 echo "<style>* { font-family: verdana, arial, helvetica, sans-serif; }</style>\n"; 39 echo "<h1>Fatal Error:</h1>\n"; 40 echo '<h3>' . htmlentities($ex->getMessage()) . "</h3>\n"; 41 echo "<h4>Original Stack Trace:</h4>\n"; 42 echo '<textarea wrap="off" style="height: 200px; width: 100%;">' . htmlentities($ex->getTraceAsString()) . '</textarea>'; 43 echo "<h4>In addition to the above error, the default error template could not be displayed:</h4>\n"; 44 echo '<textarea wrap="off" style="height: 200px; width: 100%;">' . htmlentities($ex2->getMessage()) . "\n\n" . htmlentities($ex2->getTraceAsString()) . '</textarea>'; 45 } 46 47 } 48 49 ?>
这是我的入口文件。
注意:
1.他的Controller文件,存放在libs/Controller下面,其文件的命名格式和zend framework一样,其实在他的verysimple/phreeze/Dispatcher.php文件里面的Dispatch方法中我们可以看到,当libs和libs/Controller下面找不到控制器的时候,他会去整个路径下面找,
1 static function Dispatch($phreezer,$renderEngine,$action='',$context=null,$router=null) 2 { 3 if ($router == null) 4 { 5 require_once('GenericRouter.php'); 6 $router = new GenericRouter(); 7 } 8 9 list($controller_param,$method_param) = $router->GetRoute( $action ); 10 11 // normalize the input 12 $controller_class = $controller_param."Controller"; 13 $controller_file = "Controller/" . $controller_param . "Controller.php"; 14 15 // look for the file in the expected places, hault if not found 16 if ( !(file_exists($controller_file) || file_exists("libs/".$controller_file)) ) 17 { 18 // go to plan be, search the include path for the controller 19 $paths = explode(PATH_SEPARATOR,get_include_path()); 20 $found = false; 21 foreach ($paths as $path) 22 { 23 if (file_exists($path ."/".$controller_file)) 24 { 25 $found = true; 26 break; 27 } 28 } 29 30 if (!$found) throw new Exception("File ~/libs/".$controller_file." was not found in include path"); 31 } 32 33 // convert any php errors into an exception 34 if (self::$IGNORE_DEPRECATED) 35 { 36 ExceptionThrower::Start(); 37 } 38 else 39 { 40 ExceptionThrower::Start(E_ALL); 41 ExceptionThrower::$IGNORE_DEPRECATED = false; 42 } 43 44 // we should be fairly certain the file exists at this point 45 include_once($controller_file); 46 47 // we found the file but the expected class doesn't appear to be defined 48 if (!class_exists($controller_class)) 49 { 50 throw new Exception("Controller file was found, but class '".$controller_class."' is not defined"); 51 } 52 53 54 // create an instance of the controller class 55 $controller = new $controller_class($phreezer,$renderEngine,$context,$router); 56 57 // we have a valid instance, just verify there is a matching method 58 if (!is_callable(array($controller, $method_param))) 59 { 60 throw new Exception("'".$controller_class.".".$method_param."' is not a valid action"); 61 } 62 63 // do not call the requested method/route if the controller request has been cancelled 64 if (!$controller->IsTerminated()) 65 { 66 // file, class and method all are ok, go ahead and call it 67 call_user_func(array(&$controller, $method_param)); 68 } 69 70 // reset error handling back to whatever it was 71 //restore_exception_handler(); 72 ExceptionThrower::Stop(); 73 74 return true; 75 }
2.它的模板的命名为你的指定名称,或者是你的控制器名称+方法名称.tpl
3.在zendFramework 里面我们的方法名称是小写的驼峰标记,这个phreeze里面是大写的驼峰标记
4.他的文件上传在Http/RequestUrl.php/getFileUpload ,返回对象为FileUpload对象,
5,目前我就知道有两个渲染引擎SmartyRenderEngine.php,SavantRenderEngine.php,这个配置项在_global_config.php里面,
public static $TEMPLATE_ENGINE = 'SmartyRenderEngine';
6。我们项目99%会合数据库打交道,_machine_config.php,里面就配置了连接数据库的选项,
1 /** database connection settings */ 2 GlobalConfig::$CONNECTION_SETTING = new ConnectionSetting(); 3 GlobalConfig::$CONNECTION_SETTING->ConnectionString = "localhost:3306"; 4 GlobalConfig::$CONNECTION_SETTING->DBName = "test"; 5 GlobalConfig::$CONNECTION_SETTING->Username = "root"; 6 GlobalConfig::$CONNECTION_SETTING->Password = "root"; 7 GlobalConfig::$CONNECTION_SETTING->Type = "MySQL"; 8 GlobalConfig::$CONNECTION_SETTING->Charset = "utf8";
7.当我们的controller,需要model时,他的Controller名称就是model名称,并且他的每一个model,都会在Model/DAO里面有个一样名字+DAO的文件
class test extends testDAO{.......}
8.我们再写zendframework的时候每一个控制器都会继承它自身d的Controller.php,我以前再用zf的时候就经常自己在另外写一个文件继承Controller文件,然后所有的Controller继承我自己写的文件,这种好处在Phreeze里面也得到了体现,因为Phreeze的Controller是抽象类,它里面有init这个抽象方法,如果我们让我们的每一个Controller都去继承它自身的,我们也有可能在每个controller里面都用到好几个相同的方法,这样就会浪费我们的时间,这是我为什么在zf里面自己写一个controller的原因(自己的思路,不代表官方)
9,我们的index.php是如何指向类和方法的呢,这是在我们de _global_config.php里面设置的public static $DEFAULT_ACTION = "Default.Home";_app_config.php里面的
'GET:' => array('route' => 'Default.Home'),也要修改,_global_config文件的貌似无效果,但是之修改_app_config.php的那个有效果
10,在_app_config.php里面我们可以设置:
1 GlobalConfig::$ROUTE_MAP = array( 2 3 'GET:' => array('route' => 'Default.Home'), 4 'POST:generate' => array('route' => 'Generator.Generate'), 5 'POST:hello' => array('route' => 'Hello.Say') 6 );
这个设置的好处是,我们只需要填写很简单的内容他就可以找到我们想要的位置,而且当作为参数的时候,我们可以按照下面这个这么写:
1 GlobalConfig::$ROUTE_MAP = array( 2 3 'GET:api/sales/customer/(:num)' => array( 4 'route' => 'Customer.View', 5 'params' => array('customerId' => 3) 6 ) 7 8 );
http://localhost/api/sales/customer/25 would be split into 4 parts: 0= api 1= sales 2= customer 3=25
13,他的DB函数verySimple/DB/reflection/文件夹下面有很多的函数,
1 function Connect() 2 { 3 $this->handler->Log(DBH_LOG_INFO, "Opening Connection..."); 4 if ($this->dbopen) 5 { 6 $this->handler->Log(DBH_LOG_WARNING, "Connection Already Open"); 7 } 8 else 9 { 10 if ( !$this->dbconn = mysql_connect($this->Host . ":" . $this->Port, $this->Username, $this->Password) ) 11 { 12 $this->handler->Crash(DatabaseException::$CONNECTION_ERROR,"Error connecting to database: " . mysql_error()); 13 } 14 15 if (!mysql_select_db($this->DBName, $this->dbconn)) 16 { 17 $this->handler->Crash(DatabaseException::$CONNECTION_ERROR,"Unable to select database " . $this->DBName); 18 } 19 20 $this->handler->Log(DBH_LOG_INFO, "Connection Open"); 21 $this->dbopen = true; 22 } 23 }
verysimple/DB/DataDriver/MYSQL.php里面,看着段代码大家应该很容易理解query和execute的区别:
1 function Query($connection,$sql) 2 { 3 if ( !$rs = @mysql_query($sql, $connection) ) 4 { 5 throw new DatabaseException(mysql_error(),DatabaseException::$ERROR_IN_QUERY); 6 } 7 8 return $rs; 9 } 10 11 /** 12 * @inheritdocs 13 */ 14 function Execute($connection,$sql) 15 { 16 if ( !$result = @mysql_query($sql, $connection) ) 17 { 18 throw new DatabaseException(mysql_error(),DatabaseException::$ERROR_IN_QUERY); 19 } 20 21 return mysql_affected_rows($connection); 22 }
对于这个文件里面我现在有个地方不能理解:
1 function Fetch($connection,$rs) 2 { 3 return mysql_fetch_assoc($rs); 4 }
他的方法的参数里面,根本不用$connection ,可是它写了
12,它可以渲染很多格式的代码,这个貌似不错,可是没用呢还
还有很多函数,建议大家看代码的时候直接看源码,那么着用起来比较方便,理解的也比较快,
DB应用:
第一种方法: $obj=new DataDriverMySQL(); $sql='select * from ptest where id=20'; $connection=$obj->Open('localhost:3306','PhreezeTest','root','root','utf8'); $rs=$obj->Query($connection,$sql); $arrName2=$obj->Fetch($connection,$rs); echo '<pre>'; print_r($arrName2); echo '</pre>'; 结果: Array ( [id] => 20 [name] => G [time] => 2013-02-21 15:19:48 ) 第二种方法: $cstring = $this->GetConnectionString(); $handler = new DBEventHandler(); $connection = new DBConnection($cstring, $handler); $server = new DBServer($connection); $sql='select * from ptest where id=25'; $rs=$connection->Select($sql); $arrName=$connection->Next($rs); echo '<pre>'; print_r($arrName); echo '</pre>'; Array ( [id] => 25 [name] => Zc [time] => 2013-02-21 15:19:48 ) 说明:数据是我批量插入的,你可能会说时间为什么一样,我想说时间差太小,
ps:我目前还没有找到他和zf一样的fetchAll功能的方法;
我不能肯定这里面没有错误,这也仅仅是我刚开始所了解到的表面层次的东西,如果您正好了解这个Phreeze框架,那么请您批评指教,谢谢!