本文实例讲述了laravel 5.1 on sae环境开发方法。分享给大家供大家参考,具体如下:
laravel-简洁、优雅的php开发框架,为 web 艺术家创造的 php 框架,如今正式移植到sae环境。
由于laravel 5.1相比于laravel 4有很多的改动,不仅以目录结构更加清晰,而且功能也更丰富。但是laravel官方还是没有原生支持sae环境(估计永远不会支持),所以我就做了一个移植版本,可以很优雅的切换本地和sae环境。
由于sae的特殊性,那么这几个核心问题就必须要解决
#1 putenv()函数禁用
#2 模板编译
#3 缓存类
#4 日志处理
#5 session类
#6 服务提供者缓存
#1 putenv()函数禁用
laravel 5.1使用了这个putenv()函数来向当前的环境中动态添加变量,但是很遗憾的是sae的phpruntime禁用了该函数,所以只能使用折中的方法来实现。当初本来想hook掉该实现,后来觉得没必要,这个函数在laravel 5.1中主要是为了使用.env配置文件来统一团队的配置。所以我是直接禁用了该功能,在vendor/vlucas/phpdotenv/src/dotenv.php的86行左右,直接注释掉该函数,然后把所有的配置信息都写到config文件夹的相应配置文件中。虽然解决了该函数被禁用的问题,但是实现的不够优雅,希望有大神可以给出更加优雅的实现。
#2 模板编译
该问题主要还是因为sae的本地环境写入被禁止,所以我使用了wrapper来把编译后的模板文件写入到storage。本来是打算写到kvdb中,但是会出现一些奇奇怪怪问题,原因不明。
在configview.php文件中修改:
$compiled = [
'paths' => [
realpath(base_path('resources/views')),
],
'compiled' => realpath(storage_path('framework/views')),
];
if(sae){
$compiled['compiled'] = 'saestor://'.sae_storage.'/compiled';
}
return $compiled;
注意要在相应的storage中建立compiled文件夹。
#3 缓存类
laravel 5.1没有直接提供sae可用的memcache缓存驱动,这个解决比较简单,直接写一个服务提供者注册到app.php即可,然后在configcache.php中注册,具体实现看项目源码
#4 日志处理
这也是一个比较棘手的问题,由于laravel 5.1的日志处理已经不是和4一样使用服务提供者,而且直接注入到启动器中,这就使得我们只能覆写原生configurelogging启动类,而官方也没有给出如何覆写和在哪里覆写,所以我这边的解决方案是判断当前环境为sae后直接重写http内核中的一个启动器属性,核心代码:
namespace illuminatecloudsae;
use apphttpkernel as defaultkernel;
class kernel extends defaultkernel{
/**
* the bootstrap classes for the application.
*
* @var array
*/
protected $bootstrappers = [
'illuminatefoundationbootstrapdetectenvironment',
'illuminatefoundationbootstraploadconfiguration',
'illuminatecloudsaelogconfigurelogging',
'illuminatefoundationbootstraphandleexceptions',
'illuminatefoundationbootstrapregisterfacades',
'illuminatefoundationbootstrapregisterproviders',
'illuminatefoundationbootstrapbootproviders',
];
}
这样还不行,还必须重写日志的部分实现
class writer extends illuminatelogwriter {
protected function usesaelog($level = 'debug'){
$level = $this->parselevel($level);
$this->monolog->pushhandler($handler = new saeloghandler($level));
$handler->setformatter($this->getdefaultformatter());
}
public function usefiles($path, $level = 'debug'){
if (sae) {
return $this->usesaelog($level);
}
parent::usefiles($path, $level);
}
public function usedailyfiles($path, $days = 0, $level = 'debug'){
if (sae) {
return $this->usesaelog($level);
}
parent::usedailyfiles($path, $days, $level);
}
}
#5 session类
laravel5.1的session依旧是本地写的问题,参考了laravel4的移植,使用了memcache作为session的实现,具体可以结合缓存部分来处理
#6 服务提供者缓存
在应用程序的启动过程中,laravel会在bootstrap/cache/services.json生成服务提供者的缓存,为了加快下次访问的速度,依旧是本地写的问题,解决方案很简单,使用storage的wrapper即可
以上这些问题解决后,差不多就算成功了。最后修改下bootstrapapp.php来实现本地与sae环境的优雅切换,主要是判断环境然后生成sae专有应用实例和注入相应的http内核。
/*
|--------------------------------------------------------------------------
| create the application
|--------------------------------------------------------------------------
|
| the first thing we will do is create a new laravel application instance
| which serves as the "glue" for all the components of laravel, and is
| the ioc container for the system binding all of the various parts.
|
*/
define('sae',true);
define('sae_storage', 'laravel');
if(sae){
$app = new illuminatecloudsaeapplication(
realpath(__dir__.'/../')
);
$app->singleton(
illuminatecontractshttpkernel::class,
illuminatecloudsaekernel::class
);
}else{
$app = new illuminatefoundationapplication(
realpath(__dir__.'/../')
);
$app->singleton(
illuminatecontractshttpkernel::class,
apphttpkernel::class
);
}
/*
|--------------------------------------------------------------------------
| bind important interfaces
|--------------------------------------------------------------------------
|
| next, we need to bind some important interfaces into the container so
| we will be able to resolve them when needed. the kernels serve the
| incoming requests to this application from both the web and cli.
|
*/
$app->singleton(
illuminatecontractsconsolekernel::class,
appconsolekernel::class
);
$app->singleton(
illuminatecontractsdebugexceptionhandler::class,
appexceptionshandler::class
);
/*
|--------------------------------------------------------------------------
| return the application
|--------------------------------------------------------------------------
|
| this script returns the application instance. the instance is given to
| the calling script so we can separate the building of the instances
| from the actual running of the application and sending responses.
|
*/
return $app;
这里解释下为什么要在bootstrapapp.php中来定义是否为sae环境,原因很明确了,就是要注入相应的应用程序实例和http实例,然后再这里也定义一下storage
然后就是configapp.php的相关配置,根据环境判断来注入相应的服务提供者
if(sae){
$removeproviders = [
illuminatecachecacheserviceprovider::class,
illuminatesessionsessionserviceprovider::class,
];
for($i = 0; $i < count($app['providers']); $i++){
if (in_array($app['providers'][$i], $removeproviders)) {
unset($app['providers'][$i]);
}
}
$app['providers'] = array_merge($app['providers'],[
illuminatecloudsaecachesaecacheserviceprovider::class,
illuminatecloudsaesessionsessionserviceprovider::class,
illuminatecloudsaestoragestorageserviceprovider::class,
illuminatecloudsaesegmentsegmentserviceprovider::class,
]);
$app['aliases']['storage'] = illuminatecloudsaestoragestorage::class;
$app['aliases']['segment'] = illuminatecloudsaesegmentsegment::class;
}
最后再说说sae专有应用程序实例和http实例与原生的差别,主要还是本地写的问题。原生的会在应用程序启动时候生成路由、配置、服务提供者、模板编译的相关文件,以此来提升加载速度。但是到了sae就不行了,所以重写了application类的部分与路径相关的方法,来把这些文件生成到storage中,而http专有内核则是处理启动器中的日志类。具体代码就不贴出来,可以看看项目。
再给一个sae可以使用的rewrite
handle:
- rewrite: if (path ~ "^/$") goto "public/index.php"
- rewrite: if(!is_dir() && !is_file() && path~"^(.*)$") goto "public/index.php/$1"
总结
整个移植过程还算是很顺利,得益于laravel的拓展性与sae的便利.不过在对于putenv()函数和日志处理的解决方法上,还是实现的不够优雅,希望能有人给出更有优雅的实现方案。然后其他的sae服务比如分词、邮件、队列等,则可以使用服务提供者自动加载,这个就不多说了。
项目github地址: https://github.com/wh469012917/laravel5-on-sae
软件点击此处本站下载。
更多关于laravel相关内容感兴趣的读者可查看本站专题:《laravel框架入门与进阶教程》、《php优秀开发框架总结》、《smarty模板入门基础教程》、《php日期与时间用法总结》、《php面向对象程序设计入门教程》、《php字符串(string)用法总结》、《php+mysql数据库操作入门教程》及《php常见数据库操作技巧汇总》
希望本文所述对大家基于laravel框架的php程序设计有所帮助。
【说明】:
本文章由站长整理发布,文章内容不代表本站观点,如文中有侵权行为,请与本站客服联系(QQ:)!