LaravelでAPIの最初のアプリケーションを作りたいです。私はこれを行うための最善のアプローチがわからないので、私がやろうとしていることを説明しますが、これを別の方法で行う方法についてお気軽にお答えください。
すべてのフロントエンドをjavascriptで記述し、angular.jsなどを使用してAPIのJSON出力を解析したくありません。 LaravelアプリケーションでHTMLビューを作成したい。API用とWeb用の2つのコントローラーを用意することを試みている。 .phpは次のようになります。
# the web controller
Route::controller('user', 'WebUserController');
# the api controller
Route::group(array('prefix' => 'api'), function() {
Route::resource('user', 'UserController');
});
/user
はWebUserController
に連れて行き、/api/user
はUserController
に連れて行ってくれます。ここで、すべてのロジックをAPI UserController
に配置し、そのアクションをWebUserController
から呼び出します。両方のコードは次のとおりです。
class UserController extends BaseController
{
public function show($id)
{
$user = User::find($id);
return Response::json(array('success'=>true,'user'=>$user->toArray()));
}
}
class WebUserController extends UserController
{
public function getView($id)
{
# call the show method of the API's User Controller
$response = $this->show($id);
return View::make('user.view')->with('data', $response->getData());
}
}
WebUserController
では、getData()
で応答のJSONコンテンツを取得できますが、ヘッダーとステータスコードを取得できません(これらはIlluminate\Http\JsonResponse
の保護されたプロパティです)。
私のアプローチは最善ではないかもしれないと思うので、このアプリの作り方を提案します。
[〜#〜] edit [〜#〜]:応答のヘッダーとステータスを取得する方法の質問には ドリュー・ルイス 、しかし、私はまだこれを設計するより良い方法があるかもしれないと思います
リポジトリ/ゲートウェイの設計パターンを使用する必要があります。回答を参照してください here 。
たとえば、ユーザーモデルを扱う場合、最初にユーザーリポジトリを作成します。ユーザーリポジトリのonlyの責任は、データベースと通信することです(CRUD操作を実行する)。このユーザーリポジトリは、共通のベースリポジトリを拡張し、必要なすべてのメソッドを含むインターフェイスを実装します。
class EloquentUserRepository extends BaseRepository implements UserRepository
{
public function __construct(User $user) {
$this->user = $user;
}
public function all() {
return $this->user->all();
}
public function get($id){}
public function create(array $data){}
public function update(array $data){}
public function delete($id){}
// Any other methods you need go here (getRecent, deleteWhere, etc)
}
次に、ユーザーリポジトリインターフェイスを雄弁なユーザーリポジトリにバインドするサービスプロバイダーを作成します。ユーザーリポジトリが必要な場合(IoCコンテナーを介して解決するか、コンストラクターに依存関係を挿入することで)、Laravelは、作成したEloquentユーザーリポジトリのインスタンスを自動的に提供します。 ORMを雄弁以外のものに変更する場合、このサービスプロバイダーを変更するだけでよく、コードベースに他の変更を加える必要はありません。
use Illuminate\Support\ServiceProvider;
class RepositoryServiceProvider extends ServiceProvider {
public function register() {
$this->app->bind(
'lib\Repositories\UserRepository', // Assuming you used these
'lib\Repositories\EloquentUserRepository' // namespaces
);
}
}
次に、ユーザーゲートウェイを作成します。ユーザーゲートウェイの目的は、任意の数のリポジトリと対話し、アプリケーションのビジネスロジックを実行することです。
use lib\Repositories\UserRepository;
class UserGateway {
protected $userRepository;
public function __construct(UserRepository $userRepository) {
$this->userRepository = $userRepository;
}
public function createUser(array $input)
{
// perform any sort of validation first
return $this->userRepository->create($input);
}
}
最後に、ユーザーWebコントローラーを作成します。このコントローラーは、ユーザーゲートウェイと通信します。
class UserController extends BaseController
{
public function __construct(UserGatway $userGateway)
{
$this->userGateway = $userGateway;
}
public function create()
{
$user = $this->userGateway->createUser(Input::all());
}
}
このようにアプリケーションの設計を構造化することにより、いくつかの利点が得られます。アプリケーションが 単一責任原則 (ビジネスロジックをデータベースロジック)。これにより、単体テストと統合テストをはるかに簡単に実行できるようになり、コントローラーを可能な限りスリムにし、将来必要に応じてEloquentを他のデータベースに簡単に交換できるようになります。
たとえば、EloquentからMongoに変更する場合、変更する必要があるのは、サービスプロバイダーのバインドと、UserRepositoryインターフェイスを実装するMongoUserRepositoryの作成だけです。これは、リポジトリがデータベースと通信するonlyものであるためです-それは他に何も知りません。したがって、新しいMongoUserRepositoryは次のようになります。
class MongoUserRepository extends BaseRepository implements UserRepository
{
public function __construct(MongoUser $user) {
$this->user = $user;
}
public function all() {
// Retrieve all users from the mongo db
}
...
}
そして、サービスプロバイダーはUserRepositoryインターフェイスを新しいMongoUserRepositoryにバインドします。
$this->app->bind(
'lib\Repositories\UserRepository',
'lib\Repositories\MongoUserRepository'
);
すべてのゲートウェイを通してUserRepositoryを参照しているので、この変更を行うことにより、Laravelに古いEloquentの代わりに新しいMongoUserRepositoryを使用するように指示しています。他の変更は不要です。
この設計にはリポジトリを使用する必要があります。
例-
//UserRepository Class
class UserRepository {
public function getById($id)
{
return User::find($id);
}
}
// WebUser Controller
class WebUserController extends BaseController {
protected $user;
public function __construct(UserRepository $user)
{
$this->user = $user;
}
public function show($id)
{
return View::make('user.view')->with('data', $this->user->getById($id));
}
}
// APIUser Controller
class UserController extends BaseController {
protected $user;
public function __construct(UserRepository $user)
{
$this->user = $user;
}
public function show($id)
{
$data =>$this->user->getById($id);
return Response::json(array('success'=>true,'user'= $data->toArray()));
}
}
これはJeffrey Wayによるビデオです。彼は優れたLaravel開発者です。このチュートリアルでは、BackboneJSアプリケーションをLaravelでセットアップするRESTfulサービスに接続しています。これよりもましです。定型文をたくさん書くことができますが、ニースのビデオを見て、コーヒーを飲んで学ぶだけです。;)
LaravelのRESTfulコントローラーをチェックアウトします。
http://laravel.com/docs/controllers#restful-controllers
彼らのドキュメントはかなり良い仕事をしています。
しかし、さらに良いのはこのチュートリアルです:
http://code.tutsplus.com/tutorials/laravel-4-a-start-at-a-restful-api-updated--net-29785
回答に関してあなたが抱えている問題に対する回答があります。応答からヘッダー、ステータスコード、データを取得できます。
// your data
$response->getData();
// the status code of the Response
$response->getStatusCode();
// array of headers
$response->headers->all();
// array of headers with preserved case
$response->headers->allPreserveCase();
$ response-> headersはSymfony\Component\HttpFoundation\ResponseHeaderBagで、Symfony\Component\HttpFoundation\HeaderBagを継承します
リポジトリを使用することもお勧めします。あるコントローラーを別のコントローラーから呼び出そうとすると、HMVC(階層モデル-ビュー-コントローラー)と呼ばれるパターンに陥ります。これは、アプリケーション全体が下位モジュールに依存していることを意味します。この場合、APIはデータのリポジトリとして機能します(最初は世界で最悪のことではありません)。
ただし、APIでデータが返される方法の構造を変更すると、それに依存する他のすべてが応答方法を知る必要があります。ログインしたユーザーが返されたユーザーの詳細を表示できるかどうかを確認するための承認チェックが必要で、エラーが発生したとします。
APIでは、403禁止コードといくつかのメタデータを含むResponseオブジェクトを返します。 HTMLコントローラーは、これを処理する方法を知っている必要があります。
これを、例外をスローする可能性のあるリポジトリと比較してください。
public function findById ($id)
{
$user = User::findOrFail($id);
if (Auth::user->hasAccessTo($user)) {
return $user;
} else {
throw new UnauthorizedAccessException('you do not have sufficient access to this resource');
}
}
APIコントローラーは次のようになります。
public function show($id)
{
try {
return $this->user->findById($id);
} catch (UnauthorizedAccessException $e) {
$message = $e->getMessage();
return Response::json('403', ['meta' => ['message' => $message]]));
}
}
HTMLコントローラーは次のようになります。
public function show($id)
{
try {
$user = $this->user->findById($id);
} catch (UnauthorizedAccessException $e) {
Session::flash('error', $e->getMessage());
// Redirect wherever you would like
return Response::redirect('/');
}
}
これにより、非常に再利用可能なコードが得られ、他の動作を変更する心配なしに、コントローラーの実装を個別に変更できます。 this post :でリポジトリパターンの実装方法について詳しく説明しました。インターフェイスを無視して、必要に応じて実装をスキップできます。