Sina App Engine(SAE)教程(11)- Yaf使用
Yaf参考资料
想在SAE使用Yaf?
无需申请,sae环境已经全面支持。
Yaf 实战
下面是一个运行在SAE的Yaf的hello world程序。
config.yaml
---
name: lazydemo
version: 3
...
handle:
- rewrite: if(!is_dir() && !is_file() && path ~ "^(.*)$" ) goto "/index.php"
以上文件配置了Rewrite规则,把所有这个应用的请求, 都定向到上面提到的入口文件。
index.php
<?php
define("APP_PATH", dirname(__FILE__));
$app = new Yaf_Application(APP_PATH . "/conf/application.ini");
$app->run();
/conf/application.ini
[product] application.directory=APP_PATH "/application/" 控制器文件:Index.php
<?php
class IndexController extends Yaf_Controller_Abstract {
public function indexAction() {//默认Action
$this->getView()->assign("content", "Hello World");
}
}
?>
视图文件 index.phtml
<html> <head> <title>Hello World</title> </head> <body> <?php echo $content;?> </body> </html>
文件目录请直接下载demo文件包查看,也可以点击http://yaf.laruence.com/manual/tutorial.firstpage.html 目录结构查看。效果见:http://3.lazydemo.sinaapp.com/demo 文件打包下载:
http://3.lazydemo.sinaapp.com/SAE_Yaf_helloworld_demo.zip
深化认识
天天都是helloworld自然不行,下面就进一步的深化。我们就先从数据库的连接开始,首先修改下/conf/application.ini的设置加上sae数据库的相关配置。文件如下:
[base] database.master.host = 3.lazydemo.sinaapp.com [product] ;支持直接写PHP中的已定义常量 application.directory=APP_PATH "/application/" ;应用的配置 webhost = 3.lazydemo.sinaapp.com database.adapter = pdo_mysql ;主库 database.params.host.m = SAE_MYSQL_HOST_M ;从库 database.params.host.s = SAE_MYSQL_HOST_S database.params.port = SAE_MYSQL_PORT database.params.username = SAE_MYSQL_USER database.params.password = SAE_MYSQL_PASS database.params.dbname = SAE_MYSQL_DB
那我们怎么在程序中读出这个配置呢?这时候就需要用到yaf的Yaf_Config_Ini(参考文档)
我们可以做个实现,我们在默认的控制器中通过Yaf_Config_Ini来读取刚刚配置的数据库连接信息,控制器Index.php的代码改成如下:
<?php
class IndexController extends Yaf_Controller_Abstract {
public function indexAction() {//默认Action
//test get db connection info
//获取当前web目录的绝对路径
$br = '<br/>';
$basedir = $_SERVER[ 'DOCUMENT_ROOT'];
$conf_dir = $basedir.'/conf/application.ini';
$config = new Yaf_Config_Ini($conf_dir,'product');
echo $config->database->get("params")->host->m.$br;
echo $config->database->get("params")->host->s.$br;
echo $config->get("database")->params->dbname.$br;
$this->getView()->assign("content", "Hello World");
}
}
?>
此时访问http://3.lazydemo.sinaapp.com/ (ps可能你点击看不到了,因为我改成了其他的代码,你可以自己复制上面的代码实验)
w.rdc.sae.sina.com.cn r.rdc.sae.sina.com.cn app_lazydemo Hello World
成功了!那么其他的一些配置文件都可以参考以上的方法实现。截止到以上操作的代码文件打包下载:http://3.lazydemo.sinaapp.com/SAE_Yaf_demo_step2.zip
Yaf的一大亮点:Yaf_Registry
Yaf_Registry, 对象注册表(或称对象仓库)是一个用于在整个应用空间(application space)内存储对象和值的容器. 通过把对象存储在其中,我们可以在整个项目的任何地方使用同一个对象.这种机制相当于一种全局存储. 我们可以通过Yaf_Registry类的静态方法来使用对象注册表. 另外,由于该类是一个数组对象,你可以使用数组形式来访问其中的类方法.
这就好比为我们实现了一个类似SAE的kv存取,但是这个存取会随着访问的结束而释放,不需要手工清空。下面我们也通过一个简单的例子来说明这几个函数:
为了测试我们改写Index.php代码如下:
<?php
class IndexController extends Yaf_Controller_Abstract {
public function indexAction() {//默认Action
//我们在这里注册,不放直接注册一个数组试试
$value = array('name'=>'lazy','age'=>'21');
$re = Yaf_Registry::set('config',$value);
var_dump($re);
$config = Yaf_Registry::get("config");
var_dump($config);
$this->getView()->assign("content", "This is index page");
}
}
?>
访问可以得到结果,
bool(true) array(2) { ["name"]=> string(4) "lazy" ["age"]=> string(2) "21" } This is index page
这个例子的demo源代码下载地址 http://3.lazydemo.sinaapp.com/SAE_Yaf_demo_step3.zip
关闭自动渲染,display函数实例
可能在有些时候,我们确实不想把页面的内容都刷到一固定的view中,例如你的控制器叫Test.php,那你的indexAction默认的自动渲染就是到views/test/index.phtml 文件里了,display函数可以允许我们改变渲染的视图文件,例如在Test控制器中,我们想把后端的数据刷到lazy.phtml中,我们可以将Test.php改写成:
<?php
class TestController extends Yaf_Controller_Abstract {
public function init(){
/* 首先关闭自动渲染 */
Yaf_Dispatcher::getInstance()->disableView();
}
public function indexAction() {
$this->initView();
$this->display("lazy", array("content" => "this comes from test controller index action"));
//注意第一个参数直接写lazy就行,写成lazy.phtml会出错
}
}
?>
在views/test/下新建文件 lazy.phtml,文件的内容是
<html> <head> <title>Hello World</title> </head> <body> <?php echo $content;?> </body> </html>
访问http://3.lazydemo.sinaapp.com/test就可以看到输出是:
this comes from test controller index action
本实例源代码下载地址:http://3.lazydemo.sinaapp.com/SAE_Yaf_demo_step4.zip
添加前端和数据库操作类
下面开始将对yaf做一些深度的添加树叶让他更好的在SAE上能给开发者快速的开发。首先我想添加一个类似于 Lazyphp那样的专门对SAE的数据库的封装函数,将其一样的在yaf中实现,类似的函数有get_line,get_var,run_sql等等,可以参考http://ftqq.com/lazyphp/ 下面的关于数据库的列表。
那么要实现这些个功能,我们就必须要借用Yaf提供的bootstrap对其完成初始化了。
我们首先在application下创建一个functions的文件夹,写入db.sae.function.php 文件,文件的内容是:
<?php
function db_read( $host = null , $port = null , $user = null , $password = null , $db_name = null )
{
$db_key = MD5( 'read-' . $host .'-'. $port .'-'. $user .'-'. $password .'-'. $db_name );
if( !isset( $GLOBALS['LP_'.$db_key] ) )
{
$basedir = $_SERVER[ 'DOCUMENT_ROOT'];
$conf_dir = $basedir.'/conf/application.ini';
$config = new Yaf_Config_Ini($conf_dir,'product');
if( $host == null ) $host = $config->database->get("params")->host->s;
if( $port == null ) $port = $config->database->get("params")->port;
if( $user == null ) $user = $config->database->get("params")->username;
if( $password == null ) $password = $config->database->get("params")->password;
if( $db_name == null ) $db_name = $config->database->get("params")->dbname;
if( !$GLOBALS['LP_'.$db_key] = mysql_connect( $host.':'.$port , $user , $password , true ) )
{
//
echo 'can\'t connect to database';
return false;
}
else
{
if( $db_name != '' )
{
if( !mysql_select_db( $db_name , $GLOBALS['LP_'.$db_key] ) )
{
echo 'can\'t select database ' . $db_name ;
return false;
}
}
}
mysql_query( "SET NAMES 'UTF8'" , $GLOBALS['LP_'.$db_key] );
}
return $GLOBALS['LP_'.$db_key];
}
// db functions
function db( $host = null , $port = null , $user = null , $password = null , $db_name = null )
{
$db_key = MD5( $host .'-'. $port .'-'. $user .'-'. $password .'-'. $db_name );
if( !isset( $GLOBALS['LP_'.$db_key] ) )
{
$basedir = $_SERVER[ 'DOCUMENT_ROOT'];
$conf_dir = $basedir.'/conf/application.ini';
$config = new Yaf_Config_Ini($conf_dir,'product');
if( $host == null ) $host = $config->database->get("params")->host->m;
if( $port == null ) $port = $config->database->get("params")->port;
if( $user == null ) $user = $config->database->get("params")->username;
if( $password == null ) $password = $config->database->get("params")->password;
if( $db_name == null ) $db_name = $config->database->get("params")->dbname;
if( !$GLOBALS['LP_'.$db_key] = mysql_connect( $host.':'.$port , $user , $password , true ) )
{
//
echo 'can\'t connect to database';
return false;
}
else
{
if( $db_name != '' )
{
if( !mysql_select_db( $db_name , $GLOBALS['LP_'.$db_key] ) )
{
echo 'can\'t select database ' . $db_name ;
return false;
}
}
}
mysql_query( "SET NAMES 'UTF8'" , $GLOBALS['LP_'.$db_key] );
}
return $GLOBALS['LP_'.$db_key];
}
function s( $str , $db = NULL )
{
if( $db == NULL ) $db = db();
return mysql_real_escape_string( $str , $db ) ;
}
// $sql = "SELECT * FROM `user` WHERE `name` = ?s AND `id` = ?i LIMIT 1 "
function prepare( $sql , $array )
{
foreach( $array as $k=>$v )
$array[$k] = s($v );
$reg = '/\?([is])/i';
$sql = preg_replace_callback( $reg , 'prepair_string' , $sql );
$count = count( $array );
for( $i = 0 ; $i < $count; $i++ )
{
$str[] = '$array[' .$i . ']';
}
$statement = '$sql = sprintf( $sql , ' . join( ',' , $str ) . ' );';
eval( $statement );
return $sql;
}
function prepair_string( $matches )
{
if( $matches[1] == 's' ) return "'%s'";
if( $matches[1] == 'i' ) return "'%d'";
}
function get_data( $sql , $db = NULL )
{
if( $db == NULL ) $db = db_read();
$GLOBALS['LP_LAST_SQL'] = $sql;
$data = Array();
$i = 0;
$result = mysql_query( $sql ,$db );
if( mysql_errno() != 0 )
echo mysql_error() .' ' . $sql;
while( $Array = mysql_fetch_array($result, MYSQL_ASSOC ) )
{
$data[$i++] = $Array;
}
if( mysql_errno() != 0 )
echo mysql_error() .' ' . $sql;
mysql_free_result($result);
if( count( $data ) > 0 )
return $data;
else
return false;
}
function get_line( $sql , $db = NULL )
{
$data = get_data( $sql , $db );
return @reset($data);
}
function get_var( $sql , $db = NULL )
{
$data = get_line( $sql , $db );
return $data[ @reset(@array_keys( $data )) ];
}
function last_id( $db = NULL )
{
if( $db == NULL ) $db = db();
return get_var( "SELECT LAST_INSERT_ID() " , $db );
}
function run_sql( $sql , $db = NULL )
{
if( $db == NULL ) $db = db();
$GLOBALS['LP_LAST_SQL'] = $sql;
return mysql_query( $sql , $db );
}
function db_errno( $db = NULL )
{
if( $db == NULL ) $db = db();
return mysql_errno( $db );
}
function db_error( $db = NULL )
{
if( $db == NULL ) $db = db();
return mysql_error( $db );
}
function last_error()
{
if( isset( $GLOBALS['LP_DB_LAST_ERROR'] ) )
return $GLOBALS['LP_DB_LAST_ERROR'];
}
function close_db( $db = NULL )
{
if( $db == NULL )
$db = $GLOBALS['LP_DB'];
unset( $GLOBALS['LP_DB'] );
mysql_close( $db );
}
?>
这个文件基本和lazyphp中的一样,但是数据库的配置信息那里我做了一点修改,不再是require得到,而是采用
$basedir = $_SERVER[ 'DOCUMENT_ROOT'];
$conf_dir = $basedir.'/conf/application.ini';
$config = new Yaf_Config_Ini($conf_dir,'product');
if( $host == null ) $host = $config->database->get("params")->host->m;
if( $port == null ) $port = $config->database->get("params")->port;
if( $user == null ) $user = $config->database->get("params")->username;
if( $password == null ) $password = $config->database->get("params")->password;
if( $db_name == null ) $db_name = $config->database->get("params")->dbname;
读取/conf/application.ini的配置文件得到,这个用户在上面已经介绍了。不再赘述,在实现后我们就需要在bootstrap中初始化引用这些函数,注意,Bootstrap.php的文件必须在application的根目录下。看我写的Bootstrap.php代码:
<?php
/**
* 所有在Bootstrap类中, 以_init开头的方法, 都会被Yaf调用,
* 这些方法, 都接受一个参数:Yaf_Dispatcher $dispatcher
* 调用的次序, 和申明的次序相同
*/
class Bootstrap extends Yaf_Bootstrap_Abstract{
public function _initdbfunction() {
$basedir = $_SERVER[ 'DOCUMENT_ROOT'];
$dbfunction = $basedir.'/application/functions/db.sae.function.php';
Yaf_Loader::import($dbfunction);
}
}
此时修改index.php为:
<?php
define("APP_PATH", dirname(__FILE__));
$app = new Yaf_Application(APP_PATH . "/conf/application.ini");
$app
->bootstrap()
->run();
这时就大功告成了,我们写一个测试的例子来测试下:我们修改下控制器Test.php代码
<?php
class TestController extends Yaf_Controller_Abstract {
public function init(){
/* 首先关闭自动渲染 */
Yaf_Dispatcher::getInstance()->disableView();
}
public function indexAction() {
//test db function
$sql = "select * from mysqldemo where id=1";
$result = get_line($sql);
var_dump($result);
$this->initView();
$this->display("lazy", array("content" => "this comes from test controller index action"));
//注意第一个参数直接写lazy就行,写成lazy.phtml会出错
}
}
?>
注意我们已经使用了get_line()函数哦,访问http://3.lazydemo.sinaapp.com/test 看到输出
array(3) { ["id"]=> string(1) "1" ["content"]=> string(12) "This num is1" ["timeline"]=> string(19) "2012-10-23 13:55:21" } this comes from test controller index action
嘿嘿,说明我们已经成功的添加了SAE 数据库的操作函数。另外这次修改中我还加上了开源的前端模版bootstrap。
实例站点demo
http://3.lazydemo.sinaapp.com/
效果图:

