[สร้าง Api ด้วย Laravel 5.1 ภาคต่อ V2. With Repository]


หลังจากที่ได้ลองทำการสร้าง api ด้วย laravel ภาคหนึ่งไปแล้ว เราลองมาทำให้มันยากขึ้นกันดีกว่า
ก่อนอื่นผมขอออกตัวไว้ก่อนว่าเน้นให้เห็นภาพรวมก่อน แล้วบทต่อไปผมจะไปเจาะลึกที่ละเนื้อหาครับ

เอาล่ะสำหรับท่านที่ยังไม่ได้ติดตั้ง Laravel ก็ทำการติดตั้งให้เรียบร้อยครับ
Library ที่จะให้


วิธีการติดตั้ง Prettus Repository คลิ๊กได้ตามลิงค์ครับ สำหรับวิธีการติดตั้ง Restable สามารถทำได้ดังนี้ 
  1. install ผ่าน composer โดยใช้คำสั่ง
    composer require teepluss/restable
  2. รอสักครู่เพื่อให้ Package ดาวโหลดจนเสร็ดแล้วทำการแก้ไขไฟล์ app.php โดยเพิ่ม

    provider
    Teepluss\Restable\RestableServiceProvider::class,  
    
     'Restable' => Teepluss\Restable\Facades\Restable::class,
    
    
Library Teepluss\Restable ตัวนี้เพื่อเป็นตัวกลางการ Response handle ครับซึ่งใช้งานได้สะดวกมาก สามารถเรียกใช้งานจากไฟล์ไหนก็ได้ ภายหลังจากการ Load เพราะว่าเป็น Facade ครับ

Library Benchmark สำหรับตัวนี้เอาไว้เพื่อจับเวลาตามชื่อเลยครับ สำหรับการติดตั้งทำได้โดย สร้างไฟล์ตามนี้ครับ
namespace App\Libraries;

class Benchmark
{

    /**
     * List of all benchmark markers and when they were added
     *
     * @var array
     */
    public $marker = array();

    // --------------------------------------------------------------------

    /**
     * Set a benchmark marker
     *
     * Multiple calls to this function can be made so that several
     * execution points can be timed
     *
     * @access    public
     * @param    string    $name    name of the marker
     * @return    void
     */
    public function mark($name)
    {
        $this->marker[$name] = microtime();
    }

    // --------------------------------------------------------------------

    /**
     * Calculates the time difference between two marked points.
     *
     * If the first parameter is empty this function instead returns the
     * {elapsed_time} pseudo-variable. This permits the full system
     * execution time to be shown in a template. The output class will
     * swap the real value for this variable.
     *
     * @access    public
     * @param    string    a particular marked point
     * @param    string    a particular marked point
     * @param    integer    the number of decimal places
     * @return    mixed
     */
    public function elapsed_time($point1 = '', $point2 = '', $decimals = 4)
    {
        if ($point1 == '') {
            return '{elapsed_time}';
        }

        if (!isset($this->marker[$point1])) {
            return '';
        }

        if (!isset($this->marker[$point2])) {
            $this->marker[$point2] = microtime();
        }

        list($sm, $ss) = explode(' ', $this->marker[$point1]);
        list($em, $es) = explode(' ', $this->marker[$point2]);

        return number_format(($em + $es) - ($sm + $ss), $decimals);
    }

    // --------------------------------------------------------------------

    /**
     * Memory Usage
     *
     * This function returns the {memory_usage} pseudo-variable.
     * This permits it to be put it anywhere in a template
     * without the memory being calculated until the end.
     * The output class will swap the real value for this variable.
     *
     * @access    public
     * @return    string
     */
    public function memory_usage()
    {
        return '{memory_usage}';
    }

}

Route
Route::group(['namespace' => 'Api\v1\Member', 'prefix' => 'api/v1/member', 'middleware' => ['guest']], function () {

    Route::get('/', [
        'uses' => 'MembersController@index',
        'as' => 'member.MembersController.index',
    ]);

    Route::post('/', [
        'uses' => 'MembersController@store',
        'as' => 'member.MembersController.store',
    ]);

});

Controllers

namespace App\Http\Controllers\Api\v1\Member;

use App\Http\Controllers\Api\v1\Member\BaseApiController;
use App\Http\Requests\MemberRequest;
use App\Repositories\MembersRepository;
use Illuminate\Http\Request;

class MembersController extends BaseApiController
{
    /**
     * [$request description]
     * @var [type]
     */
    private $request;

    /**
     * [$member description]
     * @var [type]
     */
    private $member;

    public function __construct(MemberRequest $request, MembersRepository $member)
    {
        parent::__construct();
        $this->request = $request;
        $this->member = $member;
    }

    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        try {
            $member['item'] = $this->member->all();
            if (!empty($member)) {
                $all = $member['item']->count();
                return $this->response(200, $member, '', $all, $all);
            } else {
                return $this->response(404, []);
            }
        } catch (\Exception $e) {
            return $this->response(400, [], $e->getMessage());
        }
    }

