thinkphp5.1 运行在 腾讯云 阿里云 serverless 环境

用阿里云吧
https://help.aliyun.com/document_detail/159783.html

阿里云存储配置

ROSTemplateFormatVersion: '2015-09-01'
Transform: 'Aliyun::Serverless-2018-04-03'
Resources:
  blog:
    Type: 'Aliyun::Serverless::Service'
    Properties:
      Description: typecho博客
      Role: 'acs:ram::1157897650908336:role/new-service1578321763398-role'
      VpcConfig:
        VpcId: vpc-uf6kcg6z74ayq0pa9nliu
        VSwitchIds:
          - vsw-uf6atq97d8jdokd8r4e5r
        SecurityGroupId: sg-uf60rdm0o11g8ajzf56d
      NasConfig:
        UserId: 10000
        GroupId: 10000
        MountPoints:
          - ServerAddr: '39d4c4be1d-amf86.cn-shanghai.nas.aliyuncs.com:/blog'
            MountDir: /mnt/blog
      InternetAccess: true
    serverless:
      Type: 'Aliyun::Serverless::Function'
      Properties:
        Handler: typecho_aliyun.handler
        Runtime: php7.2
        CodeUri: './'
        Timeout: 600
        MemorySize: 128
        EnvironmentVariables:
          PHP_INI_SCAN_DIR: '/code/extension'
      Events:
        httpTrigger:
          Type: HTTP
          Properties:
            AuthType: ANONYMOUS
            Methods: ['POST', 'GET', 'HEAD', 'PUT', 'DELETE']

阿里云

require_once './vendor/autoload.php';

use RingCentral\Psr7\Response;
use ServerlessFC\PhpCgiProxy;

define('ROOT_DIR', '/mnt/blog');
define('TEXT_REG', '#\.html.*|\.js.*|\.css.*|\.html.*#');
define('BINARY_REG', '#\.gif.*|\.jpg.*|\.png.*|\.jepg.*|\.swf.*|\.bmp.*|\.ico.*|\.svg.*#');

