gpt4 book ai didi

Laravel 5.1 on SAE环境开发教程【附项目demo源码】

转载 作者:qq735679552 更新时间:2022-09-27 22:32:09 25 4
gpt4 key购买 nike

CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.

这篇CFSDN的博客文章Laravel 5.1 on SAE环境开发教程【附项目demo源码】由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.

本文实例讲述了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中,但是会出现一些奇奇怪怪问题,原因不明.

在config\view.php文件中修改

?
1
2
3
4
5
6
7
8
9
10
$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即可,然后在config\cache.php中注册,具体实现看项目源码 。

#4 日志处理 。

这也是一个比较棘手的问题,由于Laravel 5.1的日志处理已经不是和4一样使用服务提供者,而且直接注入到启动器中,这就使得我们只能覆写原生ConfigureLogging启动类,而官方也没有给出如何覆写和在哪里覆写,所以我这边的解决方案是判断当前环境为SAE后直接重写Http内核中的一个启动器属性,核心代码

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
namespace Illuminate\Cloud\SAE;
use App\Http\Kernel as DefaultKernel;
class Kernel extends DefaultKernel{
  /**
  * The bootstrap classes for the application.
  *
  * @var array
  */
  protected $bootstrappers = [
  'Illuminate\Foundation\Bootstrap\DetectEnvironment' ,
  'Illuminate\Foundation\Bootstrap\LoadConfiguration' ,
  'Illuminate\Cloud\SAE\Log\ConfigureLogging' ,
  'Illuminate\Foundation\Bootstrap\HandleExceptions' ,
  'Illuminate\Foundation\Bootstrap\RegisterFacades' ,
  'Illuminate\Foundation\Bootstrap\RegisterProviders' ,
  'Illuminate\Foundation\Bootstrap\BootProviders' ,
  ];
}

这样还不行,还必须重写日志的部分实现 。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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即可 以上这些问题解决后,差不多就算成功了。最后修改下bootstrap\app.php来实现本地与SAE环境的优雅切换,主要是判断环境然后生成SAE专有应用实例和注入相应的Http内核.

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
/*
|--------------------------------------------------------------------------
| 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 Illuminate\Cloud\SAE\Application(
  realpath (__DIR__. '/../' )
  );
  $app ->singleton(
  Illuminate\Contracts\Http\Kernel:: class ,
  Illuminate\Cloud\SAE\Kernel:: class
  );
} else {
  $app = new Illuminate\Foundation\Application(
  realpath (__DIR__. '/../' )
  );
  $app ->singleton(
  Illuminate\Contracts\Http\Kernel:: class ,
  App\Http\Kernel:: 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(
  Illuminate\Contracts\Console\Kernel:: class ,
  App\Console\Kernel:: class
);
$app ->singleton(
  Illuminate\Contracts\Debug\ExceptionHandler:: class ,
  App\Exceptions\Handler:: 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 ;

这里解释下为什么要在bootstrap\app.php中来定义是否为SAE环境,原因很明确了,就是要注入相应的应用程序实例和Http实例,然后再这里也定义一下Storage 。

然后就是config\app.php的相关配置,根据环境判断来注入相应的服务提供者 。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
if (SAE){
  $removeProviders = [
  Illuminate\Cache\CacheServiceProvider:: class ,
  Illuminate\Session\SessionServiceProvider:: 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' ],[
  Illuminate\Cloud\SAE\Cache\SaeCacheServiceProvider:: class ,
  Illuminate\Cloud\SAE\Session\SessionServiceProvider:: class ,
  Illuminate\Cloud\SAE\Storage\StorageServiceProvider:: class ,
  Illuminate\Cloud\SAE\Segment\SegmentServiceProvider:: class ,
  ]);
  $app [ 'aliases' ][ 'Storage' ] = Illuminate\Cloud\SAE\Storage\Storage:: class ;
  $app [ 'aliases' ][ 'Segment' ] = Illuminate\Cloud\SAE\Segment\Segment:: class ;
}

最后再说说SAE专有应用程序实例和Http实例与原生的差别,主要还是本地写的问题。原生的会在应用程序启动时候生成路由、配置、服务提供者、模板编译的相关文件,以此来提升加载速度。但是到了SAE就不行了,所以重写了Application类的部分与路径相关的方法,来把这些文件生成到Storage中,而Http专有内核则是处理启动器中的日志类。具体代码就不贴出来,可以看看项目.

再给一个SAE可以使用的rewrite 。

?
1
2
3
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框架的PHP程序设计有所帮助.

最后此篇关于Laravel 5.1 on SAE环境开发教程【附项目demo源码】的文章就讲到这里了,如果你想了解更多关于Laravel 5.1 on SAE环境开发教程【附项目demo源码】的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com