/**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        try {
            $insert['item'] = $this->member->create(\Input::all());
            if ($insert) {
                return $this->response(200, $insert, '', 1, 1);
            } else {
                return $this->response(400, ['insert fail']);
            }
        } catch (\Exception $e) {
            return $this->response(400, [], $e->getMessage());
        }
    }

}
Request
namespace App\Http\Requests;

use App\Http\Requests\Request;

class MemberRequest extends Request
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return true;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        $rules = [];
        switch ($this->method()) {
            case 'POST':
                $rules = [
                    'name' => 'required|string|min:3|max:60',
                    'email' => 'required|string|email|unique:users,email',
                    'password',
                    'remember_token',
                    'created_at' => 'date|date_format:Y-m-d H:i:s',
                    'updated_at' => 'date|date_format:Y-m-d H:i:s',
                ];
                break;

            default:
                # code...
                break;
        }
        return $rules;
    }
}

BaseControllers
 
namespace App\Http\Controllers\Api\v1\Member;

use App\Http\Controllers\Controller;
use App\Libraries\Benchmark;

class BaseApiController extends Controller
{
    public $benchmark;
    public static $listCode = array(
        '200' => 'OK',
        '201' => 'Created',
        '202' => 'Accepted',
        '203' => 'Non-Authoritative Information',
        '204' => 'No Content',
        '205' => 'Reset Content',
        '206' => 'Partial Content',
        '300' => 'Multiple Choices',
        '301' => 'Moved Permanently',
        '302' => 'Found',
        '303' => 'See Other',
        '304' => 'Not Modified',
        '306' => 'Switch Proxy',
        '307' => 'Temporary Redirect',
        '308' => 'Resume Incomplete',
        '400' => 'Bad Request',
        '401' => 'Unauthorized',
        '402' => 'Payment Required',
        '403' => 'Forbidden',
        '404' => 'Not Found',
        '405' => 'Method Not Allowed',
        '406' => 'Not Acceptable',
        '407' => 'Proxy Authentication Required',
        '408' => 'Request Timeout',
        '409' => 'Conflict',
        '410' => 'Gone',
        '411' => 'Length Required',
        '412' => 'Precondition Failed',
        '413' => 'Request Entity Too Large',
        '414' => 'Request-URI Too Long',
        '415' => 'Unsupported Media Type',
        '416' => 'Requested Range Not Satisfiable',
        '417' => 'Expectation Failed',
        '500' => 'Internal Server Error',
        '501' => 'Not Implemented',
        '502' => 'Bad Gateway',
        '503' => 'Service Unavailable',
        '504' => 'Gateway Timeout',
        '505' => 'HTTP Version Not Supported',
        '511' => 'Network Authentication Required',
    );

    public function __construct()
    {
        $this->benchmark = new Benchmark;
        $this->benchmark->mark('start');
    }

    public function response($code = 400, $data = '', $errorMessage = null, $total = 0, $total_page = 0)
    {
        if ($code == '0') {
            $code = 400;
        }
        $header = array(
            'code' => $code,
            'message' => self::$listCode[$code],
        );
        $response = array(
            'header' => $header,
            'transaction_id' => (isset($transaction_id)) ? $transaction_id : '105116109 ' . DATE('U'),
            'total' => $total,
            'total_page' => $total_page,
            'count_result' => (isset($data['item'])) ? count($data['item']) : 0,
            'date_current' => date('Y-m-d H:i:s'),
        );

        $request = \Request::all();
        $responseReturn = array_merge($response, $request);
        if ($response['header']['code'] == 200) {
            $responseReturn['data'] = $data;
        } else {
            $responseReturn['data'] = null;
            $responseReturn['debug_error_message'] = $errorMessage;
        }
        $this->benchmark->mark('end');
        $responseTime = $this->benchmark->elapsed_time('start', 'end');
        $responseReturn['process_time'] = $responseTime;
        return \Restable::listing($responseReturn)->render('json');

    }
}
MemberRepository interface
namespace App\Repositories;

use Prettus\Repository\Contracts\RepositoryInterface;

/**
 * Interface MembersRepository
 * @package namespace App\Repositories;
 */
interface MembersRepository extends RepositoryInterface
{
    //
}

MemberRepo
namespace App\Repositories;

use Prettus\Repository\Eloquent\BaseRepository;
use Prettus\Repository\Criteria\RequestCriteria;
use App\Repositories\MembersRepository;
use App\Entities\Members;

/**
 * Class MembersRepositoryEloquent
 * @package namespace App\Repositories;
 */
class MembersRepositoryEloquent extends BaseRepository implements MembersRepository
{
    /**
     * Specify Model class name
     *
     * @return string
     */
    public function model()
    {
        return Members::class;
    }

    /**
     * Boot up the repository, pushing criteria
     */
    public function boot()
    {
        $this->pushCriteria(app(RequestCriteria::class));
    }

    


}



}

Member model
namespace App\Entities;

use Illuminate\Database\Eloquent\Model;
use Prettus\Repository\Contracts\Transformable;
use Prettus\Repository\Traits\TransformableTrait;

