この投稿では、Symfonyのバックエンドを使用して、AngularJSおよびその他のフロントエンドフレームワーク用のRESTfull APIを適切に構築する方法についてお話したいと思います。
そして、おそらく既にご想像のとおり、FOSRestBundleを使用します。これは、バックエンドの実装に役立つ素晴らしいバンドルです。
Angularの操作方法の例はありません。SymfonyFosRestBundleの操作についてのみ説明します。
作業には、EntityからJSONまたはその他の形式にデータをシリアル化し、エンティティの特定のフィールド(ユーザーのリストを取得するメソッドのAPIのパスワードなど)をシリアル化する
JMSSerializerBundleも必要です。 詳細については、ドキュメントをご覧ください。
インストールと構成1)composer.jsonで必要な依存関係をダウンロードします"friendsofsymfony/rest-bundle": "^1.7",
"jms/serializer-bundle": "^1.1"
2)設定
config.ymlを編集します
まず、FOSRestBundleを構成します
fos_rest: body_listener: true view: view_response_listener: true serializer: serialize_null: true body_converter: enabled: true format_listener: rules: - { path: '^/api', priorities: ['json'], fallback_format: json, exception_fallback_format: html, prefer_extension: true } - { path: '^/', priorities: [ 'html', '*/*'], fallback_format: html, prefer_extension: true }
body_listenerには、ユーザーがAccept- *ヘッダーに基づいて必要とする応答形式を追跡するEventListenerが含まれています
view_response_listener-この設定により、特定のリクエストに対して単にビューを返すことができます
serializer.serialize_null-この設定は、すべてを設定したりfalseに設定したりしない場合、すべてのようにNULLも
シリアル化することを意味し、nullを持つすべてのフィールドはサーバー応答に表示されません。
PS:
lowadkaを思い出させて
くれてありがとうbody_converter.rules-特定のアドレスを対象とした設定用の配列が含まれます。この例では、
/ apiプレフィックスを持つすべてのリクエストに対してJSONを返します。その他の場合はすべてhtmlを返します。
それでは、JMSSerializeBundleのセットアップを始めましょう。
jms_serializer: property_naming: separator: _ lower_case: true metadata: cache: file debug: "%kernel.debug%" file_cache: dir: "%kernel.cache_dir%/serializer" directories: FOSUserBundle: namespace_prefix: FOS\UserBundle path: %kernel.root_dir%/config/serializer/FosUserBundle AppBundle: namespace_prefix: AppBundle path: %kernel.root_dir%/config/serializer/AppBundle auto_detection: true
jms_serializer.metadata.directoriesを使用して、特定のクラス(エンティティ)の構成がそこにあることを
シリアライザーに伝えることは意味があります:)
ユーザーのリスト全体を表示する必要があることに同意しましょう。私は個人的に自分のプロジェクトでFosUserBundleを使用していますが、これが私の本質です。
<?php namespace AppBundle\Entity; use JMS\Serializer\Annotation\Expose; use JMS\Serializer\Annotation\Groups; use JMS\Serializer\Annotation\Exclude; use JMS\Serializer\Annotation\VirtualProperty; use JMS\Serializer\Annotation\ExclusionPolicy; use Doctrine\ORM\Mapping as ORM; use FOS\UserBundle\Model\User as BaseUser; use FOS\UserBundle\Model\Group; class User extends BaseUser { protected $id; private $balance = 0; public function setBalance($balance) { $this->balance = $balance; return $this; } public function getBalance() { return $this->balance; } }
メインのFosUserBundleモデルを継承するこのエンティティの例を示します。 JmsSerializerBundleに対して両方のクラスを個別に構成する必要があるため、これは重要です。
jms_serializer.metadata.directoriesに戻ります。
directories: FOSUserBundle: namespace_prefix: FOS\UserBundle path: %kernel.root_dir%/config/serializer/FosUserBundle AppBundle: namespace_prefix: AppBundle path: %kernel.root_dir%/config/serializer/AppBundle
ここでは、AppBundleクラスについては、app / config / serializer / AppBundleでシリアル化の構成を検索し、app / config / serializer / FosUserBundleでFosUserBundleを検索することを示しています。
クラスの構成は自動的に次の形式になります。
クラスAppBundle \ Entity \ User-app / config / serializer / AppBundle / Entity.Userの場合(Yml | xml | php)
基本モデルクラスFosUserBundleの場合-app / config / serializer / FosUserBundle / Model.User。(Yml | xml | php)
個人的には、YAMLを使用することを好みます。 最後に、このクラスまたはそのクラスを構成するために必要な方法をJMSSerializerに伝え始めます。
app / config / serializer / AppBundle / Entity.User.yml AppBundle\Entity\User: exclusion_policy: ALL properties: balance: expose: true
app / config / serializer / FosUserBundle / Model.User.yml FOS\UserBundle\Model\User: exclusion_policy: ALL group: user properties: id: expose: true username: expose: true email: expose: true balance: expose: true
そのように、1人のユーザーからデータを受信したときに、サーバーからの次の応答形式について確認したいことについて話し合うことができました。
{"id":1,"username":"admin","email":"admin","balance":0}
原則として、この構成は登録する必要はなく、サーバーはエンティティに関するすべてのデータを返します。 この場合にのみ、たとえばパスワードなど、多くのものを表示するのは非論理的です。 したがって、この例では、このような実装を実証する必要があると考えました。
それでは、コントローラーの作成を始めましょう。まず、ルートを作成します。
backend_user: resource: "@BackendUserBundle/Resources/config/routing.yml" prefix: /api
/ apiに注意してください-追加することを忘れないでください。ただし、変更する場合は、config.ymlのfos_restの構成を変更する必要があります。BackendUserBundle / Resources / config / routing.yml自体:
backend_user_users: type: rest resource: "@BackendUserBundle/Controller/UsersController.php" prefix: /v1
これで、コントローラー自体の作成を開始できます。
<?php namespace Backend\UserBundle\Controller; use AppBundle\Entity\User; use FOS\RestBundle\Controller\FOSRestController; use FOS\RestBundle\Controller\Annotations as Rest; use FOS\RestBundle\Controller\Annotations\View; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; class UsersController extends FOSRestController { public function getUsersAllAction() { $users = $this->getDoctrine()->getRepository('AppBundle:User')->findAll(); $view = $this->view($users, 200); return $this->handleView($view); } public function getUserAction($id) { $user = $this->getDoctrine()->getRepository('AppBundle:User')->find($id); if (!$user instanceof User) { throw new NotFoundHttpException('User not found'); } $view = $this->view($user, 200); return $this->handleView($view); } }
FOS \ RestBundle \ Controller \ FOSRestControllerから継承していることに注意してください。
ちなみに、おそらく
Viewアノテーション(serializerGroups = {"user"})に気付いたでしょう。
事実は、なぜなら App \ Entity \ Userのデータと、他のすべてのフィールドが格納されているメインのFosUserBundleモデルの両方を表示するには、特定のグループ(この場合は「user」)を作成する必要があります。
したがって、2つのアクションgetUserActionとgetUsersAllActionがあります。 これで、コントローラーメソッドの名前の特異性の本質を理解できます。
すべてのルートをデバッグしましょう:
$ app / console debug:ルート| grep api
取得するもの:
get_users_all GET ANY ANY /api/v1/users/all.{_format} get_user GET ANY ANY /api/v1/users/{id}.{_format}
新しいメソッドを使用した次の例を検討してください。
<?php class UsersComment extends Controller { public function postUser($id) {}
Laravel Resource Controllerを思い出させますよね?
コメントは、このアドレスまたは要求メソッドで、このメソッドまたはそのメソッドが実行されることを示します。
次回、FOSRestBundleを正しく使用する方法について説明します。たとえば、アドレス「/ users / {id} / comments」で特定のユーザーのコメントを表示して、ユーザーデータを作成/更新します。