function debug($contents, $code = 200, $headers = ['Content-Type' => 'text/html'])
{
    if (!is_string($contents)) {
        $contents = json_encode($contents, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
    }
    return new Response(
        $code,
        $headers,
        $contents
    );
}

function fileHandler($filename)
{
    $filename = rawurldecode($filename);
    $handle = fopen($filename, "r");
    $contents = fread($handle, filesize($filename));
    fclose($handle);
    try {
        $type = $GLOBALS['fcPhpCgiProxy']->getMimeType($filename);
    } catch (\Exception $e) {
        $type = 'application/octet-stream';
    }
    $headers = [
        'Content-Type' => $type,
        'Accept-Ranges' => 'bytes',
        'Cache-Control' => 'max-age=3600',
    ];
    return new Response(200, $headers, $contents);
}

function appHandler($request, $host, $scheme, $script = 'index.php')
{
    $param = [
        $request, ROOT_DIR, $script,
        [
            'HTTP_HOST' => $host,
            'SERVER_NAME' => $host,
            'SERVER_PORT' => '80',
            'REQUEST_SCHEME' => $scheme,
            'SCRIPT_FILENAME' => ROOT_DIR . '/' . $script,
            'SCRIPT_NAME' => $script,
        ],
        [
            'debug_show_cgi_params' => false,
            'readWriteTimeout' => 50000,
        ],
    ];
    try {
        $resp = call_user_func_array([$GLOBALS['fcPhpCgiProxy'], 'requestPhpCgi'], $param);
    } catch (\Exception $e) {
        $GLOBALS['fcPhpCgiProxy'] = new PhpCgiProxy;
        $resp = call_user_func_array([$GLOBALS['fcPhpCgiProxy'], 'requestPhpCgi'], $param);
    }
    return $resp;
}

function trace(string $log, string $level = 'info')
{
    $logger = $GLOBALS['fcLogger'];
    call_user_func([$logger, $level], $log);
}

function handler($request, $context): Response
{
    $uri = $request->getAttribute('requestURI');
    $host = $request->getHeaderLine('Host');
    $method = $request->getMethod();
    $scheme = $request->getHeaderLine('X-Forwarded-Proto');
    $clientIP = $request->getAttribute('clientIP');
    $userAgent = $request->getHeaderLine('user-agent');

    // 访问日志
    $log = sprintf('%s %s %s %s %s', $method, $host, $uri, $clientIP, $userAgent);
    // trace($log);

    $urlInfo = parse_url($uri);
    $path = $urlInfo['path'];
    $query = $urlInfo['query'] ?? '';

    $pathInfo = pathinfo($path);
    $extension = $pathInfo['extension'] ?? '';
    $filePath = ROOT_DIR . $path;
    // 目录跳转
    if (!preg_match('#/$#', $path) && is_dir($filePath . '/') && $method == 'GET') {
        return new Response(301, ['Location' => str_replace($path, $path . '/', $uri)], '');
    }
    // 静态文件
    if (file_exists($filePath) && (preg_match(TEXT_REG, $path) || preg_match(BINARY_REG, $path))) {
        return fileHandler($filePath);
    }
    // 直接访问
    if (strpos($path, '.php')) {
        $script = $path;
    }
    // 伪静态
    if (!strpos($path, '.php')) {
        // 优先访问index.php
        if (is_dir($filePath)) {
            $requestUri = $path . 'index.php' . '?' . $query;
            $request = $request->withAttribute('requestURI', $requestUri);
            $script = $path . 'index.php';
        } else {
            $script = 'index.php';
        }
    }
    return appHandler($request, $host, $scheme, $script);
}

// 显示nas目录
// fun nas ls -a nas://

腾讯云

<?php
/**
 * thinkphp5.1运行在腾讯云serverless的容器
 *
 * 2020-03-03
 *
 * 范国金
 */

require_once __DIR__ . '/thinkphp/base.php';

// 应用目录
define('APP_PATH', __DIR__ . '/application/');
// 缓存目录
define('RUNTIME_PATH', '/tmp/');
// 静态目录
define('STATIC_PATH', __DIR__ . '/public');
// 文本文件
define('TEXT_REG', '#\.html.*|\.js.*|\.css.*|\.html.*#');
// 其他文件
define('BINARY_REG', '#\.gif.*|\.jpg.*|\.png.*|\.jepg.*|\.swf.*|\.bmp.*|\.ico.*#');

use think\Container;
use think\Db;
use think\Error;
use think\exception\ClassNotFoundException;
use think\exception\HttpResponseException;
use think\facade\Request;
use think\Loader;
use think\Route;
use think\route\Dispatch;

class App extends \think\App
{
    public static function mainHandler($event, $context)
    {
        // 请求路径
        $path = str_replace("//", "/", $event->path);

        // 静态文件
        if (preg_match(TEXT_REG, $path) || preg_match(BINARY_REG, $path)) {
            return static::handlerStatic($path);
        }

        // 请求数据
        $req = $event->body ?? '';
        $data = !empty($req) ? json_decode($req, true) : [];

        // 请求头部
        $headers = $event->headers ?? [];
        $headers = json_decode(json_encode($headers), true);
        $headers['HTTP_X_REAL_IP'] = $event->requestContext->sourceIp;
        $headers['HTTP_REMOTE_ADDR'] = $event->requestContext->sourceIp;

        // 请求参数
        $query = $event->queryString ?? [];
        $query = json_decode(json_encode($query), true);
        $params = json_decode($event->body ?? '', true) ?? [];
        $params = array_merge($query, $params);

        // 启动框架
        Container::set('app', \App::class);
        $app = Container::get('app');
        $app->path(APP_PATH)->initialize();

        // 重置数据
        $app->setBeginTime(microtime(true));
        $app->setBeginMem(memory_get_usage());
        $app->delete('think\Request');
        Db::$queryTimes = 0;
        Db::$executeTimes = 0;

        // 请求内容
        $uri = $event->path . '?' . http_build_query($query);
        $app->request = Request::create($uri, $event->httpMethod, $params, $cookie = [], $files = [], $server = [], $content = null);
        $app->request->withHeader($headers);
        $app->route->setRequest($app->request);

        // 执行请求
        $resp = $app->run();
        $body = $resp->getContent();
        $status = $resp->getCode();
        $header = $resp->getHeader();

        // 调试注入
        if ($app->env->get('app_trace', $app->config->get('app_trace'))) {
            $app->debug->inject($resp, $body);
        }

        return [
            'isBase64Encoded' => false,
            'statusCode' => $status,
            'headers' => $header,
            'body' => $body,
        ];
    }

    public static function handlerStatic($path)
    {
        $filename = STATIC_PATH . $path;
        $handle = fopen($filename, "r");
        $contents = fread($handle, filesize($filename));
        fclose($handle);

        $base64Encode = false;
        $headers = [
            'Content-Type' => '',
            'Accept-Ranges' => 'bytes',
        ];
        $body = $contents;
        if (preg_match(BINARY_REG, $path)) {
            $base64Encode = true;
            $headers = [
                'Content-Type' => '',
            ];
            $body = base64_encode($contents);
        }
        return [
            "isBase64Encoded" => $base64Encode,
            "statusCode" => 200,
            "headers" => $headers,
            "body" => $body,
        ];
    }

    public function setBeginTime($value)
    {
        $this->beginTime = $value;
        return $this;
    }

    public function setBeginMem($value)
    {
        $this->beginMem = $value;
        return $this;
    }

    /**
     * 初始化应用
     * @access public
     * @return void
     */
    public function initialize()
    {
        if ($this->initialized) {
            return;
        }
        $this->initialized = true;
        $this->beginTime = microtime(true);
        $this->beginMem = memory_get_usage();
        $this->rootPath = dirname($this->appPath) . DIRECTORY_SEPARATOR;
        // 修改写入路径
        $this->runtimePath = defined('RUNTIME_PATH') ? RUNTIME_PATH : $this->rootPath . 'runtime' . DIRECTORY_SEPARATOR;
        $this->routePath = $this->rootPath . 'route' . DIRECTORY_SEPARATOR;
        $this->configPath = $this->rootPath . 'config' . DIRECTORY_SEPARATOR;
        static::setInstance($this);
        $this->instance('app', $this);
        if (is_file($this->rootPath . '.env')) {
            $this->env->load($this->rootPath . '.env');
        }
        $this->configExt = $this->env->get('config_ext', '.php');
        $this->config->set(include $this->thinkPath . 'convention.php');
        $this->env->set([
            'think_path' => $this->thinkPath,
            'root_path' => $this->rootPath,
            'app_path' => $this->appPath,
            'config_path' => $this->configPath,
            'route_path' => $this->routePath,
            'runtime_path' => $this->runtimePath,
            'extend_path' => $this->rootPath . 'extend' . DIRECTORY_SEPARATOR,
            'vendor_path' => $this->rootPath . 'vendor' . DIRECTORY_SEPARATOR,
        ]);
        $this->namespace = $this->env->get('app_namespace', $this->namespace);
        $this->env->set('app_namespace', $this->namespace);
        Loader::addNamespace($this->namespace, $this->appPath);
        $this->init();
        $this->suffix = $this->config('app.class_suffix');
        $this->appDebug = $this->env->get('app_debug', $this->config('app.app_debug'));
        $this->env->set('app_debug', $this->appDebug);
        if (!$this->appDebug) {
            ini_set('display_errors', 'Off');
        } elseif (PHP_SAPI != 'cli') {
            if (ob_get_level() > 0) {
                $output = ob_get_clean();
            }
            ob_start();
            if (!empty($output)) {
                echo $output;
            }
        }
        if ($this->config('app.exception_handle')) {
            Error::setExceptionHandler($this->config('app.exception_handle'));
        }
        if (!empty($this->config('app.root_namespace'))) {
            Loader::addNamespace($this->config('app.root_namespace'));
        }
        Loader::loadComposerAutoloadFiles();
        Loader::addClassAlias($this->config->pull('alias'));
        Db::init($this->config->pull('database'));
        date_default_timezone_set($this->config('app.default_timezone'));
        $this->loadLangPack();
        $this->routeInit();
    }
}
// 入口函数
function main_handler($event, $context)
{
    return App::mainHandler($event, $context);
}

serverless cli部署

service: thinkphp51

provider:
  name: tencent
  runtime: Php7
  credentials: ~/credentials
  region: ap-shanghai

plugins:
  - serverless-tencent-scf

functions:
  thinkphp5:
    handler: tencent.main_handler
    memorySize: 128
    timeout: 600

此处评论已关闭