หลังจากที่ได้ลองทำการสร้าง api ด้วย laravel ภาคหนึ่งไปแล้ว เราลองมาทำให้มันยากขึ้นกันดีกว่า
ก่อนอื่นผมขอออกตัวไว้ก่อนว่าเน้นให้เห็นภาพรวมก่อน แล้วบทต่อไปผมจะไปเจาะลึกที่ละเนื้อหาครับ
เอาล่ะสำหรับท่านที่ยังไม่ได้ติดตั้ง Laravel ก็ทำการติดตั้งให้เรียบร้อยครับ
Library ที่จะให้
- Prettus\Repository
- Teepluss\Restable
- Benchmark
วิธีการติดตั้ง Prettus Repository คลิ๊กได้ตามลิงค์ครับ สำหรับวิธีการติดตั้ง Restable สามารถทำได้ดังนี้
- install ผ่าน composer โดยใช้คำสั่ง
composer require teepluss/restable - รอสักครู่เพื่อให้ Package ดาวโหลดจนเสร็ดแล้วทำการแก้ไขไฟล์ app.php โดยเพิ่ม
providerTeepluss\Restable\RestableServiceProvider::class,
'Restable' => Teepluss\Restable\Facades\Restable::class,
Library Teepluss\Restable ตัวนี้เพื่อเป็นตัวกลางการ Response handle ครับซึ่งใช้งานได้สะดวกมาก สามารถเรียกใช้งานจากไฟล์ไหนก็ได้ ภายหลังจากการ Load เพราะว่าเป็น Facade ครับ
Library Benchmark สำหรับตัวนี้เอาไว้เพื่อจับเวลาตามชื่อเลยครับ สำหรับการติดตั้งทำได้โดย สร้างไฟล์ตามนี้ครับ
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."
]
}
}
ในส่วนรายละเอียดจะมาอธิบายภายหลังทีละส่วนครับ

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