天天看点

Lumen - 学习/实践1.文档阅读2.整理输出

1.应用场景

学习使用Lumen框架,开发API服务,比如为App提供REST API服务,

以及实现微服务架构~

2.学习/操作

Lumen - 学习/实践1.文档阅读2.整理输出

1.文档阅读

Lumen - PHP Micro-Framework By Laravel

Lumen - 为速度而生的 Laravel 框架 - Laravel 中国

Installation - Lumen - PHP Micro-Framework By Laravel

Lumen - 基于 Laravel 构建的最快的 PHP 微框架(Micro-Framework)。 | Laravel 中文网

2.整理输出

Note // 下面是几年前自己的学习体会

首先, 要即将学习的东西, 分为几部分, 快速地浏览一遍.

心中有个印象即可------基本思想: 这是啥, 能干啥[what-why]

后面再详细看, 认真看------基本思想:怎么干[how]

整个过程的基本思想:

这是啥,能干啥,怎么干. [what-why-how]

2.1 介绍

Lumen是一个基于Laravel的微框架,号称是以速度为生。

截用Lumen官网的一段,号称是比silex和slim还要快。

2.2 实操

本文将用Lumen来实现一个完整的用户注册、登录及获取用户信息的API 【REST API】

环境

Mac Pro

Homestead

Lumen 5.6

Lumen 8.x

Postman

方式一:

直接使用已有的项目进行测试 // 最后的测试是一样

Lumen 5.6

Code:

https://github.com/ningxiaofa/todo-app-with-lumen

https://github.com/ahmedkhan847/todoappwithlumen // 原始代码仓库

方式二:

使用Lumen 8.x重新构建

1. 构建项目,以及设置环境配置

composer create-project --prefer-dist laravel/lumen todorest
Lumen - 学习/实践1.文档阅读2.整理输出
Lumen - 学习/实践1.文档阅读2.整理输出
框架默认使用homestead环境, 比如数据库
Lumen - 学习/实践1.文档阅读2.整理输出
Homestead
Lumen - 学习/实践1.文档阅读2.整理输出

连接数据库

tablePlus 

Lumen - 学习/实践1.文档阅读2.整理输出
Navicat
Lumen - 学习/实践1.文档阅读2.整理输出

这里需要姜.env文件中的DB_HOST修改为: 192.168.10.10

如此,环境与项目初步看都okay了~

2. Setup Lumen to use Facade and Eloquent. 解开如下代码注释

$app->withFacades();

$app->withEloquent();

$app->register(App\Providers\AppServiceProvider::class);

$app->register(App\Providers\AuthServiceProvider::class);

$app->routeMiddleware([

'auth' => App\Http\Middleware\Authenticate::class,

]);

3. 创建数据表[创建数据库迁移文件]

进入目录 database/migrations

创建文件

执行迁移命令,生成数据表

4. Create the User & ToDo Model

Users.php

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

use Illuminate\Contracts\Auth\Authenticatable;

use Illuminate\Auth\Authenticatable as AuthenticableTrait;


class Users extends Model implements Authenticatable

{

   //

   use AuthenticableTrait;

   protected $fillable = ['username','email','password','userimage'];

   protected $hidden = [

   'password'

   ];

   /*

   * Get Todo of User

   *

   */

   public function todo()

   {

       return $this->hasMany('App\Todo','user_id');

   }

}

Todo.php
<?php      

namespace App;

use Illuminate\Database\Eloquent\Model;

class Todo extends Model

{

//

protected $table = 'todo';

protected $fillable = ['todo','category','user_id','description'];

}

5. 创建User控制器

cd app/Http/Controllers 

UsersController.php

<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Hash;
use Illuminate\Http\Request;
use App\Users;

class UsersController extends Controller
{
  public function __construct()
  {
    //  $this->middleware('auth:api');
  }

  /**
   * Display a listing of the resource.
   *
   * @return \Illuminate\Http\Response
   */
  public function authenticate(Request $request)
  {
    $this->validate($request, [
      'email' => 'required',
      'password' => 'required'
    ]);
    //  dd($request->all());
    $user = Users::where('email', $request->input('email'))->first();
    // Prevent from appearing error when user does not exist
    if (empty($user)) {
      return response()->json(['status' => 'fail', 'msg' => 'The user does not exist.'], 401);
    }
    if (Hash::check($request->input('password'), $user->password)) {
      $apikey = base64_encode(str_random(40));
      // dd($apikey); // Y0RDZE1FTDlaczFMdW5OcGVhTmhyT05LOW8yRjNkTVJQOFZqQ2o1TA==
      Users::where('email', $request->input('email'))->update(['api_key' => "$apikey"]);;
      return response()->json(['status' => 'success', 'api_key' => $apikey]);
    } else {
      return response()->json(['status' => 'fail', 'msg' => 'Email or password is not correct.'], 401);
    }
  }

  /**
   * User register
   * For ref: vendor/illuminate/database/Eloquent/Builder.php
   */
  public function register(Request $request)
  {
    // Validate params of user submited
    $this->validate($request, [
      'name' => 'required',
      'email' => 'required',
      'password' => 'required',
    ]);

    // Judgement: unique of email and name
    $user = Users::where('email', $request->input('email'))
    ->orWhere('name', $request->input('name'))
    ->first();
    if($user){
      return response()->json(['status' => 'fail', 'msg' => 'Name or email exists already.']);
    }

    // Store user info
    $hashPwd = Hash::make($request->input('password'));
    $ret = Users::insert(array_merge($request->all(), ['password' => $hashPwd]));
    if($ret){
      return response()->json(['status' => 'success', 'msg' => 'Register successully']);
    }
    return response()->json(['status' => 'fail', 'msg' => 'Register failed, please try later']);
  }
}
      

