65.9K
CodeProject 正在变化。 阅读更多。
Home

在 Lambda 上运行 PHP,使用 Homebrew MVC 框架

starIconstarIconstarIconstarIconstarIcon

5.00/5 (1投票)

2021年6月14日

CPOL

3分钟阅读

viewsIcon

5589

downloadIcon

64

30 分钟内构建自定义 PHP MVC 并部署到 AWS lambda。

演示URL:  https://0qdhumcwd5.execute-api.ap-southeast-2.amazonaws.com/Prod/

引言

大约一年前,我撰写了一篇关于为AWS Lambda构建自定义运行时环境的文章,使您能够运行PHP。以这种方式运行PHP有很多好处,它可以很好地扩展、托管成本很低,如果您熟悉PHP而不是AWS,那么这可能是一个有趣的尝试项目。过去一年中,有几个人就此与我联系,这个周末,我正在帮助某人让它工作。在回忆如何使用PHP的同时,我决定稍微修补一下,并用PHP编写一个迷你MVC框架。

最终的应用程序可以在这里看到https://dsemyh3dx0.execute-api.ap-southeast-2.amazonaws.com/Prod

背景

对于一些背景知识,这里有许多好的资源库https://github.com/aws-samples/php-examples-for-aws-lambda。实际上,我的许多示例存储库都基于此,但是如果您尚未设置PHP,则可能很难部署并弄清楚如何安装所有依赖项以及安装composer。因此,除了代码之外,我还添加了在Cloud9中设置和运行此代码的说明以及一个短视频。

Using the Code

如果您未使用AWS,那么SAM可能对您来说是新的,我将快速介绍一下。 SAM是无服务器应用程序模型,它帮助您使用模板yaml文件快速为AWS构建无服务器基础设施。 让我们快速看一下这个文件

请注意,我已经对正在使用的层硬编码了区域

AWSTemplateFormatVersion: 2010-09-09
Description:  Testing PHP and Lambda
Transform: AWS::Serverless-2016-10-31

##########################################################################
#  Parameters & Globals                                                  #
##########################################################################
Globals:
  Function:
    Timeout: 3
    
Resources:
##########################################################################
#  Lambda function with PHP runtime provided by layers                   #
##########################################################################
  CatchAllLambdaFunction:
    Type: AWS::Serverless::Function
    Properties:
      Description: Lambda function to hosts entire application codebase
      CodeUri: ./code/
      Runtime: provided
      Handler: index.php
      MemorySize: 4096
      Timeout: 30
      Tracing: Active
      Layers:
        - 'arn:aws:lambda:ap-southeast-2:209497400698:layer:php-73-fpm:25'
      Events:
        DynamicRequestsRoot:
          Type: Api
          Properties:
            Path: /
            Method: ANY
        DynamicRequestsProxy:
          Type: Api
          Properties:
            Path: /{proxy+}
            Method: ANY
##########################################################################
#  Stack Outputs                                                         #
##########################################################################  
Outputs:
  WebEndpoint:
    Description: "API Gateway endpoint URL for Prod stage"
    Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/"

从高层次上看,此模板指定了以下内容

  • 部署一个lambda函数
  • 部署一个API网关,这样我们就可以在浏览器中调用PHP函数。
  • 将一个层附加到lambda函数,该层已预构建以支持PHP(一个层是运行代码所需的其他依赖项)。
  • code文件夹指定为我们将要部署的代码的来源,如果需要,它可以包含许多文件和文件夹。
  • 强制将所有传入请求的入口点设置为index.php
  • 为此函数分配4096MB的RAM,并指定最大运行时时间为3秒。

如果我们考虑一下这个文件,它做了很多事情,它完全取代了构建服务器、安装PHP、安装Apache或nginx、配置PHP和服务器强化。这是一个巨大的好处和节省时间的措施。

部署

我选择制作一个小视频,而不是添加静态图像

创建一个新的Cloud9环境,最小的实例大小就足够了,但请确保选择Amazon Linux 2。

