近日学习用kohana框架,写了一个在线查字的小应用。在本地测试良好,效果图
主要实现的是按部首、按拼音查检索文字,搜索汉子查询。
主要业务逻辑很简单。预览地址请点击这里 现在部署在SAE平台上面。一些问题的参考文档来自这里
正常运行
本地测试完成代码,刚刚部署到SAE平台上时会出现这样的错误。
ErrorException [ Warning ]: Set the ini directive 'unserialize_callback_func' without permission
可以看到kohana完善的错误信息提示已经指向了APPPATH/bootstrap.php中得这一行
[code]
ini_set('unserialize_callback_func', 'spl_autoload_call');
[/code]
这个是因为SAE平台禁用了ini_set()函数的原因,已经没有权限执行了。
解决办法就是直接注释,这个注释的影响是
“代码中使用了unserialize(),并且其解析的结果是一个对象,同时这个对象对应的类还没有定义。这种情况下就会导致一个错误。”来自上面那篇参考文章。
第二个错误则是日志、文件cache不能正常写入了。
Kohana_Exception [ 0 ]: Directory APPPATH/logs must be writable
这个是因为SAE平台禁止了程序对本地的文件进行操作,所以也就没有权限了。“唯一可以直接使用并提供了写入权限的是一个虚拟目录SAE_TMP_PATH。但是这个目录会在php脚本执行完后销毁,所以实际上并不能真正起到缓存的作用。”
解决办法 同样注释掉
[code]
Kohana::$log->attach(new Log_File(APPPATH.'logs'));
[/code]
这样则禁用了日志功能了,不过对于一般的程序来说没有太大的影响。
加入SAE的缓存目录常量
[code]
Kohana::init(array(
'base_url' => '/',
'index_file' => 'index.php',
'cache_dir' => SAE_TMP_PATH // 这里
));
[/code]
至此如果你的程序不用缓存,那么配置好SAE平台的数据库连接参数等,程序就能正常访问了。
提示一下:
SAE的数据库参数hostname的常量,这个一定要注意,最好把SAE_MYSQL_PORT这个端口常量加上去,否则出现数据库连接不上的问题,但这个问题不容易被注意到,好吧,我就是好不容易才注意到的。SAE云平台的mysql端口不是默认的3306所以我刚开始时没有加上这个端口常量,想不出问题原因,最后登录sae后天,进入管理mysql数据库才看到,原来sae的mysql端口是3307
于是加上了这个端口常量,果然好了。。
[code]
'hostname' => SAE_MYSQL_HOST_M.':'.SAE_MYSQL_PORT,
'database' => SAE_MYSQL_DB,
'username' => SAE_MYSQL_USER,
'password' => SAE_MYSQL_PASS,
'persistent' => FALSE,
[/code]
因为还有考虑到本地环境运行的问题;所以我再bootstrap.php中加入了SAE常量,值为true或false,true为sae,false为本地
最后bootstrap.ph的代码修改为
[code]
// 添加sae的环境控制,也能让程序在本地正常运行
define('SAE', TRUE);
if( ! SAE){
define('SAE_TMP_PATH', APPPATH.'/cache');
}
/**
* 本地环境,非SAE平台的独立设置
* 注意这一段必须在 spl_autoload_register(array('Kohana', 'auto_load')); 之后
* 否则Kohana类未加载情况下,调用$log会出错
*/
if( ! SAE ){
// SAE不支持ini_set函数的运行
ini_set('unserialize_callback_func', 'spl_autoload_call');
// SAE暂不支持对文件夹进行文件写入,暂时关闭日志
Kohana::$log->attach(new Log_File(APPPATH.'logs'));
define('SAE_MYSQL_HOST_M', 'localhost');
define('SAE_MYSQL_PORT', '3306');
define('SAE_MYSQL_DB', 'xhzd');
define('SAE_MYSQL_USER', 'root');
define('SAE_MYSQL_PASS', 'root');
}
[/code]
使用SAE memcache 缓存
不过我的这个查字程序在部首;拼音列表,以及部首拼音相关的文字这些操作都用了缓存的。所以在sae上文件缓存是用不了了,但是还有memcache缓存啊。
因为SAE平台的memcache缓存启用不是原生的new memcache,而是memcache_init()所以程序还得改下。要改的地方比较简单。大致思路就是重写Kohana_Cache_Memcache的构造函数,重写初始化_memcache
modules\cache\classes\cache\memcache.php
[code]
class Cache_Memcache extends Kohana_Cache_Memcache {
public function __construct(array $config) {
parent::__construct($config);
// SAE平台则初始化sae平台memcache
if( SAE ){
$this->_memcache = memcache_init();
}
}
}
[/code]
不过还是有问题,在SAE平台上会显示 modules\cache\classes\kohana\cache\memcache.php
call undefined function $this->_memcache->addServer() 估计也是被禁掉了。
那也好办注释掉就好了
[code]
/**
* 区别sae平台以及本地环境
*/
if( ! SAE){
// Add the memcache servers to the pool
foreach ($servers as $server)
{
// Merge the defined config with defaults
$server += $this->_default_config;
if ( ! $this->_memcache->addServer($server['host'], $server['port'], $server['persistent'], $server['weight'], $server['timeout'], $server['retry_interval'], $server['status'], $server['failure_callback']))
{
throw new Cache_Exception('Memcache could not connect to host \':host\' using port \':port\'', array(':host' => $server['host'], ':port' => $server['port']));
}
}
}
[/code]
因为kohana默认采用的是文件缓存
所以在调用Cache::instance();前应当Cache::$default = 'memcache';
至此,memcache缓存就能正常的运行了。Kohana框架在SAE平台上的主要修改也完成,不过肯定还有一些不知道的问题,主要是对于SAE平台的不熟悉以及SAE平台处于安全考虑禁用的一些函数、方法等。
最后宣传下个人在sae上的这个应用地址欢迎访问http://xhzd.sinaapp.com/