6. Update the Auth Service Provider

head to the app/Providers and open AutheServiceProvider.php file.

在boot()方法中,修改如下:

$this->app['auth']->viaRequest('api', function ($request) {

   if ($request->header('Authorization')) { 

        $key = explode(' ',$request->header('Authorization'));

        $user = Users::where('api_key', $key[1])->first();

        if(!empty($user)){

            $request->request->add(['userid' => $user->id]);

        }

        return $user;

    }           

});

 app/Http/Middleware folder and open Authenticate.php file
return response()->json(['error' => 'Unauthorized'], 401);      

7. Create the ToDo Controller

TodoController.php

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

use App\Todo;

use Auth;

class TodoController extends Controller

{

    public function __construct()

    {

        $this->middleware('auth');

    }

    public function index(Request $request)

    {

        $todo = Auth::user()->todo()->get();

        return response()->json(['status' => 'success', 'result' => $todo]);

    }

    public function store(Request $request)

    {

        $this->validate($request, [

            'todo' => 'required',

            'description' => 'required',

            'category' => 'required'

        ]);

        if (Auth::user()->todo()->Create($request->all())) {

            return response()->json(['status' => 'success']);

        } else {

            return response()->json(['status' => 'fail']);

        }

    }

    public function show($id)

    {

        $todo = Todo::where('id', $id)->get();

        return response()->json($todo);

    }

    public function edit($id)

    {

        $todo = Todo::where('id', $id)->get();

        return view('todo.edittodo', ['todos' => $todo]);

    }

    public function update(Request $request, $id)

    {

        $this->validate($request, [

            'todo' => 'filled',

            'description' => 'filled',

            'category' => 'filled'

        ]);

        $todo = Todo::find($id);

        if ($todo->fill($request->all())->save()) {

            return response()->json(['status' => 'success']);

        }

        return response()->json(['status' => 'failed']);

    }

    public function destroy($id)

    {

        if (Todo::destroy($id)) {

            return response()->json(['status' => 'success']);

        }

    }

}

8. Create Routes For the Todo API

$app->group(['prefix' => 'api/'], function ($app) {

    $app->get('login/','[email protected]');

    $app->post('todo/','[email protected]');

    $app->get('todo/', '[email protected]');

    $app->get('todo/{id}/', '[email protected]');

    $app->put('todo/{id}/', '[email protected]');

    $app->delete('todo/{id}/', '[email protected]');

});

9. Test the ToDo REST API / 测试ToDo REST API

启动PHP内置HTTP Server
php -S localhost:8000 -t public
Lumen - 学习/实践1.文档阅读2.整理输出

9.1 Register user

测试之前要先注册一个user用来测试

http://localhost:8000/api/register/[email protected]&password=Aa123456&name=william

Lumen - 学习/实践1.文档阅读2.整理输出
数据表users
Lumen - 学习/实践1.文档阅读2.整理输出
注册成功!

9.2 Login using the API

http://localhost:8000/api/login/
Lumen - 学习/实践1.文档阅读2.整理输出
登录成功!

9.3 Create todo first

Note

认证信息可以放在在Authorization栏[postman专门独立出来放认证信息], 也可以放在请求头中。

前者[Authorization]

Lumen - 学习/实践1.文档阅读2.整理输出
 后者[Request Header]
Lumen - 学习/实践1.文档阅读2.整理输出

1. 测试没有添加认证的情况下,即不在请求头中带上api_key=OVRrUnVud1dFaEJQeUZJdjdsWVJCa1oyMDNEUXBKS1F4T3FsVjA1aA==

发起请求,查看结果: 未认证

Lumen - 学习/实践1.文档阅读2.整理输出

2. 正常带上api_key

重新请求,查看返回结果

Lumen - 学习/实践1.文档阅读2.整理输出

 请求体

payload: // content-type: json/application

{

"todo": "Testing REST Api",

"description": "Testing REST Api with Lumen",

"category": "REST"

}

Lumen - 学习/实践1.文档阅读2.整理输出
数据表
Lumen - 学习/实践1.文档阅读2.整理输出
创建todo成功 !

9.4 Get todo list

http://localhost:8000/api/todo
Lumen - 学习/实践1.文档阅读2.整理输出
 获取列表成功!

9.5 Get one todo detail

http://localhost:8000/api/todo/1

Lumen - 学习/实践1.文档阅读2.整理输出

获取todo详情成功! 

9.6 Update todo

http://localhost:8000/api/todo/1
Lumen - 学习/实践1.文档阅读2.整理输出
数据表todo
Lumen - 学习/实践1.文档阅读2.整理输出
更新成功! 

9.7 Delete todo

http://localhost:8000/api/todo/2
Lumen - 学习/实践1.文档阅读2.整理输出
数据表todo
Lumen - 学习/实践1.文档阅读2.整理输出

 删除成功!

 最后再获取列表

Lumen - 学习/实践1.文档阅读2.整理输出
一切正常!

后续补充

...

3.问题/补充

1. 为什么Lumen认证使用的Bearer token类型验证?具体的配置地方在哪里?与其他认证方式有什么区别,或者说为什么选择了这种认证方式?

Authentication - Lumen - PHP Micro-Framework By Laravel

2. 这里的api_key是永久的,不会变的,也就意味着如果在App中,用户自己不主动退出,是一直保持登录状态的。当然也可能因为一些操作,到底api_key丢失的情况,则需要重新登录~

TBD

4.参考

就是上面的文档链接列表

Restful API - 学习/实践_william_n的博客-CSDN博客

后续补充

...