PHP微框架 Lumen 使用全纪录

lumen.jpeg

本文将介绍Lumen的使用和遇到的问题,重点是官方文档中没太详细介绍的内容,不定期更新。

Lumen框架使用Laravel模块构建而成。

与Laravel臃肿不同,Lumen是微框架,去繁就简,专注于构建无状态API。

在使用中依然能感受到Laravel一样的艺术感,

Lumen的性能表现也值得称赞。

如果你在构建API应用,请关注Lumen。

安装Lumen框架

  • 全局安装Composer
curl -sS https://getcomposer.org/installer | php
mv composer.phar /usr/local/bin/composer
  • 配置Composer中国镜像,国内用户都懂得。
composer config -g repo.packagist composer https://packagist.phpcomposer.com

  • 建立一个目录为lumen的项目
composer create-project --prefer-dist laravel/lumen lumen

一些简单的配置

配置web服务器,支持单入口(优雅链接)

Apache配置:

  • 打开mod_rewrite模块
  • 配置public/.htaccess
Options +FollowSymLinks
RewriteEngine On

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]

Nginx:

nginx.conf

location / {
    try_files $uri $uri/ /index.php?$query_string;
}

配置开发环境

Lumen把配置放到.env文件中. 根目录下包含一个.env.example文件

cp .env.example .env

.env 示例

APP_ENV=local
APP_DEBUG=false
APP_KEY=

如何判断当前程序运行环境?

$environment = app()->environment();

if (app()->environment('local')) {
    // 环境是 local
    // 加载 local 配置
}

if (app()->environment('local', 'staging')) {
    // 环境是 local 或 staging...
}

  • 第一个页面 hello world

在routes中添加路由规则 /app/Http/routes.php

方法1:接收闭包函数

$app->get('/hello', function() use ($app) {
    return 'Hello World!';
});

方法2:指定路由到控制器方法处理

$app->get('/hello', 'HelloController@index');

一个简单的控制器动作

/app/Http/Controllers/HelloController.php

<?php

namespace App\Http\Controllers;

class HelloController extends Controller
{
    public function index()
    {
        return 'Hello World!';
    }
}

Lumen异常处理 修改异常报告

为什么引入这个问题呢?我们一般用Lumen写API接口,返回格式为JSON或XML。

Lumen默认报错是这个样子的, 不满足我们的要求了,我们想实现浏览器呈现的错误信息为JSON格式怎么办呢?

lumen-exception-default.png

首先Lumen输出JSON 响应很简单。

return response()->json(['name' => 'Abigail', 'state' => 'CA']);

再来看异常处理如何修改。

Lumen中的异常都交给App\Exceptions\Handler这个类处理

render 方法负责将指定的异常转换成HTTP响应再发送到浏览器。

我们把报错的行号,文件和错误消息都通过JSON返回:

<?php

/**
 * Render an exception into an HTTP response.
 *
 * @param  \Illuminate\Http\Request  $request
 * @param  \Exception  $e
 * @return \Illuminate\Http\Response
 */
public function render($request, Exception $e)
{
    $code = $e->getCode() == 0 ? 500 : $e->getCode();
    $msg = sprintf("%s:%s:%s", $e->getFile(), $e->getLine(), $e->getMessage());
    return response()->json(array('errorNo' => $code, 'errorMsg' => $msg));
}

刚才的错误消息变成了这样

{"errorNo":500,"errorMsg":"\/home\/vagrant\/Code\/www_data\/lumen\/app\/Http\/routes.php:18:Parse error: syntax error, unexpected '$app' (T_VARIABLE)"}

Lumen操作phpredis?

phpredis 是PHP的Redis扩展。
predis是PHP实现的Redis操作库,
由于phpredis的性能更好,所以我们有必要折腾一下。

/bootstrap/app.php中,把phpredis注入到Lumen容器中


//Lumen中使用PhpRedis
$app->singleton('redis', function() {
    try {
        $redis = new \Redis();
        $redis->connect('127.0.0.1', 6379);
        return $redis;
    } catch (Exception $e) {
        echo $e->getMessage();
    }
    
});
unset($app->availableBindings['redis']);

绑定后即可通过 app('redis') 操作Redis了。

