Symfony FOSRestBundleの使用方法

この投稿では、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)設定

 // app/AppKernel.php class AppKernel extends Kernel { public function registerBundles() { $bundles = array( // ... new JMS\SerializerBundle\JMSSerializerBundle(), new FOS\RestBundle\FOSRestBundle(), ); // ... } }
      
      







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; /** * User * * @ORM\Table(name="user") * @ORM\Entity(repositoryClass="AppBundle\Repository\UserRepository") * @ExclusionPolicy("all") */ class User extends BaseUser { /** * @ORM\Id * @ORM\Column(type="integer") * @ORM\GeneratedValue(strategy="AUTO") * @Exclude */ protected $id; /** * @ORM\Column(type="integer") * @Groups({"user"}) * @Expose */ private $balance = 0; /** * Set balance * * @param integer $balance * * @return User */ public function setBalance($balance) { $this->balance = $balance; return $this; } /** * Get balance * * @return integer */ 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 * @package Backend\UserBundle\Controller */ class UsersController extends FOSRestController { /** * @return \Symfony\Component\HttpFoundation\Response * @View(serializerGroups={"user"}) */ public function getUsersAllAction() { $users = $this->getDoctrine()->getRepository('AppBundle:User')->findAll(); $view = $this->view($users, 200); return $this->handleView($view); } /** * @param $id * @return \Symfony\Component\HttpFoundation\Response * @View(serializerGroups={"user"}) */ 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) {} // "post_user_comment_vote" [POST] /users/{id} public function getUser($id) {} // "get_user" [GET] /users/{id} public function deleteUserAction($id) {} // "delete_user" [DELETE] /users/{id} public function newUserAction($id) {} // "new_user" [GET] /users/{id}/new public function editUserAction($slug, $id) {} // "edit_user" [GET] /users/{id}/edit public function removeUserAction($slug) {} // "remove_user" [GET] /users/{slug}/remove }
      
      





Laravel Resource Controllerを思い出させますよね?



コメントは、このアドレスまたは要求メソッドで、このメソッドまたはそのメソッドが実行されることを示します。

次回、FOSRestBundleを正しく使用する方法について説明します。たとえば、アドレス「/ users / {id} / comments」で特定のユーザーのコメントを表示して、ユーザーデータを作成/更新します。



All Articles