代码代码下载:
http://3.lazydemo.sinaapp.com/SAE_Yaf_demo.zip
Sina App Engine(SAE)教程(11)- Yaf使用的更多相关文章
- Sina App Engine(SAE)入门教程(2)-Mysql使用
如果你还没有SAE的账号,请在http://sae.sina.com.cn 注册新用户.具体的注册流程请参见:Sina App Engine(SAE)入门教程(1)在常规的环境下,我们可以通过http ...
- Python Flask 在Sina App Engine (SAE)上安家
早就听说了Python的大名,随着的编程语言的理解加深,越发认为动态语言的威力--真大呀. 趁这段时间不忙,我也用Python写了一个应用,而且将其部署到Sina App Engine (SAE).S ...
- Sina App Engine(SAE)入门教程(8)- SaeFetchurl使用
fetchurl是什么? FetchURL是SAE为开发者提供的分布式网页抓取服务,用来同步的抓取http页面,FetchURL针对国内的网络的做了优化,内部有调度系统,尽可能保证用户快速的抓取到目标 ...
- Sina App Engine(SAE)入门教程(1)
此教程只针对刚接触SAE的小白用户,资深码农.高手请绕道.首先还是一个经典的实例,hello sae. 创建应用 在注册完账号之后,需要到 http://sae.sina.com.cn/?m=myap ...
- Sina App Engine(SAE)入门教程(4)- SaeVCode(验证码服务)使用
参考资料 SaeVCode api 文档 使用教程 所有的验证码原理都是生成一个vcode字符串,存到session中,和用户的输入进行比较判断,以下是一个使用验证码服务的完整实例: 首页index. ...
- Sina App Engine(SAE)入门教程(3)-KVDB使用
简介 因为传统关系型数据库在分布式环境下表现的扩展性不足等缺点,近年来NoSQL的概念渐渐成为业界关注的焦点,越来越多的技术人员也习惯于使用NoSQL数据库进行日常开发,SAE为了应对这种新需求,也进 ...
- Sina App Engine(SAE)入门教程(7)- Storage使用
参考阅读 sae storage api 文档 Storage 说明文档 Storage 大文件上传说明 storage是什么? 因为sae禁用了代码环境的本地读写,但是在网站运行的过程中,必定会出现 ...
- Sina App Engine(SAE)入门教程(6)- memcache使用
Memcache是一个高性能的分布式的内存对象缓存系统,通过在内存里维护一个统一的巨大的hash表,它能够用来存储各种格式的数据,包括图像.视频.文件以及数据库检索的结果等.简单的说就是将数据调用到内 ...
- Sina App Engine(SAE)入门教程(10)- Cron(定时任务)使用
参考资料 SAE Cron说明文档 Cron能干什么? cron 可以定时的触发一个脚本,在sae上最大的频率是一分钟一次.你可以用其来完成自己需要的业务逻辑,例如定期的抓取某些网页完菜信息的采集,定 ...
随机推荐
- 安装gitolite,并ssh公钥无密码登录
安装gitolite,并ssh公钥无密码登录 gitolite是管理git版本库的一种方案,它将git版本库的管理信息放在了一个特殊git版本库里.gitolite与linux操作系统集成了,需要使用 ...
- 如何查看 Apache 的版本
查看 Apache 服务器版本的命令行为: httpd -v 或者 apachectl -v 例如:用 Xshell 连接到服务器后,输入:httpd -v 或者:apachectl -v 返回: S ...
- centos问题集锦
一. 为什么新装的centos系统无法使用xshell,putty等工具连接? 原因:sshd服务没有启动. 解决: 1)使用命令rpm -qa | grep ssh查看是否已经安装了ssh 2)使用 ...
- 使用Telerik的登陆模板实现DoubanFm的登陆(WP7)
Telerik的控件很强大.我们直接使用其登陆模板. 在装过Telerik WP版后,就可以在VS里非常方便的添加页面了. 我们选择 Sign In Form 其XAML不是很长,直接贴出来 < ...
- C#实现发送邮件——核心部分代码
在KS系统中有个发送邮件的功能需要做上网查阅资料以后,通过自己的部分修改实现了发送邮件的功能话不多说先来个界面: 邮件发送分一下步骤: 1.smtp服务信息设置 2.验证发件人信息 3.添加附件 4. ...
- 通过替换frm文件方式修改表结构
版本:5.6.16 在自己的虚拟环境中,测试创建一个表,表结构如下:mysql> drop table yoon_temp;Query OK, 0 rows affected (0.09 sec ...
- mysql数据库本地化操作
<?php if(!defined('SITE_PATH')){ define('SITE_PATH',dirname(dirname(__FILE__))); } $dbconfig=incl ...
- 20145120黄玄曦 《java程序设计》 寒假学习总结
1和2.我对未来规划不多,我认为好好学习积累知识能帮助我应对未来的挑战,这是我的学习动力之一,此外,了解新知识满足好奇心也是我的主要的学习动力. 3.我认为专业课学习比公务员考试重要,我认为专业知识是 ...
- 特征值分解,奇异值分解(SVD)
特征值分解和奇异值分解在机器学习领域都是属于满地可见的方法.两者有着很紧密的关系,我在接下来会谈到,特征值分解和奇异值分解的目的都是一样,就是提取出一个矩阵最重要的特征. 1. 特征值: 如果说一个向 ...
- Java 8 VM GC Tuning Guide Charter3-4
第三章 Generations One strength of the Java SE platform is that it shields the developer from the compl ...