Lumen怎么添加自定义配置?

我们看到上面的代码 $redis->connect('127.0.0.1', 6379);
像这种代码把配置信息硬编码到代码中,以后维护起来不是很好的。
我们把Redis连接修改为配置文件怎么办?

方法1:.env

$redis->connect(env('REDIS_HOST', env('REDIS_PORT')));

方法2:Laravel风格的config文件

  • 添加文件 /config/redis.php
<?php

return [
    'REDIS_HOST' => '127.0.0.1',
    'REDIS_PORT' => 6379,
];
  • 修改bootstrap/app.php, 让配置文件生效
// ... 
$app->configure('redis');
return $app;
  • 使用 config()函数来获取配置值
$redis->connect(config('redis.REDIS_HOST'), config('redis.REDIS_PORT'));

Lumen请求相关方法

Lumen Request类由Illuminate\Http\Request实现

// 所有的路由规则
app()->getRoutes();

// 当前REQUEST_URI
// app('request') 是 Illuminate\Http\Request类的实例
app('request')->getRequestUri();

// 当前route

app('request')->route();

怎么得到当前Uri的控制器、Action、路由规则


<?php

namespace App\Http\Controllers;

class HelloController extends Controller
{
    public function index()
    {
     // 当前path
        $router = explode("?", $request->getRequestUri())[0];
        // 所有的router
        $rts = app()->getRoutes();
        // 当前route
        $routeInfo = app('request')->route();
        $rows = [];
        foreach ($rts as $rt => $route ) {
            $rows[$route['uri']] = [
                'verb' => $route['method'],
                'uri' => $route['uri'],
                'uses' => isset($route['action']['uses']) ? $route['action']['uses'] : 'Closure',
                'controller' => $this->getController($route['action']),
                'action' => $thiw->getAction($route['action']),
            ];
        }
        
        print_r($rows);
        return;
    }
        
    /**
     * @param array $action
     * @return mixed|string
     */
    protected function getAction(array $action)
    {
        if (!empty($action['uses'])) {
            $data = $action['uses'];
            if (($pos = strpos($data, "@")) !== false) {
                return substr($data, $pos + 1);
            } else {
                return "METHOD NOT FOUND";
            }
        } else {
            return 'Closure';
        }
    }

    /**
     * @param array $action
     * @return mixed|string
     */
    protected function getController(array $action)
    {
        if (empty($action['uses'])) {
            return 'Closure';
        }
        
        return current(explode("@", $action['uses']));
    }
 
 }   
    

得到的所有路由规则数组

Array
(
    [/] => Array
        (
            [verb] => GET
            [uri] => /
            [uses] => Closure
            [controller] => Closure
            [action] => Closure
        )

    [/hello] => Array
        (
            [verb] => GET
            [uri] => /hello
            [uses] => App\Http\Controllers\HelloController@index
            [controller] => App\Http\Controllers\HelloController
            [action] => index
        )
)

Lumen 实现自定义LOG目录

由于篇幅较长,单独成一篇文章 Lumen 实现自定义LOG目录

今天先写到这里,由于本人水平有限,如果文章中有错误,还请大神指点。

大家遇到Lumen使用问题欢迎和我交流,有问题可以在评论区留言。

本文会持续更新。大家可以把这篇文章添加到收藏。


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,835评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,598评论 1 295
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,569评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,159评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,533评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,710评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,923评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,674评论 0 203
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,421评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,622评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,115评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,428评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,114评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,097评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,875评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,753评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,649评论 2 271

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,100评论 18 139
  • 原文链接 必备品 文档:Documentation API:API Reference 视频:Laracasts ...
    layjoy阅读 8,519评论 0 121
  • 必备品文档:DocumentationAPI: API Reference视频:Laracasts速查表:Lara...
    ethanzhang阅读 5,724评论 0 68
  • Composer Repositories Composer源 Firegento - Magento模块Comp...
    零一间阅读 3,940评论 1 66
  • “表情包”是一种利用图片来表示感情的一种方式。表情包是在社交软件活跃之后,形成的一种流行文化,表情包流行于互联网上...
    呆呆浅蓝阅读 823评论 0 2