class Members extends Model implements Transformable
{
    use TransformableTrait;

    protected $table = 'users';
    protected $fillable = [
        'name',
        'email',
        'password',
        'remember_token',
        'created_at',
        'updated_at',
    ];

    protected $hidden = [
        'password',
        'remember_token',
    ];

}
VerifyCsrf
namespace App\Http\Middleware;

use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as BaseVerifier;

class VerifyCsrfToken extends BaseVerifier
{
    /**
     * The URIs that should be excluded from CSRF verification.
     *
     * @var array
     */
    protected $except = [
        'api/v1/member',
    ];
}

Request
namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

abstract class Request extends FormRequest
{
    public function response(array $errors)
    {
        $header = array(
            'code' => '400',
            'message' => 'Bad Request',
        );
        $response = array(
            'header' => $header,
            'transaction_id' => ($this->has('transaction_id')) ? $this->get('transaction_id') : DATE('U'),
            'total' => 0,
            'count_result' => 0,
            'date_current' => date('Y-m-d H:i:s'),
        );
        $request = $this->all();
        $responseReturn = array_merge($response, $request);
        $responseReturn['data'] = $errors;
        return \Restable::listing($responseReturn)->render('json');
    }
}

RepositoryProvider
namespace App\Providers;

use Illuminate\Support\ServiceProvider;

class RepositoryProvider extends ServiceProvider
{
    /**
     * Bootstrap the application services.
     *
     * @return void
     */
    public function boot()
    {
        //
    }

    /**
     * Register the application services.
     *
     * @return void
     */
    public function register()
    {

        $this->app->bind(
            'App\Repositories\MembersRepository',
            'App\Repositories\MembersRepositoryEloquent'
        );
    }
}

ผลลัพธ์การดึงขอ้มูล
{
{
  "header": {
    "code": 200,
    "message": "OK"
  },
  "transaction_id": "105116109 1447929847",
  "total": 7,
  "total_page": 7,
  "count_result": 7,
  "date_current": "2015-11-19 10:44:07",
  "data": {
    "item": [
      {
        "id": 1,
        "name": "xxxx",
        "email": "sdfsdf@tmail.com",
        "created_at": "2015-11-19 09:44:06",
        "updated_at": "2015-11-19 09:44:06"
      },
      {
        "id": 2,
        "name": "xxxx",
        "email": "sdfsdf@tmail.comx",
        "created_at": "2015-11-19 09:44:24",
        "updated_at": "2015-11-19 09:44:24"
      },
      {
        "id": 3,
        "name": "xxxx",
        "email": "sdfsdf@tmail.cox",
        "created_at": "2015-11-19 09:44:55",
        "updated_at": "2015-11-19 09:44:55"
      },
      {
        "id": 4,
        "name": "xxxx",
        "email": "samark@gmail.com",
        "created_at": "2015-11-19 09:53:41",
        "updated_at": "2015-11-19 09:53:41"
      },
      {
        "id": 5,
        "name": "samark chai",
        "email": "samark2@gmail.com",
        "created_at": "2015-11-19 09:54:58",
        "updated_at": "2015-11-19 09:54:58"
      },
      {
        "id": 6,
        "name": "samark chai",
        "email": "samark_chai@gmail.com",
        "created_at": "2015-11-19 09:55:48",
        "updated_at": "2015-11-19 09:55:48"
      },
      {
        "id": 7,
        "name": "samark chai",
        "email": "samark_chaisa@gmail.com",
        "created_at": "2015-11-19 09:56:11",
        "updated_at": "2015-11-19 09:56:11"
      }
    ]
  },
  "process_time": "0.0360"
}
ผลลัทธ์การใส่ข้อมูล
{
  "header": {
    "code": 200,
    "message": "OK"
  },
  "transaction_id": "105116109 1447926971",
  "total": 1,
  "total_page": 1,
  "count_result": 1,
  "date_current": "2015-11-19 09:56:11",
  "name": "samark chai",
  "email": "samark_chaisa@gmail.com",
  "data": {
    "item": {
      "name": "samark chai",
      "email": "samark_chaisa@gmail.com",
      "updated_at": "2015-11-19 09:56:11",
      "created_at": "2015-11-19 09:56:11",
      "id": 7
    }
  },
  "process_time": "0.0280"
}
กรณีข้อมูลซ้ำ
{
  "header": {
    "code": "400",
    "message": "Bad Request"
  },
  "transaction_id": "1447929361",
  "total": 1,
  "count_result": 1,
  "date_current": "2015-11-19 10:36:01",
  "name": "samark chai",
  "email": "samark_chaisa@gmail.com",
  "data": {
    "email": [
      "The email has already been taken."
    ]
  }
}
ในส่วนรายละเอียดจะมาอธิบายภายหลังทีละส่วนครับ



Share on Google Plus

About maxcom

This is a short description in the author block about the author. You edit it by entering text in the "Biographical Info" field in the user admin panel.
    Blogger Comment
    Facebook Comment

0 ความคิดเห็น:

แสดงความคิดเห็น