在Cloud 9中,在终端中执行以下步骤

sudo yum -y update
sudo amazon-linux-extras install -y php7.2 php-mbstring

git clone https://github.com/kukielp/aws-lambda-php-mvc.git

cd aws-lambda-php-mvc

php -r "copy('https://getcomposer.org.cn/installer', 'composer-setup.php');"
php -r "if (hash_file('sha384', 'composer-setup.php') === '756890a4488ce9024fc62c56153228907f1545c228516cbf63f885e036d37e9a59d27d63f46af1d4d07ee0f76181c7d3') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
php composer-setup.php
php -r "unlink('composer-setup.php');"

这将安装PHP 7.2,克隆存储库并安装composer,接下来我们将安装brefguzzel

cd code
php ../composer.phar require bref/bref
php ../composer.phar require guzzlehttp/guzzle

打开template.yaml,更新第27行以对齐您希望部署到的区域。您可以在此处查找可用的层:https://runtimes.bref.sh/

然后运行

cd ..
sam deploy --guided

按照说明进行操作,并确保部署到您在template.yaml中指定的区域。

部署完成后,您可以在浏览器中从输出部分打开WebEndpoint,您将看到应用程序正在运行。

MVC代码

index.php

// Include breff/guzzel and other dependencies.
require_once 'vendor/autoload.php';
    
$__path = explode("/", $_SERVER['REQUEST_URI']);

if(count($__path) < 3){
    $__controller = 'controller/base.php';
    $__view = 'view/base/base.php';
    $__controllerMethod = 'base';
}else{
    //Delete the first '/'
    $__pos = strpos($_SERVER['REQUEST_URI'], "/");
    if ($__pos !== false) {
        //extract the view (/sample/page will be --> view/sample/page.php)
        $__view = "view/" .substr_replace($_SERVER['REQUEST_URI'], "/", $__pos, 1) .".php";
        //extract the controller at this point it ill be (sample/page)
        $__controller = "controller/" .substr_replace($_SERVER['REQUEST_URI'], "/", $__pos, 1);
    }
    //Convert to an array and get the last item (page)
    $__method_arr = explode ("/", $__controller);
    $__controllerMethod = end($__method_arr);
        
    //Remove the last item in the path (sample/page --> sample)
    array_pop($__method_arr);
    //rebuild the path to the controller (controller/sample.php)
    $__controller = implode ($__method_arr, "/") .'.php';        
}
// Include the controller which provides access to....
include $__controller;
// the methods we will call (in this case page), the result will be placed back in $_rc
$_rc = call_user_func($__controllerMethod);
// include the view, the view should only ever access $_rc no other scopes for data.
include $__view;

所有这些代码的作用基本上是解析要“include”的两个文件以及要运行的方法。 $__rc 用作请求上下文变量,用于将信息从控制器传递到视图。控制器将处理任何业务逻辑,与数据库或外部源进行通信,而视图应仅包含用于显示目的的基本逻辑。

random.php(示例控制器)

    function joke() {
        
        $client = new GuzzleHttp\Client();
        $res = $client->get('https://official-joke-api.appspot.com/random_joke');
        $json = $res->getBody(); 
        $result = json_decode($json);
        $_rc = [
            "httpResult" => $result
        ];
        return $_rc;
    }    

joke.php(示例视图)

<html>
    <body>
        <h1>This is the Random Joke page!.</h1>
        <p>Enjoy the Joke Text:</p>
        <div>Setup: <?php echo $_rc["httpResult"]->setup; ?></div>
        <div>Punchline: <?php echo $_rc["httpResult"]->punchline; ?></div>
        <pre>
            <?php 
                krumo($_rc["httpResult"]);
            ?>
        </pre>
        <a href="/Prod">Home</a>
    </body>
</html>

包含Krumo以进行基本调试。

存储库:https://github.com/kukielp/aws-lambda-php-mvc

这是一个有趣的小实验,希望您喜欢阅读!

历史

  • 2021年6月14日:初始版本
© . All rights reserved.