Symfony2 рдкрд░ рдПрдХ рд░реАрд╕реНрдЯ рдПрдкреАрдЖрдИ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдирд╛: рд╕рд╣реА рддрд░реАрдХрд╛

рдмрд╛рдХреА
REST API рдмрдирд╛рдирд╛ рдХреЛрдИ рдЖрд╕рд╛рди рдХрд╛рдо рдирд╣реАрдВ рд╣реИред рдирд╣реАрдВ, рдЧрдВрднреАрд░рддрд╛ рд╕реЗ! рдпрджрд┐ рдЖрдк рдПрдкреАрдЖрдИ рдХреЛ рд╕рд╣реА рддрд░реАрдХреЗ рд╕реЗ рд▓рд┐рдЦрдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рддреЛ рдЖрдкрдХреЛ рдмрд╣реБрдд рдХреБрдЫ рд╕реЛрдЪрдирд╛ рд╣реЛрдЧрд╛, рдпрд╣ рддрдп рдХрд░рдирд╛ рд╣реЛрдЧрд╛ рдХрд┐ рд╡реНрдпрд╛рд╡рд╣рд╛рд░рд┐рдХ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП, рдпрд╛ рдПрдкреАрдЖрдИ рдкрд╛рдЧрд▓ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред REST рдХреЗрд╡рд▓ GET, POST, PUT рдФрд░ Delete рдирд╣реАрдВ рд╣реИред рд╡реНрдпрд╡рд╣рд╛рд░ рдореЗрдВ, рдЖрдкрдХреЗ рдкрд╛рд╕ рд╕рдВрд╕рд╛рдзрдиреЛрдВ рдХреЗ рдмреАрдЪ рдмрд╛рддрдЪреАрдд рд╣реЛ рд╕рдХрддреА рд╣реИ, рдЖрдкрдХреЛ рд╕рдВрд╕рд╛рдзрдиреЛрдВ рдХреЛ рдХрд╣реАрдВ рдФрд░ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдПрдХ рдкреЗрдбрд╝ рдХреЗ рдЕрдВрджрд░), рдпрд╛ рдЖрдк рдПрдХ рд╡рд┐рд╢рд┐рд╖реНрдЯ рд╕рдВрд╕рд╛рдзрди рдорд╛рди рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВред

рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ рд╡рд╣ рд╕рдм рдХреБрдЫ рд╣реИ рдЬреЛ рдореИрдВрдиреЗ рдЗрд╕ рдЙрджреНрджреЗрд╢реНрдп рдХреЗ рд▓рд┐рдП Symfony2 , FOSRestBundle , NelmioApiDocBundle рдФрд░ Propel рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╡рд┐рднрд┐рдиреНрди API рд╕реЗрд╡рд╛рдУрдВ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдХреЗ рд╕реАрдЦрд╛ред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд╣рдо рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдПрдкреАрдЖрдИ рдмрдирд╛рдПрдВрдЧреЗред

рдХреНрдпрд╛ рдЖрдк рдмреЛрд▓рддреЗ рд╣реИрдВ ...?


API рдХреНрд▓рд╛рдЗрдВрдЯ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВред рдЙрдиреНрд╣реЗрдВ рдкрддрд╛ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП рдХрд┐ рдЖрдкрдХреА рдПрдкреАрдЖрдИ рд╕реЗрд╡рд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХреИрд╕реЗ рдХрд┐рдпрд╛ рдЬрд╛рдП, рдФрд░ рдЙрдЪреНрдЪ рдЧреБрдгрд╡рддреНрддрд╛ рд╡рд╛рд▓реЗ рдкреНрд░рд▓реЗрдЦрди рдЗрд╕реЗ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХрд╛ рдПрдХ рдЕрдЪреНрдЫрд╛ рддрд░реАрдХрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рд▓реЗрдЦ рдХреЗ рдЕрдВрдд рдореЗрдВ рдЗрд╕рд╕реЗ рднреА рдЕрдзрд┐рдХред

рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдЖрдкрдХреЛ рдпрд╣ рднреА рдкрддрд╛ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП рдХрд┐ рдЧреНрд░рд╛рд╣рдХреЛрдВ рдХреЗ рд╕рд╛рде рд╕рдВрд╡рд╛рдж рдХреИрд╕реЗ рдХрд░реЗрдВ, рдФрд░ HTTP рдкреНрд░реЛрдЯреЛрдХреЙрд▓, рдЕрд░реНрдерд╛рддреН рд╣реЗрдбрд░ рд╕реНрд╡реАрдХрд╛рд░ рдХрд░реЗрдВ , рдЗрд╕рдореЗрдВ рд╣рдорд╛рд░реА рдорджрдж рдХрд░реЗрдВрдЧреЗред рд╕рдВрдХреНрд╖реЗрдк рдореЗрдВ, рдЧреНрд░рд╛рд╣рдХ рдПрдХ рд╣реЗрдбрд░ рднреЗрдЬреЗрдВрдЧреЗ рдЬрд┐рд╕рдХреЗ рд╕рд╛рде рд╡реЗ рдЙрд╕ рдбреЗрдЯрд╛ рдкреНрд░рд╛рд░реВрдк рдХреЗ рдкреНрд░рдХрд╛рд░ рдХреЛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛ рдЪрд╛рд╣реЗрдВрдЧреЗ рдЬрд┐рд╕реЗ рд╡реЗ рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВред

рд╣рд╛рд▓рд╛рдБрдХрд┐, FOSRestBundle рдореЗрдВ рдЖрдкрдХреЗ рд▓рд┐рдП рд╕рдм рдХреБрдЫ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред рдЗрд╕ рднрд╛рдЧ рдХреЛ рдЯреНрд░реИрдХ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЖрдкрдХреЛ рдЙрди рд╕реЗрдЯрд┐рдВрдЧреНрд╕ рдореЗрдВ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рдирд╛ рд╣реЛрдЧрд╛ рдЬреЛ рдЖрдк рд╕рдорд░реНрдерди рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВред рд╕рдмрд╕реЗ рдЕрдзрд┐рдХ рд╕рдВрднрд╛рд╡рдирд╛ рд╣реИ, рдЖрдк рдЖрдорддреМрд░ рдкрд░ JSON рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдпрджрд┐ рдЖрдк рд╢рдмреНрджрд╛рд░реНрде рдХреА рд╕рдорд╕реНрдпрд╛ рдореЗрдВ рдЖрддреЗ рд╣реИрдВ, рддреЛ рдЖрдк XML рднреЗрдЬреЗрдВрдЧреЗред рдЗрд╕ рд╣рд┐рд╕реНрд╕реЗ рдХреЛ рдмрд╛рдж рдореЗрдВ рднреА рдЙрдЬрд╛рдЧрд░ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред

рдХреНрдпрд╛ рдорд┐рд▓рддрд╛ рд╣реИ?


HTTP GET рд╡рд┐рдзрд┐ idempotent рд╣реИред рдЗрд╕рдХрд╛ рдорддрд▓рдм рд╣реИ рдХрд┐ рдЗрд╕ рдкрджреНрдзрддрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЖрдк рдХрд┐рддрдиреА рдмрд╛рд░ рдбреЗрдЯрд╛ рдХрд╛ рдЕрдиреБрд░реЛрдз рдХрд░рддреЗ рд╣реИрдВ, рдЖрдкрдХреЛ рдПрдХ рд╣реА рдбреЗрдЯрд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред рдЙрдиреНрд╣реЗрдВ рдХреЛрдИ рдмрджрд▓рд╛рд╡ рдирд╣реАрдВ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред рд╕рдВрд╕рд╛рдзрди рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП GET рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ: рдПрдХ рд╕рдВрдЧреНрд░рд╣ рдпрд╛ рдПрдХ рдЕрд▓рдЧ рд╕рдВрд╕рд╛рдзрдиред Symfony2 рдореЗрдВ, рд░реВрдЯрд┐рдВрдЧ рдирд┐рдпрдо рд╡рд┐рд╡рд░рдг рдХреБрдЫ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦреЗрдЧрд╛:
# src/Acme/DemoBundle/Resources/config/routing.yml acme_demo_user_all: pattern: /users defaults: { _controller: AcmeDemoBundle:User:all, _format: ~ } requirements: _method: GET acme_demo_user_get: pattern: /users/{id} defaults: { _controller: AcmeDemoBundle:User:get, _format: ~ } requirements: _method: GET id: "\d+" 


UserController рд╡рд░реНрдЧ рдореЗрдВ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХреЛрдб рд╢рд╛рдорд┐рд▓ рд╣реЛрдВрдЧреЗ:
 <?php namespace Acme\DemoBundle\Controller; use Acme\DemoBundle\Model\User; use Acme\DemoBundle\Model\UserQuery; use FOS\RestBundle\Controller\Annotations as Rest; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; class UserController { /** * @Rest\View */ public function allAction() { $users = UserQuery::create()->find(); return array('users' => $users); } /** * @Rest\View */ public function getAction($id) { $user = UserQuery::create()->findPk($id); if (!$user instanceof User) { throw new NotFoundHttpException('User not found'); } return array('user' => $user); } } 


* * () рд╡рд┐рдзрд┐рдпреЛрдВ рдореЗрдВ рдкреИрд░рд╛рдореАрдЯрд░ рдХрдирд╡рд░реНрдЯрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рдмрдЬрд╛рдп, рдореБрдЭреЗ рд╣рдореЗрд╢рд╛ рд╡рд╕реНрддреБрдУрдВ рдХреЛ рд╕реНрд╡рдпрдВ рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред рдмрд╛рдж рдореЗрдВ рдореИрдВ рд╕рдордЭрд╛рддрд╛ рд╣реВрдБ рдХрд┐ рдХреНрдпреЛрдВ, рд▓реЗрдХрд┐рди рдЕрднреА рдХреЗ рд▓рд┐рдП, рдмрд╕ рдореБрдЭ рдкрд░ рд╡рд┐рд╢реНрд╡рд╛рд╕ рдХрд░реЛ, рдпрд╣ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдмреЗрд╣рддрд░ рд╣реИред

рдЧреНрд░рд╛рд╣рдХреЛрдВ рдХреЗ рд▓рд┐рдП рд╕реНрдерд┐рддрд┐ рдХреЛрдб рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИ, рдЗрд╕рд▓рд┐рдП рдпрджрд┐ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдореМрдЬреВрдж рдирд╣реАрдВ рд╣реИ, рддреЛ NotFoundHttpException рдЕрдкрд╡рд╛рдж рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ, рдЬреЛ рд╕реНрдерд┐рддрд┐ рдХреЛрдб 404 рдХреЗ рд╕рд╛рде рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рд▓реМрдЯрд╛рдПрдЧрд╛ред

рджреГрд╢реНрдп рдПрдиреЛрдЯреЗрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдП, рдЖрдк рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЛ рд╡рд╛рдВрдЫрд┐рдд рдкреНрд░рд╛рд░реВрдк рдореЗрдВ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рддреЗ рд╣реИрдВ, рдЬрд┐рд╕реЗ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдПрдХреНрд╕реЗрдбрд░ рд╢реАрд░реНрд╖рдХ рдореЗрдВ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рддрд╛ рд╣реИред рдПрдиреЛрдЯреЗрд╢рди рдХреЗ рд▓рд┐рдП рдПрдХ рдЙрдкрдирд╛рдо (рд░реЗрд╕реНрдЯ) рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдПрдХ рдЪрд╛рд▓ рд╣реИ рдЬреЛ рд╡реНрдпреВ рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЗ рд╕рд╛рде рд╕рдВрдШрд░реНрд╖ рд╕реЗ рдмрдЪрдиреЗ рдореЗрдВ рдорджрдж рдХрд░реЗрдЧрд╛, рдЬрд┐рд╕рдХреА рдЪрд░реНрдЪрд╛ рд╣рдо рдмрд╛рдж рдореЗрдВ рдХрд░реЗрдВрдЧреЗред рд╕реАрдзреЗ рд╢рдмреНрджреЛрдВ рдореЗрдВ рдХрд╣реЗрдВ, рдПрдиреЛрдЯреЗрд╢рди рдЗрд╕ рд╡рд░реНрдЧ рдХреЛ рд╕рдВрджрд░реНрднрд┐рдд рдХрд░рддреЗ рд╣реИрдВред рдпрд╣ рдХреЗрд╡рд▓ рд╕реНрд╡рд╛рдж рдХреА рдмрд╛рдд рд╣реИ, рдПрдиреЛрдЯреЗрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рд╣реИ рдпрд╛ рдирд╣реАрдВред

рдФрд░ рдЕрдВрдд рдореЗрдВ, AllAction () рд╡рд┐рдзрд┐ред рдпрд╣ getAction рдХреЗ рд╕рдорд╛рди рд╡реНрдпрд╡рд╣рд╛рд░ рдХрд░рддрд╛ рд╣реИ: рдЖрдкрдХреЛ рдХреЗрд╡рд▓ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдХрд╛ рдЪрдпрди рдорд┐рд▓рддрд╛ рд╣реИ рдФрд░ рдЗрд╕реЗ рд╡рд╛рдкрд╕ рдХрд░рдирд╛ рд╣реЛрддрд╛ рд╣реИред

рдПрдХ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдСрдмреНрдЬреЗрдХреНрдЯ рдореЗрдВ 4 рдЧреБрдг рд╣реИрдВ: рдЖрдИрдбреА, рдИрдореЗрд▓, рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдирд╛рдо рдФрд░ рдкрд╛рд╕рд╡рд░реНрдбред рд╕рдВрднрд╡рддрдГ рд╕рд╛рдорд╛рдиреНрдп рдЬреНрдЮрд╛рди рдЖрдкрдХреЛ рдПрдкреАрдЖрдИ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдХреЛ рдореБрдлреНрдд рдореЗрдВ рдкрд╛рд╕рд╡рд░реНрдб рджреЗрдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рдирд╣реАрдВ рджреЗрдЧрд╛ред рдЗрд╕ рд╕рдВрдкрддреНрддрд┐ рдХреЛ рдмрд╛рд╣рд░ рдХрд░рдиреЗ рдХрд╛ рд╕рдмрд╕реЗ рдЖрд╕рд╛рди рддрд░реАрдХрд╛ рд╣реИ рдЬрдм рдПрдХ рд╕реАрд░рд┐рдпрд▓ рдХреЛ рд╕реЗрдЯ рдХрд░рдХреЗ рдХрд┐рд╕реА рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЛ рдХреНрд░рдорд╛рдВрдХрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред YAML рдкреНрд░рд╛рд░реВрдк рдореЗрдВ рдЙрджрд╛рд╣рд░рдг рд╕реЗрдЯрдЕрдк:
 # In Propel, the most part of the code is located in base classes # src/Acme/DemoBundle/Resources/config/serializer/Model.om.BaseUser.yml Acme\DemoBundle\Model\om\BaseUser: exclusion_policy: ALL properties: id: expose: true username: expose: true email: expose: true 


рдореИрдВ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд░реВрдк рд╕реЗ рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЗ рд╕рднреА рдЧреБрдгреЛрдВ рдХреЛ рдмрд╛рд╣рд░ рдХрд░рдиреЗ рдХреА рд╕рд▓рд╛рд╣ рджреЗрддрд╛ рд╣реВрдВ, рдФрд░ рдЖрд╡рд╢реНрдпрдХ рд▓реЛрдЧреЛрдВ рдХреЛ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рдЬреЛрдбрд╝рд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред рдпрд╣ рдмрдбрд╝реА рд╡рд╕реНрддреБрдУрдВ рдкрд░ рдЕрдзрд┐рдХ рд▓рдЪреАрд▓рд╛рдкрди рджреЗрддрд╛ рд╣реИред 4 рдЧреБрдгреЛрдВ рдХреЗ рд╕рд╛рде рдЗрд╕рдХрд╛ рдмрд╣реБрдд рдЕрд░реНрде рдирд╣реАрдВ рд╣реИ, рд▓реЗрдХрд┐рди рдлрд┐рд░ рднреА рдЗрд╕ рд░рдгрдиреАрддрд┐ рдХрд╛ рдкрд╛рд▓рди рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдВ, рдпрд╣ рд╣реИ рдХрд┐ рдЕрдВрдд рдореЗрдВ рдлрд╝рд╛рдпрд░рд╡реЙрд▓ рдХреЛ рдХреИрд╕реЗ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд┐рдпрд╛ рдЬрд╛рдПред

рдкрд░рд┐рдгрд╛рдорд╕реНрд╡рд░реВрдк, рд╣рдореЗрдВ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд JSON рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдорд┐рд▓рддреА рд╣реИ:
 { "user": { "id": 999, "username": "xxxx", "email": "xxxx@example.org" } } 


рд╕рд░рд▓, рд╕рд╣реА? рд▓реЗрдХрд┐рди рдЖрдкрдХреЛ рд╕рдВрднрд╡рддрдГ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдХреЛ рдмрдирд╛рдиреЗ, рд╕рдВрд╢реЛрдзрд┐рдд рдХрд░рдиреЗ рдпрд╛ рд╣рдЯрд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреА, рдФрд░ рдпрд╣ рдЕрдЧрд▓реЗ рдЕрдзреНрдпрд╛рдп рдХреЗ рд▓рд┐рдП рд╡рд┐рд╖рдп рд╣реЛрдЧрд╛ред

рдЗрд╕реЗ рдкреЛрд╕реНрдЯ рдХрд░реЗрдВ


рдПрдХ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдмрдирд╛рдиреЗ рдореЗрдВ HTTP POST рд╡рд┐рдзрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рд╢рд╛рдорд┐рд▓ рд╣реИред рд▓реЗрдХрд┐рди рдЖрдк рдбреЗрдЯрд╛ рдХреИрд╕реЗ рдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдВрдЧреЗ? рдЖрдк рдЙрдирдХреА рдЬрд╛рдВрдЪ рдХреИрд╕реЗ рдХрд░реЗрдВрдЧреЗ? рдФрд░ рдЖрдк рдПрдХ рдирдИ рд╡рд╕реНрддреБ рдХреИрд╕реЗ рдмрдирд╛рдПрдВрдЧреЗ? рдЗрди рддреАрди рд╕рд╡рд╛рд▓реЛрдВ рдХреЗ рдПрдХ рд╕реЗ рдЕрдзрд┐рдХ рдЙрддреНрддрд░ рдпрд╛ рд░рдгрдиреАрддрд┐ рд╣реИрдВред

рдЖрдк рдХреНрд░рдорд╛рдВрдХрд┐рдд рдЗрдирдкреБрдЯ рд╕реЗ рдПрдХ рдлреЙрд░реНрдо рдСрдмреНрдЬреЗрдХреНрдЯ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдбреАрд╕реЗрд░рд┐рдПрд▓рд╛рдЗрдЬрд╝реЗрд╢рди рддрдВрддреНрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдмреЗрдВрдЬрд╛рдорд┐рди рдирд╛рдо рдХрд╛ рдПрдХ рд▓рдбрд╝рдХрд╛ рдПрдХ рдлреЙрд░реНрдо рдбреЗрдЬрд┐рд▓рд╛рдЗрдЬрд╝рд░ рдкрд░ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред рдпрд╣ рд╡рд┐рдзрд┐ Serializer рдШрдЯрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рд╕реЗ рдХреЗрд╡рд▓ рдереЛрдбрд╝рд╛ рдЕрд▓рдЧ рд╣реИ, рд▓реЗрдХрд┐рди рдпрд╣ рд╕рд░рд▓ рд▓рдЧрддрд╛ рд╣реИред

рдореИрдВ рд╕рд┐рдореНрдлрдиреА рд╕реЗ рдХреВрд▓ рдлреЙрд░реНрдо рдШрдЯрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдПрдХ рд╣реА рдмрд╛рд░ рдореЗрдВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд░рддрд╛ рд╣реВрдВред рдПрдХ рдирдпрд╛ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдлрд╛рд░реНрдо рд╡рд░реНрдЧ рд▓рд┐рдЦреЗрдВред PropelBundle рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЖрдк рдкреНрд░реЛрдкреЗрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ : рдлрд╝реЙрд░реНрдо: рдХрдорд╛рдВрдб рдХрдорд╛рдВрдб рдЙрддреНрдкрдиреНрди рдХрд░реЗрдВ :
 php app/console propel:form:generate @AcmeDemoBundle User 


рдпрд╣ рдХрдорд╛рдВрдб рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдлреЙрд░реНрдо рдХреНрд▓рд╛рд╕ рдмрдирд╛рдПрдЧреА:
 <?php namespace Acme\DemoBundle\Form\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\OptionsResolver\OptionsResolverInterface; class UserType extends AbstractType { /** * {@inheritdoc} */ public function buildForm(FormBuilderInterface $builder, array $options) { $builder->add('username'); $builder->add('email', 'email'); $builder->add('password', 'password'); } /** * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'data_class' => 'Acme\DemoBundle\Model\User', 'csrf_protection' => false, )); } /** * {@inheritdoc} */ public function getName() { return 'user'; } } 


рдореБрдЭреЗ рдЕрдкрдиреЗ рд╣рд╛рдереЛрдВ рд╕реЗ рдХреБрдЫ рдХрд░рдирд╛ рдерд╛: рдИрдореЗрд▓ рдФрд░ рдкрд╛рд╕рд╡рд░реНрдб рдкреНрд░рдХрд╛рд░, рдФрд░ рдореИрдВрдиреЗ рд╕реАрдПрд╕рдЖрд░рдПрдл рд╕реБрд░рдХреНрд╖рд╛ рднреА рдмрдВрдж рдХрд░ рджреАред REST API рдореЗрдВ, рдЖрдк рд╕рдмрд╕реЗ рдЕрдзрд┐рдХ рд╕реБрд░рдХреНрд╖рд╛ рдкрд░рдд рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ, рдЬреИрд╕реЗ OAuthред рдПрдХ REST рд╕рдВрджрд░реНрдн рдореЗрдВ CSRF рд╕реБрд░рдХреНрд╖рд╛ рд╣реЛрдиреЗ рд╕реЗ рдХреЛрдИ рдорддрд▓рдм рдирд╣реАрдВ рд╣реИред

рдЕрдм рд╣рдореЗрдВ рд╕рддреНрдпрд╛рдкрди рдирд┐рдпрдо рдЬреЛрдбрд╝рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдФрд░ рдЙрдкрдпреБрдХреНрдд рдШрдЯрдХ рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рдж , рдпрд╣ рдЖрд╕рд╛рди рд╣реЛрдЧрд╛ред рдореИрдВ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЗрд╕ рдШрдЯрдХ рдХреЛ рдкрд╕рдВрдж рдХрд░рддрд╛ рд╣реВрдВ, рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рд╕рднреА рдЖрдиреЗ рд╡рд╛рд▓реЗ рдбреЗрдЯрд╛ рдХреЛ рд╕реБрд░рдХреНрд╖рд┐рдд рддрд░реАрдХреЗ рд╕реЗ рдЬрд╛рдВрдЪрдирд╛ рдмрд╣реБрдд рдЖрд╕рд╛рди рдмрдирд╛рддрд╛ рд╣реИред

рд╣рдорд╛рд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ рд▓реМрдЯрдХрд░, рдореИрдВ YAML рдореЗрдВ рд╕рддреНрдпрд╛рдкрди рдирд┐рдпрдореЛрдВ рдХрд╛ рд╡рд░реНрдгрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, рд▓реЗрдХрд┐рди рдХреЛрдИ рднреА рдЖрдкрдХреЛ рдЕрдкрдиреА рдкрд╕рдВрдж рдореЗрдВ рдкреНрд░рддрд┐рдмрдВрдзрд┐рдд рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИред рдпрд╣рд╛рдБ рдПрдХ рдЙрджрд╛рд╣рд░рдг рд╣реИ:
 # src/Acme/DemoBundle/Resources/config/validation.yml Acme\DemoBundle\Model\User: getters: username: - NotBlank: email: - NotBlank: - Email: password: - NotBlank: 


рдЖрдЗрдП рдЕрдм рдХрдВрдЯреНрд░реЛрд▓рд░ рдореЗрдВ рдПрдХ рд╡рд┐рдзрд┐ рд▓рд┐рдЦрддреЗ рд╣реИрдВ:
 <?php // ... public function newAction() { return $this->processForm(new User()); } 


рдПрдХ рдФрд░ рдЯрд┐рдкред рдЕрдкрдиреЗ рдкреНрд░рдкрддреНрд░реЛрдВ рдХреЛ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╣рдореЗрд╢рд╛ рдПрдХ рдЕрд▓рдЧ рд╡рд┐рдзрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВред рддрдм рдЖрдк рдЦреБрдж рдХреЛ рдзрдиреНрдпрд╡рд╛рдж рджреЗрдВред ProcessForm () рд╡рд┐рдзрд┐ рдХреБрдЫ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрддреА рд╣реИ:
 // ... private function processForm(User $user) { $statusCode = $user->isNew() ? 201 : 204; $form = $this->createForm(new UserType(), $user); $form->bind($this->getRequest()); if ($form->isValid()) { $user->save(); $response = new Response(); $response->setStatusCode($statusCode); $response->headers->set('Location', $this->generateUrl( 'acme_demo_user_get', array('id' => $user->getId()), true // absolute ) ); return $response; } return View::create($form, 400); } 


рд╕рдВрдХреНрд╖реЗрдк рдореЗрдВ, рдЖрдк рдПрдХ рдкреНрд░рдкрддреНрд░ рдмрдирд╛рддреЗ рд╣реИрдВ, рдЗрд╕рдХреЗ рд▓рд┐рдП рдЖрдиреЗ рд╡рд╛рд▓реЗ рдбреЗрдЯрд╛ рдХреЛ рдмрд╛рдВрдзрддреЗ рд╣реИрдВ, рдФрд░ рдпрджрд┐ рд╕рднреА рдбреЗрдЯрд╛ рдорд╛рдиреНрдп рд╣реИрдВ, рддреЛ рдЖрдк рдЕрдкрдиреЗ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЛ рд╕рд╣реЗрдЬрддреЗ рд╣реИрдВ рдФрд░ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рд╡рд╛рдкрд╕ рдХрд░рддреЗ рд╣реИрдВред рдпрджрд┐ рдХреБрдЫ рдЧрд▓рдд рд╣реЛрддрд╛ рд╣реИ, рддреЛ рдЖрдк рдлреЙрд░реНрдо рдХреЗ рд╕рд╛рде 400 рдХреЛрдб рд╡рд╛рдкрд╕ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рддреНрд░реБрдЯрд┐ рд╕рдВрджреЗрд╢ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкреНрд░рдкрддреНрд░ рд╡рд░реНрдЧ рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рдХреНрд░рдордмрджреНрдз рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рдпрд╣рд╛рдВ рдРрд╕реА рддреНрд░реБрдЯрд┐ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдорд┐рд▓ рд╕рдХрддреА рд╣реИ:
 { "children": { "username": { "errors": [ "This value should not be blank." ] } } } 


рдиреЛрдЯ: рдпрд╣рд╛рдВ рдЬреЛ рджреГрд╢реНрдп рд╡рд░реНрдЧ рд╣рдо рджреЗрдЦрддреЗ рд╣реИрдВ, рд╡рд╣реА рдирд╣реАрдВ рд╣реИ рдЬреЛ рд╣рдо рдПрдиреЛрдЯреЗрд╢рди рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ, рдпрд╣реА рдХрд╛рд░рдг рд╣реИ рдХрд┐ рдореИрдВрдиреЗ рдЙрдирдХреЗ рд▓рд┐рдП рдПрдХ рдЙрдкрдирд╛рдо рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рд╣реИред FOSRestBundle рдкреНрд░рд▓реЗрдЦрди рдореЗрдВ "рджреГрд╢реНрдп рдкрд░рдд" рдЕрдзреНрдпрд╛рдп рдореЗрдВ рдЗрд╕ рд╡рд░реНрдЧ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдФрд░ рдкрдврд╝реЗрдВред

рдлреЙрд░реНрдо рдХреЗ рдирд╛рдо рдХреЛ рдкрд╛рд╕ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рднреА рдпрд╣ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИред рдЖрдорддреМрд░ рдкрд░, рдЧреНрд░рд╛рд╣рдХ рдЖрдкрдХреЛ рдХреБрдЫ рдЗрд╕ рддрд░рд╣ рд╕реЗ рднреЗрдЬреЗрдВрдЧреЗ:
 { "user": { "username": "foo", "email": "foo@example.org", "password": "hahaha" } } 


рдЖрдк рдЗрд╕ рд╡рд┐рдзрд┐ рдХреЛ рдХрд░реНрд▓ рдХреЗ рд╕рд╛рде рдХреЙрд▓ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:
 curl -v -H "Accept: application/json" -H "Content-type: application/json" -X POST -d '{"user":{"username":"foo", "email": "foo@example.org", "password": "hahaha"}}' http://example.com/users 


рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░реЗрдВ рдХрд┐ рдЖрдкрдиреЗ FOSRestBundle рд╕реЗрдЯрд┐рдВрдЧ рдореЗрдВ body_listener рдкреИрд░рд╛рдореАрдЯрд░ рдХреЗ рд▓рд┐рдП рд╕рд╣реА рд╕реЗрдЯ рдХрд┐рдпрд╛ рд╣реИред рдпрд╣ рдкреИрд░рд╛рдореАрдЯрд░ рдЖрдкрдХреЛ JSON, XML рдФрд░ рдЕрдиреНрдп рдХреЗ рдкреНрд░рд╛рд░реВрдк рдореЗрдВ рдбреЗрдЯрд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред рдлрд┐рд░ рд╕реЗ, рд╕рдм рдХреБрдЫ рдмреЙрдХреНрд╕ рд╕реЗ рдмрд╛рд╣рд░ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред

рдЬреИрд╕рд╛ рдХрд┐ рдореИрдВрдиреЗ рдкрд╣рд▓реЗ рдХрд╣рд╛ рдерд╛, рдЕрдЧрд░ рд╕рдм рдХреБрдЫ рдареАрдХ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рдЖрдк рдЕрдкрдиреЗ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ ($ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛-> рдкреНрд░реЛрдкреЗрд▓ рдореЗрдВ рд╕рд╣реЗрдЬреЗрдВ) рдХреЛ рдмрдЪрд╛рддреЗ рд╣реИрдВ рдФрд░ рдлрд┐рд░ рдЬрд╡рд╛рдм рд╡рд╛рдкрд╕ рдХрд░рддреЗ рд╣реИрдВред

рдЖрдкрдХреЛ рд╕реНрдЯреЗрдЯрд╕ рдХреЛрдб 201 рднреЗрдЬрдирд╛ рд╣реЛрдЧрд╛, рдЬреЛ рдХрд╣рддрд╛ рд╣реИ рдХрд┐ рд╕рдВрд╕рд╛рдзрди рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рд╣реИред рдХреГрдкрдпрд╛ рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рдореИрдВ рдЗрд╕ рдкрджреНрдзрддрд┐ рдХреЗ рд▓рд┐рдП рджреГрд╢реНрдп рдПрдиреЛрдЯреЗрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░ рд░рд╣рд╛ рд╣реВрдВред

рд▓реЗрдХрд┐рди рдЕрдЧрд░ рдЖрдк рдХреЛрдб рдХреЛ рдХрд░реАрдм рд╕реЗ рджреЗрдЦрддреЗ рд╣реИрдВ, рддреЛ рдЖрдк рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рдореИрдВрдиреЗ рдПрдХ рдЕрдЬреАрдм рдмрд╛рдд рдХреАред рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рд╕рдВрд╕рд╛рдзрди рдмрдирд╛рддреЗ рд╕рдордп, рдЖрдкрдХреЛ рдХреБрдЫ рдЬрд╛рдирдХрд╛рд░реА рд╡рд╛рдкрд╕ рдХрд░рдиреА рдЪрд╛рд╣рд┐рдП: рдЗрд╕ рд╕рдВрд╕рд╛рдзрди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХреИрд╕реЗ рдХрд░реЗрдВред рджреВрд╕рд░реЗ рд╢рдмреНрджреЛрдВ рдореЗрдВ, рдЖрдкрдХреЛ рдпреВрдЖрд░рдЖрдИ рд╡рд╛рдкрд╕ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред HTTP рдХрд▓реНрдкрдирд╛ рдХрд╣рддреА рд╣реИ рдХрд┐ рдЖрдкрдХреЛ рд╕реНрдерд╛рди рд╣реЗрдбрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП, рдЬреЛ рдореИрдВрдиреЗ рдХрд┐рдпрд╛ред рд▓реЗрдХрд┐рди рдЖрдк рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЖрдИрдбреА рдЬреИрд╕реА рдЬрд╛рдирдХрд╛рд░реА рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдФрд░ рдЕрдиреБрд░реЛрдз рдХрд░рдиреЗ рдХреА рд╕рдВрднрд╛рд╡рдирд╛ рдирд╣реАрдВ рд░рдЦрддреЗ рд╣реИрдВ (рд╡реИрд╕реЗ рднреА рдЖрдкрдХреЗ рдкрд╛рд╕ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдмрд╛рдХреА рдЬрд╛рдирдХрд╛рд░реА рд╣реИ)ред рдФрд░ рдлрд┐рд░ рдореЗрд░реА рдореБрдЦреНрдп рдЕрд╡рдзрд╛рд░рдгрд╛ рджрд┐рдЦрд╛рдИ рджреЗрддреА рд╣реИ: рд╡реНрдпрд╛рд╡рд╣рд╛рд░рд┐рдХ рдпрд╛ рдЙрдиреНрдорддреНрдд?

рдЬрд╛рдирддреЗ рд╣реЛ рдХреНрдпрд╛? рдореИрдВ рдореИрдирд┐рдХ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдкрд╕рдВрдж рдХрд░рддрд╛ рд╣реВрдВ, рдФрд░ рдореИрдВ рд╡рд┐рдирд┐рд░реНрджреЗрд╢рди рдХрд╛ рдкрд╛рд▓рди рдХрд░рддрд╛ рд╣реВрдВ, рдХреЗрд╡рд▓ рд╕реНрдерд╛рди рд╣реЗрдбрд░ рд▓реМрдЯрд╛рддрд╛ рд╣реВрдВ:
 Location: http://example.com/users/999 


рдпрджрд┐ рдореИрдВ рдПрдХ рдЧреНрд░рд╛рд╣рдХ рдХреЗ рд░реВрдк рдореЗрдВ рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдлреНрд░реЗрдорд╡рд░реНрдХ Backbone.js рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реВрдВ, рдХреНрдпреЛрдВрдХрд┐ рдореИрдВ рдЗрд╕рдХреЗ рдХреБрдЫ рд╣рд┐рд╕реНрд╕реЛрдВ рдХреЛ рдлрд┐рд░ рд╕реЗ рд▓рд┐рдЦрдирд╛ рдирд╣реАрдВ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рд╕рд╣реА рдПрдкреАрдЖрдИ рдХрд╛ рд╕рдорд░реНрдерди рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ, рддреЛ рдореИрдВ рд╕рдм рдХреБрдЫ рдХреЗ рдЕрд▓рд╛рд╡рд╛ рдЖрдИрдбреА рд╡рд╛рдкрд╕ рдХрд░ рджреВрдВрдЧрд╛ред рд╡реНрдпрд╛рд╡рд╣рд╛рд░рд┐рдХ рд╣реЛрдирд╛ рдЕрднреА рднреА рдЗрддрдирд╛ рдмреБрд░рд╛ рдирд╣реАрдВ рд╣реИред

рдЗрд╕ рдХреНрд░рд┐рдпрд╛ рдХреЗ рд▓рд┐рдП рд░реВрдЯрд┐рдВрдЧ рдирд┐рдпрдо рдЬреЛрдбрд╝рдирд╛ рдпрд╛рдж рд░рдЦреЗрдВред рд╕рдВрд╕рд╛рдзрди рдмрдирд╛рдирд╛ рд╕рдВрдЧреНрд░рд╣ рдХреЗ рд▓рд┐рдП рдПрдХ POST рдЕрдиреБрд░реЛрдз рд╣реИ, рдЗрд╕рд▓рд┐рдП рдПрдХ рдирдпрд╛ рдирд┐рдпрдо рдЬреЛрдбрд╝реЗрдВ:
 acme_demo_user_new: pattern: /users defaults: { _controller: AcmeDemoBundle:User:new, _format: ~ } requirements: _method: POST 


рдПрдХ рдирдпрд╛ рд╕рдВрд╕рд╛рдзрди рдмрдирд╛рдиреЗ рдХрд╛ рддрд░реАрдХрд╛ рдЬрд╛рдирдиреЗ рдХреЗ рдмрд╛рдж, рдЗрд╕реЗ рдмрджрд▓рдирд╛ рдХрд╛рдлреА рдЖрд╕рд╛рди рд╣реЛрдЧрд╛ред

рдкреИрдЯ рдмрдирд╛рдо рдкрд┐рдЪ, рд▓рдбрд╝рд╛рдИ!


рд╕рдВрд╕рд╛рдзрди рдмрджрд▓рдиреЗ рдХрд╛ рдЕрд░реНрде рд╣реИ рдХрд┐ рдЗрд╕реЗ рдмрджрд▓рдирд╛, рдЦрд╛рд╕рдХрд░ рдпрджрд┐ рдЖрдк HTTP PUT рд╡рд┐рдзрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВред рдПрдХ PATCH рд╡рд┐рдзрд┐ рднреА рд╣реИ рдЬреЛ рд╕рдВрд╕рд╛рдзрдиреЛрдВ рдХреЗ рдмреАрдЪ рдХрд╛ рдЕрдВрддрд░ рд▓реЗрддреА рд╣реИ рдФрд░ рдкреИрдЪ рдХреЛ рдореВрд▓ рд╕рдВрд╕рд╛рдзрди рдкрд░ рд▓рд╛рдЧреВ рдХрд░рддреА рд╣реИ, рджреВрд╕рд░реЗ рд╢рдмреНрджреЛрдВ рдореЗрдВ, рдЖрдВрд╢рд┐рдХ рдЕрджреНрдпрддрди рдХрд░рддреА рд╣реИред

рдкрд╣рд▓реЗ рдХрд┐рдП рдЧрдП рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рдж, рд╕рдВрд╕рд╛рдзрди рдХреЛ рдмрджрд▓рдирд╛ рдХрд╛рдлреА рдЖрд╕рд╛рди рд╣реЛрдЧрд╛ред рдЖрдкрдХреЛ рдирд┐рдпрдВрддреНрд░рдХ рдореЗрдВ рдПрдХ рдирдИ рд╡рд┐рдзрд┐ рд▓рд┐рдЦрдиреА рд╣реЛрдЧреА рдФрд░ рдПрдХ рдирдпрд╛ рд░реВрдЯрд┐рдВрдЧ рдирд┐рдпрдо рдЬреЛрдбрд╝рдирд╛ рд╣реЛрдЧрд╛ред рдпрд╣рд╛рдВ рд╣рдо рдЕрдкрдиреЗ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреА рд╡рд╕реНрддреБ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдкреИрд░рд╛рдореАрдЯрд░ рдХрдирд╡рд░реНрдЯрд░ рдкрд░ рднрд░реЛрд╕рд╛ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдпрджрд┐ рдРрд╕рд╛ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдореМрдЬреВрдж рдирд╣реАрдВ рд╣реИ, рддреЛ рдкреИрд░рд╛рдореАрдЯрд░ рдХрдирд╡рд░реНрдЯрд░ рдПрдХ рдЕрдкрд╡рд╛рдж рдлреЗрдВрдХ рджреЗрдЧрд╛ рдФрд░ рдпрд╣ рдЕрдкрд╡рд╛рдж рд╕реНрдерд┐рддрд┐ рдХреЛрдб 404 рдХреЗ рд╕рд╛рде рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрд┐рдд рд╣реЛ рдЬрд╛рдПрдЧрд╛ред

 <?php // ... public function editAction(User $user) { return $this->processForm($user); } 


рд╕рдВрд╕рд╛рдзрди рдмрджрд▓рдиреЗ рдХрд╛ рдЕрд░реНрде рд╣реИ рдХрд┐ рдЖрдк рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдЗрд╕рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╕рдм рдХреБрдЫ рдЬрд╛рдирддреЗ рд╣реИрдВ, рддрд╛рдХрд┐ рдЖрдк рдЗрд╕ рд╕рдВрд╕рд╛рдзрди рдХреЗ рд▓рд┐рдП рдХреЗрд╡рд▓ URI рдХреЗ PUT рдЕрдиреБрд░реЛрдз рдореЗрдВ рд╡рд╛рдкрд╕ рд▓реМрдЯ рд╕рдХреЗрдВ:
 acme_demo_user_edit: pattern: /users/{id} defaults: { _controller: AcmeDemoBundle:User:edit, _format: ~ } requirements: _method: PUT 


рдФрд░ рд╡рд╣ рд╕рдм рд╣реИ! рдПрдХ рд╕рдВрд╕рд╛рдзрди рдХреЛ рд╣рдЯрд╛рдиреЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХреНрдпрд╛?

рд╣рдЯрд╛рдПрдБ


рдПрдХ рд╕рдВрд╕рд╛рдзрди рдирд┐рдХрд╛рд▓рдирд╛ рдмрд╣реБрдд рд╕рд░рд▓ рд╣реИред рдПрдХ рд░реВрдЯрд┐рдВрдЧ рдирд┐рдпрдо рдЬреЛрдбрд╝реЗрдВ:
 acme_demo_user_delete: pattern: /users/{id} defaults: { _controller: AcmeDemoBundle:User:remove, _format: ~ } requirements: _method: DELETE 


рдФрд░ рдПрдХ рдЫреЛрдЯреА рд╡рд┐рдзрд┐ рд▓рд┐рдЦреЗрдВ:
 <?php // ... /** * @Rest\View(statusCode=204) */ public function removeAction(User $user) { $user->delete(); } 


рдХреЛрдб рдХреА рд╕рд┐рд░реНрдл рдХреБрдЫ рджрд░реНрдЬрди рдкрдВрдХреНрддрд┐рдпреЛрдВ рдХреЛ рд▓рд┐рдЦрдиреЗ рдХреЗ рдмрд╛рдж, рдЖрдкрдиреЗ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдХрд╛рдо рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рдПрдкреАрдЖрдИ рдХреЛ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рд╣реИ рдЬреЛ рд╕реБрд░рдХреНрд╖рд┐рдд рд░реВрдк рд╕реЗ рд╕реАрдЖрд░рдпреВрдбреА рд╕рдВрдЪрд╛рд▓рди рдХреЛ рд▓рд╛рдЧреВ рдХрд░рддрд╛ рд╣реИред рдЕрдм, рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЗрдВрдЯрд░реИрдХреНрд╢рди рдХреЛ рдЬреЛрдбрд╝рдиреЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХреНрдпрд╛? рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рджреЛрд╕реНрддреА?

REST рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдХрд┐рд╕реА рджрд┐рдП рдЧрдП рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЗ рд▓рд┐рдП рдПрдХ рдорд┐рддреНрд░ рд╕реВрдЪреА рдХреИрд╕реЗ рдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдВ? рд╣рдореЗрдВ рдХреЗрд╡рд▓ рджреЛрд╕реНрддреЛрдВ рдХреЛ рдХрд┐рд╕реА рд╡рд┐рд╢реЗрд╖ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд╕реЗ рд╕рдВрдмрдВрдзрд┐рдд рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдХреЗ рд╕рдВрдЧреНрд░рд╣ рдХреЗ рд░реВрдк рдореЗрдВ рд╡рд┐рдЪрд╛рд░ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдЖрдЗрдП рдЗрд╕ рдЗрдВрдЯрд░реИрдХреНрд╢рди рдХреЛ рд▓рд╛рдЧреВ рдХрд░реЗрдВред

рдорд┐рддреНрд░рддрд╛ рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо


рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рд╣рдореЗрдВ рдПрдХ рдирдпрд╛ рд░реВрдЯрд┐рдВрдЧ рдирд┐рдпрдо рдмрдирд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдЪреВрдБрдХрд┐ рд╣рдо рдорд┐рддреНрд░реЛрдВ рдХреЛ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдХрд╛ рд╕рдВрдЧреНрд░рд╣ рдорд╛рдирддреЗ рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП рд╣рдо рдЗрд╕реЗ рд╕реАрдзреЗ рд╕рдВрд╕рд╛рдзрди рд╕реЗ рдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдВрдЧреЗ:
 acme_demo_user_get_friends: pattern: /users/{id}/friends defaults: { _controller: AcmeDemoBundle:User:getFriends, _format: ~ } requirements: _method: GET 


рдпрд╣ рдХреНрд░рд┐рдпрд╛ рдирд┐рдпрдВрддреНрд░рдХ рдореЗрдВ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрд╛рдИ рджреЗрдЧреА:
 <?php // ... public function getFriendsAction(User $user) { return array('friends' => $user->getFriends()); } 


рд╡рд╣ рд╕рдм рд╣реИред рдЕрдм рдЖрдЗрдП рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВ рдХрд┐ рдХрд┐рд╕реА рдЕрдиреНрдп рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЗ рджреЛрд╕реНрдд рдмрдирдиреЗ рдХреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХрд╛ рд╡рд░реНрдгрди рдХреИрд╕реЗ рдХрд░реЗрдВред рдЖрдк рдЗрд╕реЗ REST рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдХреИрд╕реЗ рдкреНрд░рдмрдВрдзрд┐рдд рдХрд░реЗрдВрдЧреЗ? рдЖрдк рджреЛрд╕реНрддреЛрдВ рдХреЗ рдПрдХ рд╕рдВрдЧреНрд░рд╣ рдХреЗ рд▓рд┐рдП POST рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░ рд╕рдХрддреЗ рдХреНрдпреЛрдВрдХрд┐ рдЖрдк рдХреБрдЫ рднреА рдмрдирд╛рдиреЗ рдирд╣реАрдВ рдЬрд╛ рд░рд╣реЗ рд╣реИрдВред рджреЛрдиреЛрдВ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдкрд╣рд▓реЗ рд╕реЗ рдореМрдЬреВрдж рд╣реИрдВред рдЖрдк PUT рдкрджреНрдзрддрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░ рд╕рдХрддреЗ рдХреНрдпреЛрдВрдХрд┐ рдЖрдк рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рд╕рдВрдкреВрд░реНрдг рд╕рдВрдЧреНрд░рд╣ рдХреЛ рдмрджрд▓рдирд╛ рдирд╣реАрдВ рдЪрд╛рд╣рддреЗ рд╣реИрдВред рдпрд╣ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рд╣рдореЗрдВ рдЪрдХрд┐рдд рдХрд░ рд╕рдХрддрд╛ рд╣реИ ...

рд▓реЗрдХрд┐рди, HTTP рдкреНрд░реЛрдЯреЛрдХреЙрд▓ рд╡рд┐рдирд┐рд░реНрджреЗрд╢ рдПрдХ рд▓рд┐рдВрдХ рд╡рд┐рдзрд┐ рдХрд╛ рд╡рд░реНрдгрди рдХрд░рддрд╛ рд╣реИ рдЬреЛ рд╣рдорд╛рд░реА рд╕рдорд╕реНрдпрд╛ рдХреЛ рд╣рд▓ рдХрд░рддрд╛ рд╣реИред рдпрд╣ рдХрд╣рддрд╛ рд╣реИ:
рд▓рд┐рдВрдХ рд╡рд┐рдзрд┐ рдЕрдиреБрд░реЛрдз-рдпреВрдЖрд░рдЖрдИ рдФрд░ рдЕрдиреНрдп рдореМрдЬреВрджрд╛ рд╕рдВрд╕рд╛рдзрдиреЛрдВ рдореЗрдВ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдореМрдЬреВрджрд╛ рд╕рдВрд╕рд╛рдзрди рдХреЗ рдмреАрдЪ рдПрдХ рдпрд╛ рдПрдХ рд╕реЗ рдЕрдзрд┐рдХ рд╕рдВрдмрдВрдз рд╕реНрдерд╛рдкрд┐рдд рдХрд░рддреА рд╣реИред


рдпрд╣ рд╡рд╣реА рд╣реИ рдЬреЛ рд╣рдореЗрдВ рдЪрд╛рд╣рд┐рдПред рд╣рдо рджреЛ рд╕рдВрд╕рд╛рдзрдиреЛрдВ рдХреЛ рдЬреЛрдбрд╝рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рд╣рдореЗрдВ рдПрдкреАрдЖрдИ рд╕реЗрд╡рд╛рдУрдВ рдХреЛ рд▓рд┐рдЦрддреЗ рд╕рдордп рд╕рдВрд╕рд╛рдзрдиреЛрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдирд╣реАрдВ рднреВрд▓рдирд╛ рдЪрд╛рд╣рд┐рдПред рддреЛ рд╕рд┐рдореНрдлрдиреА 2 рдореЗрдВ рдпрд╣ рдХреИрд╕реЗ рдХрд░реЗрдВ?

рдореЗрд░реА рд╡рд┐рдзрд┐ рдЕрдиреБрд░реЛрдз рд╢реНрд░реЛрддрд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдкрд░ рдЖрдзрд╛рд░рд┐рдд рд╣реИред рдХреНрд▓рд╛рдЗрдВрдЯ рд╕рдВрд╕рд╛рдзрди рдХреЗ рд▓рд┐рдП рдПрдХ рд▓рд┐рдВрдХ рдЕрдиреБрд░реЛрдз рднреЗрдЬрддрд╛ рд╣реИ рдФрд░ рдХрдо рд╕реЗ рдХрдо рдПрдХ рд▓рд┐рдВрдХ рд╣реЗрдбрд░ рднреЗрдЬрддрд╛ рд╣реИред
 LINK /users/1 Link: <http://example.com/users/2>; rel="friend" Link: <http://example.com/users/3>; rel="friend" 


рдХреНрд╡реЗрд░реА рд╢реНрд░реЛрддрд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдПрдХ рдмрд╣реБрдд рдЕрдЪреНрдЫрд╛ рд╡рд┐рдХрд▓реНрдк рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рдЖрдкрдХреЛ рдЕрдкрдиреЗ рддрд░реАрдХреЛрдВ рд╕реЗ рд╕реНрд╡рдЪреНрдЫ рдЗрдирдкреБрдЯ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред рдЕрдВрдд рдореЗрдВ, рдЗрд╕ рдкрджреНрдзрддрд┐ рдХрд╛ рд▓рдХреНрд╖реНрдп рд╡рд╕реНрддреБрдУрдВ рдХреЛ рдЬреЛрдбрд╝рдирд╛ рд╣реИ, рд▓реЗрдХрд┐рди рд╣рдо рдирд┐рдпрдВрддреНрд░рдХ рдореЗрдВ рдпреВрдЖрд░рдЖрдИ рдХреЗ рд╕рд╛рде рдЦреЗрд▓рдирд╛ рдирд╣реАрдВ рдЪрд╛рд╣рддреЗ рд╣реИрдВред рдЗрд╕рд╕реЗ рдкрд╣рд▓реЗ рд╕рднреА рд░реВрдкрд╛рдВрддрд░рдг рдХрд┐рдП рдЬрд╛рдиреЗ рдЪрд╛рд╣рд┐рдПред

рдЕрдиреБрд░реЛрдз рд╢реНрд░реЛрддрд╛ рдЗрди рд╕рднреА рд▓рд┐рдВрдХ рд╣реЗрдбрд░ рдХреЛ рд▓реЗ рдЬрд╛рдПрдЧрд╛ рдФрд░ рдЙрдиреНрд╣реЗрдВ рдирд┐рдпрдВрддреНрд░рдХ рдФрд░ рд╡рд┐рдзрд┐ рдХреЗ рдирд╛рдо рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП Symfony2 RouterMatcher рдШрдЯрдХ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдХрд░реЗрдЧрд╛ред рд╡рд╣ рдорд╛рдкрджрдВрдбреЛрдВ рдХреЛ рднреА рддреИрдпрд╛рд░ рдХрд░реЗрдЧрд╛ред

рджреВрд╕рд░реЗ рд╢рдмреНрджреЛрдВ рдореЗрдВ, рдирд┐рдпрдВрддреНрд░рдХ рдмрдирд╛рдиреЗ рдФрд░ рдЖрд╡рд╢реНрдпрдХ рдорд╛рдкрджрдВрдбреЛрдВ рдХреЗ рд╕рд╛рде рдЗрд╕рдореЗрдВ рд╕рд╣реА рд╡рд┐рдзрд┐ рдХреЛ рдХреЙрд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рднреА рдЖрд╡рд╢реНрдпрдХ рдЬрд╛рдирдХрд╛рд░реА рд╣реИред рд╣рдорд╛рд░реЗ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ, UserController рдореЗрдВ getUser () рд╡рд┐рдзрд┐ рдХреЛ рдкреНрд░рддреНрдпреЗрдХ рд▓рд┐рдВрдХ рд╣реЗрдбрд░ рдХреЗ рд▓рд┐рдП рдмреБрд▓рд╛рдпрд╛ рдЬрд╛рдПрдЧрд╛ред рдпрд╣реА рдХрд╛рд░рдг рд╣реИ рдХрд┐ рдореИрдВрдиреЗ рдкреИрд░рд╛рдореАрдЯрд░ рдХрдирд╡рд░реНрдЯрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд┐рдпрд╛, рдЗрд╕рд╕реЗ рдореБрдЭреЗ рддрд░реНрдХ рдХреЗ рдореВрд▓реНрдп рдХреЗ рд░реВрдк рдореЗрдВ рдЖрдИрдбреА рд▓реЗрдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рдорд┐рд▓реА, рддрд╛рдХрд┐ рдореБрдЭреЗ рдЗрд╕рдХреЗ рд▓рд┐рдП рдПрдХ рд╕рдВрд╕рд╛рдзрди рдорд┐рд▓ рд╕рдХреЗред рдореИрдВрдиреЗ рдХреБрдЫ рдзрд╛рд░рдгрд╛рдПрдБ рдмрдирд╛рдИрдВ:


рдЬрдм рдореБрдЭреЗ рдЕрдкрдиреЗ рд╕рдВрд╕рд╛рдзрди рдСрдмреНрдЬреЗрдХреНрдЯ рдорд┐рд▓рддреЗ рд╣реИрдВ, рддреЛ рдореИрдВ рдЙрдиреНрд╣реЗрдВ рдЕрдиреБрд░реЛрдз рд╡рд┐рд╢реЗрд╖рддрд╛рдУрдВ рдХреЗ рд░реВрдк рдореЗрдВ рд░рдЦреВрдВрдЧрд╛, рдФрд░ рд╣рдорд╛рд░реЗ рд╢реНрд░реЛрддрд╛ рдХреЗ рд▓рд┐рдП, рдХрд╛рдо рдкреВрд░рд╛ рд╣реЛ рдЬрд╛рдПрдЧрд╛ред рдпрд╣рд╛рдБ рдХреЛрдб рд╣реИ:
 <?php namespace Acme\DemoBundle\EventListener; use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface; use Symfony\Component\Routing\Matcher\UrlMatcherInterface; use Symfony\Component\HttpFoundation\Request; class LinkRequestListener { /** * @var ControllerResolverInterface */ private $resolver; private $urlMatcher; /** * @param ControllerResolverInterface $controllerResolver The 'controller_resolver' service * @param UrlMatcherInterface $urlMatcher The 'router' service */ public function __construct(ControllerResolverInterface $controllerResolver, UrlMatcherInterface $urlMatcher) { $this->resolver = $controllerResolver; $this->urlMatcher = $urlMatcher; } public function onKernelRequest(GetResponseEvent $event) { if (!$event->getRequest()->headers->has('link')) { return; } $links = array(); $header = $event->getRequest()->headers->get('link'); /* *   ,     *     . * *         Link   * http://tools.ietf.org/html/rfc2068#section-19.6.2.4 */ while (preg_match('/^((?:[^"]|"[^"]*")*?),/', $header, $matches)) { $header = trim(substr($header, strlen($matches[0]))); $links[] = $matches[1]; } if ($header) { $links[] = $header; } $requestMethod = $this->urlMatcher->getContext()->getMethod(); //    GET    //     ,      (LINK/UNLINK) $this->urlMatcher->getContext()->setMethod('GET'); //           $stubRequest = new Request(); foreach ($links as $idx => $link) { $linkParams = explode(';', trim($link)); $resource = array_shift($linkParams); $resource = preg_replace('/<|>/', '', $resource); try { $route = $this->urlMatcher->match($resource); } catch (\Exception $e) { //        //     Link continue; } $stubRequest->attributes->replace($route); if (false === $controller = $this->resolver->getController($stubRequest)) { continue; } $arguments = $this->resolver->getArguments($stubRequest, $controller); try { $result = call_user_func_array($controller, $arguments); //       if (!is_array($result)) { continue; } //     $links[$idx] = current($result); } catch (\Exception $e) { continue; } } $event->getRequest()->attributes->set('link', $links); $this->urlMatcher->getContext()->setMethod($requestMethod); } } 


рдЕрдм рд╣рдо рдПрдХ рд░реВрдЯрд┐рдВрдЧ рдирд┐рдпрдо рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВ:
 acme_demo_user_link: pattern: /users/{id} defaults: { _controller: AcmeDemoBundle:User:link, _format: ~ } requirements: _method: LINK 


рдФрд░ рд╣рдорд╛рд░реА рдХрд╛рд░реНрд░рд╡рд╛рдИ рдХрд╛ рдХреЛрдб рдЗрд╕ рддрд░рд╣ рджрд┐рдЦреЗрдЧрд╛:
 <?php // ... /** * @Rest\View(statusCode=204) */ public function linkAction(User $user, Request $request) { if (!$request->attributes->has('link')) { throw new HttpException(400); } foreach ($request->headers->get('Link') as $u) { if (!$u instanceof User) { throw new NotFoundHttpException('Invalid resource'); } if ($user->hasFriend($u)) { throw new HttpException(409, 'Users are already friends'); } $user->addFriend($u); } $user->save(); } 


рдпрджрд┐ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдорд┐рддреНрд░ рд╣реИрдВ, рддреЛ рд╣рдореЗрдВ 409 рдХреА рд╕реНрдерд┐рддрд┐ рдХреЛрдб рдХреЗ рд╕рд╛рде рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдорд┐рд▓реЗрдЧреА, рдЬрд┐рд╕рдХрд╛ рдЕрд░реНрде рд╣реИ рдХрд┐ рдПрдХ рд╕рдВрдШрд░реНрд╖ рд╣реБрдЖ рд╣реИред рдпрджрд┐ рдЕрдиреБрд░реЛрдз рд▓рд┐рдВрдХ рд╣реЗрдбрд░ рдХреЛ рдпрд╛рдж рдХрд░ рд░рд╣рд╛ рд╣реИ, рддреЛ рдпрд╣ рдЦрд░рд╛рдм рдЕрдиреБрд░реЛрдз (400) рд╣реИред

рд╡рд╣реА рджреЛрд╕реНрддреЛрдВ рдХреЛ рд╣рдЯрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдЬрд╛рддрд╛ рд╣реИред рдХреЗрд╡рд▓ рдпрд╣рд╛рдБ рд╣рдо UNLINK рд╡рд┐рдзрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗред

рдФрд░ рдЕрдВрдд рдореЗрдВред рдореИрдВрдиреЗ PATCH рд╡рд┐рдзрд┐ рдХреА рд╡реНрдпрд╛рдЦреНрдпрд╛ рдирд╣реАрдВ рдХреАред рдореЗрд░рд╛ рдорддрд▓рдм рд╣реИ, рдЗрд╕ рдкрджреНрдзрддрд┐ рдХреЗ рд▓рд┐рдП рдкрд░рд┐рджреГрд╢реНрдп рдХреНрдпрд╛ рд╣реЛрдЧрд╛? рдЙрддреНрддрд░ рдЖрдВрд╢рд┐рдХ рдЕрджреНрдпрддрди рдпрд╛ рдХреЛрдИ рднреА рддрд░реАрдХрд╛ рд╣реЛрдЧрд╛ рдЬреЛ рдЕрд╕реБрд░рдХреНрд╖рд┐рдд, рдЕрд╡рд┐рд╢реНрд╡рд╕рдиреАрдп рдпрд╛ рдмреЗрдХрд╛рд░ рди рд╣реЛред рдпрджрд┐ рдЖрдкрдХреЗ рдкрд╛рд╕ рдПрдХ рдЧреИрд░-рдорд╛рдирдХ рд╡рд┐рдзрд┐ рд╣реИ, рдФрд░ рдЖрдкрдХреЛ рдкрддрд╛ рдирд╣реАрдВ рд╣реИ рдХрд┐ рдЗрд╕рдХреЗ рд▓рд┐рдП рдХреМрди рд╕реА рд╡рд┐рдзрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рд╣реИ, рддреЛ рд╕рдмрд╕реЗ рдЕрдзрд┐рдХ рд╕рдВрднрд╛рд╡рдирд╛ рд╣реИ рдХрд┐ рдкреИрдЯрдЪ рдЖрдкрдХреЗ рдЕрдиреБрд░реВрдк рд╣реЛрдЧрд╛ред

рдорд╛рди рд▓реАрдЬрд┐рдП рдХрд┐ рдЖрдкрдХреЗ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдХреЛ рддреГрддреАрдп-рдкрдХреНрд╖ рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЕрдкрдирд╛ рдИрдореЗрд▓ рдмрджрд▓рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рд╣реИред рдпрд╣ рдХреНрд▓рд╛рдЗрдВрдЯ рджреЛ-рдЪрд░рдгреАрдп рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИред рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЕрдкрдиреЗ рдИрдореЗрд▓ рдкрддреЗ рдХреЛ рдмрджрд▓рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрдиреБрдорддрд┐ рдХрд╛ рдЕрдиреБрд░реЛрдз рдХрд░рддрд╛ рд╣реИ, рд╡рд╣ рдПрдХ рд▓рд┐рдВрдХ рдХреЗ рд╕рд╛рде рдПрдХ рдИрдореЗрд▓ рдкреНрд░рд╛рдкреНрдд рдХрд░рддрд╛ рд╣реИ рдФрд░ рдЙрд╕ рдкрд░ рдХреНрд▓рд┐рдХ рдХрд░рдХреЗ, рдкрд░рд┐рд╡рд░реНрддрдиреЛрдВ рдХреА рдЕрдиреБрдорддрд┐ рдкреНрд░рд╛рдкреНрдд рдХрд░рддрд╛ рд╣реИред рдкрд╣рд▓рд╛ рдЪрд░рдг рдЫреЛрдбрд╝реЗрдВ рдФрд░ рджреВрд╕рд░реЗ рдкрд░ рдзреНрдпрд╛рди рдХреЗрдВрджреНрд░рд┐рдд рдХрд░реЗрдВред рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЛ рдПрдХ рдирдпрд╛ рдИрдореЗрд▓ рднреЗрдЬрддрд╛ рд╣реИ, рдФрд░ рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЛ рдЖрдкрдХрд╛ рдПрдкреАрдЖрдИ рддрд░реАрдХрд╛ рдХреЙрд▓ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред рдпрд╛ рддреЛ рдХреНрд▓рд╛рдЗрдВрдЯ рд╕рдВрд╕рд╛рдзрди рдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдЧрд╛ рдФрд░ рдЗрд╕реЗ рдмрджрд▓ рджреЗрдЧрд╛, рдпрд╛, рдЖрдк рд╕реНрдорд╛рд░реНрдЯ рд╣реИрдВ рдФрд░ рдЙрд╕реЗ PATCH рд╡рд┐рдзрд┐ рдкреНрд░рджрд╛рди рдХрд░рддреЗ рд╣реИрдВред

рд╣рдо PATCH рдХреА рджреБрдирд┐рдпрд╛ рдкрд░ рдереЛрдкрддреЗ рд╣реИрдВ


рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рдПрдХ рдирдпрд╛ рд░реВрдЯрд┐рдВрдЧ рдирд┐рдпрдо рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░реЗрдВ:
 acme_demo_user_patch: pattern: /users/{id} defaults: { _controller: AcmeDemoBundle:User:patch, _format: ~ } requirements: _method: PATCH 


рдФрд░ рдЕрдм рдЕрдкрдиреЗ рдХрдВрдЯреНрд░реЛрд▓рд░ рдореЗрдВ рдПрдХ рд╕реБрд░рдХреНрд╖рд┐рдд рдкреИрдЪрдРрдХреНрд╢рди () рд╡рд┐рдзрд┐ рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдХрд▓реНрдкрдирд╛ рдХреЛ рдЪрд╛рд▓реВ рдХрд░рдиреЗ рдХрд╛ рд╕рдордп рд╣реИред рдЖрдЗрдП рдПрдХ рдЙрдкрдпреЛрдЧ рдХреЗ рдорд╛рдорд▓реЗ рдХреЛ рджреЗрдЦреЗрдВред рдПрдХ рдЧреНрд░рд╛рд╣рдХ рдЖрдкрдХреЗ рд╕рдВрд╕рд╛рдзрди рдХреЗ рд▓рд┐рдП рдПрдХ рдпрд╛ рдЕрдзрд┐рдХ рдорд╛рди рднреЗрдЬ рд╕рдХрддрд╛ рд╣реИред рдмрдбрд╝реЗ рдкреИрдорд╛рдиреЗ рдкрд░ рдЕрд╕рд╛рдЗрдирдореЗрдВрдЯ рдХреЛ рд░реЛрдХрдиреЗ рдХреЗ рд▓рд┐рдП рд╕рдлреЗрдж рд╕реВрдЪреА рдкрд░ рднрд░реЛрд╕рд╛ рдХрд░рдирд╛ рдЕрдЪреНрдЫрд╛ рд╣реЛрдЧрд╛, рдЬреИрд╕рд╛ рдХрд┐ рд╕рднреА рдЕрдЪреНрдЫреЗ рд▓реЛрдЧ рдХрд░рддреЗ рд╣реИрдВ ...

рдЪрд▓реЛ рдЗрдирдкреБрдЯ рдорд╛рдкрджрдВрдбреЛрдВ рдХреЛ рдлрд╝рд┐рд▓реНрдЯрд░ рдХрд░рддреЗ рд╣реИрдВ:
 <?php $parameters = array(); foreach ($request->request->all() as $k => $v) { //   if (in_array($k, array('email'))) { $parameters[$k] = $v; } } 


рдЬреИрд╕реЗ рд╣реА рд╣рдордиреЗ рдЖрдиреЗ рд╡рд╛рд▓реЗ рдорд╛рдкрджрдВрдбреЛрдВ рдХреЛ рдлрд╝рд┐рд▓реНрдЯрд░ рдХрд┐рдпрд╛, рд╣рдореЗрдВ рдмрд┐рд▓реНрдХреБрд▓ рд╡рд╣реА рдкреИрд░рд╛рдореАрдЯрд░ рдорд┐рд▓реЗ рдЬреЛ рд╣рдо рдЪрд╛рд╣рддреЗ рдереЗред рдпрджрд┐ рд╣рдореЗрдВ рдХреБрдЫ рднреА рдирд╣реАрдВ рдорд┐рд▓рд╛ рд╣реИ, рддреЛ рдпрд╣ рдПрдХ рдмреБрд░рд╛ рдЕрдиреБрд░реЛрдз рд╣реИ рдФрд░ рд╣рдореЗрдВ 400 рдХреА рд╕реНрдерд┐рддрд┐ рдХреЛрдб рдХреЗ рд╕рд╛рде рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рд╡рд╛рдкрд╕ рдХрд░рдиреА рдЪрд╛рд╣рд┐рдПред

рдпрджрд┐ рд╕рдм рдареАрдХ рд╣реИ, рддреЛ рд╣рдо рд╕рдВрд╕рд╛рдзрди рдХреЛ рдирдП рдорд╛рди рджреЗ рд╕рдХрддреЗ рд╣реИрдВред рдУрд╣ рд░реБрдХреЛ ... рдирд╣реАрдВ! рд╣рдореЗрдВ рдкрд╣рд▓реЗ рдЗрдХрд╛рдИ рдХреА рдЬрд╛рдВрдЪ рдХрд░рдиреА рдЪрд╛рд╣рд┐рдП рдФрд░ рдХреЗрд╡рд▓ рддрднреА рдЬрдм рд╕рднреА рдбреЗрдЯрд╛ рдорд╛рдиреНрдп рд╣реЛрдВ, рдЗрд╕реЗ рд╕рд╣реЗрдЬреЗрдВред

рдЗрд╕ рдХреНрд░рд┐рдпрд╛ рдХрд╛ рдХреЛрдб рдХреБрдЫ рдЗрд╕ рдкреНрд░рдХрд╛рд░ рд╣реЛрдЧрд╛:
 <?php // .... public function patchAction(User $user, Request $request) { $parameters = array(); foreach ($request->request->all() as $k => $v) { // whitelist if (in_array($k, array('email'))) { $parameters[$k] = $v; } } if (0 === count($parameters)) { return View::create( array('errors' => array('Invalid parameters.')), 400 ); } $user->fromArray($parameters); $errors = $this->get('validator')->validate($user); if (0 < count($errors)) { return View::create(array('errors' => $errors), 400); } $user->save(); $response = new Response(); $response->setStatusCode(204); $response->headers->set('Location', $this->generateUrl( 'acme_demo_user_get', array('id' => $user->getId()), true // absolute ) ); return $response; } 


рдХреЛрдб рдмрд╣реБрдд рд╕рд░рд▓ рд╣реИ, рд╣реИ рдирд╛? рд╣рдореЗрд╢рд╛ рдХреА рддрд░рд╣, рдЬрдм рдЖрдк рдХреЛрдИ рд╕рдВрд╕рд╛рдзрди рдмрдирд╛рддреЗ рд╣реИрдВ рдпрд╛ рдЕрдкрдбреЗрдЯ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдЖрдкрдХреЛ рдПрдХ 2xx рд╕реНрдерд┐рддрд┐ рдХреЛрдб рдФрд░ рдПрдХ рд╕реНрдерд╛рди рд╣реЗрдбрд░ рдХреЗ рд╕рд╛рде рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рднреЗрдЬрдиреА рдЪрд╛рд╣рд┐рдПред рдпрд╣рд╛рдВ рд╣рдо рдХреЛрдб 204 рднреЗрдЬрддреЗ рд╣реИрдВ рдХреНрдпреЛрдВрдХрд┐ рдпрд╣рд╛рдВ рдХреЛрдИ рд╕рд╛рдордЧреНрд░реА рдирд╣реАрдВ рд╣реИ рдФрд░ рд╣рдо рдХреБрдЫ рднреА рдирд╣реАрдВ рдмрдирд╛ рд░рд╣реЗ рд╣реИрдВред

рдФрд░ рдЕрдм, рдХреНрдпрд╛ рдпреЛрдЬрдирд╛ рд╣реИ? рд╣рдордиреЗ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА GET, POST, PUT, DELETE, PATCH, LINK рдФрд░ UNLINK рддрд░реАрдХреЛрдВ рдХрд╛ рдЗрд╕реНрддреЗрдорд╛рд▓ рдХрд┐рдпрд╛ рд╣реИ ред рд╣рдо рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдХреЛ рдЖрдВрд╢рд┐рдХ рд░реВрдк рд╕реЗ рдЕрдкрдбреЗрдЯ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдкреНрд░рд╛рдкреНрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рд╕рдВрд╢реЛрдзрд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рд╣рдЯрд╛ рд╕рдХрддреЗ рд╣реИрдВред рд╣рдо рд╕рднреА рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдХреА рд╕реВрдЪреА рдкреНрд░рд╛рдкреНрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдЙрдирдХреЗ рдмреАрдЪ рдорд┐рддреНрд░рддрд╛ рд╕реНрдерд╛рдкрд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рд╣рдо рдЬрд╛рдирддреЗ рд╣реИрдВ рдХрд┐ рдпрджрд┐ рд╣рдореЗрдВ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдбреЗрдЯрд╛ рдХреЛ рдмрджрд▓рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рддреЛ рд╣рдо рд╕реБрд░рдХреНрд╖рд┐рдд рд░реВрдк рд╕реЗ рдкрд╛рде рд╡рд┐рдзрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред

рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рд░рд┐рдЪрд░реНрдбрд╕рди рдкрд░рд┐рдкрдХреНрд╡рддрд╛ рдореЙрдбрд▓ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ , рд╣рдордиреЗ рдХреЗрд╡рд▓ рджреВрд╕рд░реЗ рд╕реНрддрд░ рдХреЛ рдХрд╡рд░ рдХрд┐рдпрд╛ред рддреЛ рдЪрд▓рд┐рдП HATEOAS рдкрд░ рдПрдХ рдирдЬрд╝рд░ рдбрд╛рд▓рддреЗ рд╣реИрдВ рдФрд░ рддреАрд╕рд░реЗ рд╕реНрддрд░ рдХреЛ рдЕрдирд▓реЙрдХ рдХрд░рддреЗ рд╣реИрдВ!



рдХрд┐рд╕рд╕реЗ рдШреГрдгрд╛ рдХрд░рдиреА рд╣реИ?


HATEOAS рдХрд╛ рдирдлрд░рдд рд╕реЗ рдХреЛрдИ рд▓реЗрдирд╛-рджреЗрдирд╛ рдирд╣реАрдВ рд╣реИ, рд▓реЗрдХрд┐рди рдЖрдк рдЗрд╕ рджреГрд╖реНрдЯрд┐рдХреЛрдг рд╕реЗ рдирдлрд░рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдпрджрд┐ рдЖрдк рдЦреБрдж рдХреЛ рдПрдХ рд╡реНрдпрд╛рд╡рд╣рд╛рд░рд┐рдХ рдкреНрд░реЛрдЧреНрд░рд╛рдорд░ рдорд╛рдирддреЗ рд╣реИрдВред рдпрд╣ рд╕рдВрдХреНрд╖рд┐рдкреНрдд рдирд╛рдо рд╣рд╛рдЗрдкрд░рдореЗрдбрд┐рдпрд╛ рдХреЗ рд░реВрдк рдореЗрдВ рдЕрдиреБрдкреНрд░рдпреЛрдЧ рд░рд╛рдЬреНрдп рдХреЗ рдЗрдВрдЬрди рдХреЗ рд▓рд┐рдП рд╣реИред рдореЗрд░реЗ рд▓рд┐рдП, рдпрд╣ рдЖрдкрдХреЗ рдПрдкреАрдЖрдИ рд╕реЗрд╡рд╛рдУрдВ рдореЗрдВ рд╢рдмреНрджрд╛рд░реНрде рдЬреЛрдбрд╝рдиреЗ рдХреЗ рд░реВрдк рдореЗрдВ рджреЗрдЦрд╛ рдЬрд╛рддрд╛ рд╣реИред

рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ рдкрд╣рд▓реЗ, рдореИрдВрдиреЗ рдХреНрд▓рд╛рдЗрдВрдЯ рдФрд░ рдЖрдкрдХреЗ рдПрдкреАрдЖрдИ рдХреЗ рдмреАрдЪ рд╕реВрдЪрдирд╛рдУрдВ рдХреЗ рдЖрджрд╛рди-рдкреНрд░рджрд╛рди рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЬрд╛рдиреЗ рд╡рд╛рд▓реЗ рдкреНрд░рд╛рд░реВрдкреЛрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХреА рдереАред рдпрджрд┐ рдЖрдк HATEOAS рд╕рд┐рджреНрдзрд╛рдВрддреЛрдВ рдХрд╛ рдкрд╛рд▓рди рдХрд░рдиреЗ рдХрд╛ рдирд┐рд░реНрдгрдп рд▓реЗрддреЗ рд╣реИрдВ, рддреЛ JSON рд╕рдмрд╕реЗ рдЕрдЪреНрдЫрд╛ рд╡рд┐рдХрд▓реНрдк рдирд╣реАрдВ рд╣реИ, рд╣рд╛рд▓рд╛рдВрдХрд┐ рдХреБрдЫ рд▓реЛрдЧ рдЗрд╕ рд╕рдорд╕реНрдпрд╛ рдХреЗ рд╕рдорд╛рдзрд╛рди рдХреА рдкреЗрд╢рдХрд╢ рдХрд░рддреЗ рд╣реИрдВ ред

рд╣рдо рдЕрдкрдиреЗ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЗ рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдХреЛ XML рдореЗрдВ рдмрджрд▓рддреЗ рд╣реИрдВ:
 <user> <id>999</id> <username>xxxx</username> <email>xxxx@example.org</email> </user> 


рдпрджрд┐ рдХреНрд▓рд╛рдЗрдВрдЯ XML рд╕реЗ рдЕрдиреБрд░реЛрдз рдХрд░рддрд╛ рд╣реИ рддреЛ рдпрд╣ рдЖрдкрдХреА рдкреНрд░рд╛рдкреНрдд рд╡рд┐рдзрд┐ рдХрд╛ рдЖрдЙрдЯрдкреБрдЯ рд╣реИред HATEOAS рд╕реЗ рдХреБрдЫ рднреА рдирд╣реАрдВ рд╣реИред рдкрд╣рд▓рд╛ рдЪрд░рдг рд▓рд┐рдВрдХ рдЬреЛрдбрд╝рдирд╛ рд╣реИ:
 <user> <id>999</id> <username>xxxx</username> <email>xxxx@example.org</email> <link href="http://example.com/users/999" rel="self" /> </user> 


рдпрд╣ рд╕рд░рд▓ рдерд╛, рд╣рдордиреЗ рд╕рд┐рд░реНрдл рдПрдХ рд▓рд┐рдВрдХ рдЬреЛрдбрд╝рд╛, рдЬреЛ рдЙрд╕ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЛ рд╕рдВрджрд░реНрднрд┐рдд рдХрд░рддрд╛ рд╣реИ рдЬрд┐рд╕рдХрд╛ рдбреЗрдЯрд╛ рд╣рдореЗрдВ рдкреНрд░рд╛рдкреНрдд рд╣реБрдЖ рдерд╛ред рд▓реЗрдХрд┐рди рдпрджрд┐ рдЖрдкрдХрд╛ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд╕рдВрдЧреНрд░рд╣ рдкреГрд╖реНрдард╛рдВрдХрд┐рдд рд╣реИ, рддреЛ рдЖрдк рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдкреНрд░рд╛рдкреНрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:
 <users> <user> <id>999</id> <username>xxxx</username> <email>xxxx@example.org</email> <link href="http://example.com/users/999" rel="self" /> <link href="http://example.com/users/999/friends" rel="friends" /> </user> <user> <id>123</id> <username>foobar</username> <email>foobar@example.org</email> <link href="http://example.com/users/123" rel="self" /> <link href="http://example.com/users/123/friends" rel="friends" /> </user> <link href="http://example.com/users?page=1" rel="prev" /> <link href="http://example.com/users?page=2" rel="self" /> <link href="http://example.com/users?page=3" rel="next" /> </users> 


рдЕрдм рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЛ рдкрддрд╛ рд╣реИ рдХрд┐ рд╕рдВрдЧреНрд░рд╣ рдХреЛ рдХреИрд╕реЗ рджреЗрдЦрдирд╛ рд╣реИ, рдкреГрд╖реНрдареЛрдВ рдХреЛ рдХреИрд╕реЗ рдиреЗрд╡рд┐рдЧреЗрдЯ рдХрд░рдирд╛ рд╣реИ рдФрд░ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдФрд░ / рдпрд╛ рдЙрд╕рдХреЗ рджреЛрд╕реНрддреЛрдВ рдХреЛ рдХреИрд╕реЗ рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛ рд╣реИред

рдЕрдЧрд▓рд╛ рдХрджрдо рд╕рд╡рд╛рд▓ рдХреЗ рдЬрд╡рд╛рдм рдХреЗ рд░реВрдк рдореЗрдВ рдореАрдбрд┐рдпрд╛ рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЛ рдЬреЛрдбрд╝рдирд╛ рд╣реИ : рдХреНрдпрд╛? рдПрдХ рд╕рдВрд╕рд╛рдзрди рдХреНрдпрд╛ рд╣реИ? рдЗрд╕рдореЗрдВ рдХреНрдпрд╛ рд╢рд╛рдорд┐рд▓ рд╣реИ рдпрд╛ рдореБрдЭреЗ рдРрд╕рд╛ рд╕рдВрд╕рд╛рдзрди рдмрдирд╛рдиреЗ рдХреА рдХреНрдпрд╛ рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ?

рдпрд╣ рднрд╛рдЧ рдЖрдкрдХреЛ рдЕрдкрдиреА рд╕рд╛рдордЧреНрд░реА рдкреНрд░рдХрд╛рд░ рд╕реЗ рдкрд░рд┐рдЪрд┐рдд рдХрд░рд╛рдПрдЧрд╛:
 Content-Type: application/vnd.yourname.something+xml 


рд╣рдорд╛рд░реЗ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЕрдм рдирд┐рдореНрди рдкреНрд░рдХрд╛рд░ рдХреА рд╕рд╛рдордЧреНрд░реА рдХрд╛ рдЙрд▓реНрд▓реЗрдЦ рдХрд░рддреЗ рд╣реИрдВ: рдПрдкреНрд▓рд┐рдХреЗрд╢рди / vnd.acme.user + xmlред
 <user> <id>999</id> <username>xxxx</username> <email>xxxx@example.org</email> <link href="http://example.com/users/999" rel="self" /> <link rel="friends" type="application/vnd.acme.user+xml" href="http://example.com/users/999/friends" /> </user> 


рдЕрдВрддрд┐рдо рд▓реЗрдХрд┐рди рдХрдо рд╕реЗ рдХрдо, рдЖрдк рддреАрди рдЕрд▓рдЧ-рдЕрд▓рдЧ рддрд░реАрдХреЛрдВ рд╕реЗ рдЕрдкрдиреА рдПрдкреАрдЖрдИ рд╕реЗрд╡рд╛ рдореЗрдВ рд╕рдВрд╕реНрдХрд░рдг рдЬреЛрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВред рдЕрдкрдиреЗ рдпреВрдЖрд░рдЖрдИ рдореЗрдВ рд╕рдВрд╕реНрдХрд░рдг рд╕рдВрдЦреНрдпрд╛ рдЬреЛрдбрд╝рдиреЗ рдХрд╛ рдПрдХ рдЖрд╕рд╛рди рддрд░реАрдХрд╛ рд╣реЛрдЧрд╛:
 /api/v1/users 

рджреВрд╕рд░рд╛ рддрд░реАрдХрд╛ рдпрд╣ рд╣реИ рдХрд┐ рдПрдХ рдирдИ рд╕рд╛рдордЧреНрд░реА рдкреНрд░рдХрд╛рд░ рдШреЛрд╖рд┐рдд рдХрд░реЗрдВ:
 application/vnd.acme.user-v1+xml 


рдпрд╛ рдЖрдк рдЕрдкрдиреЗ рд╕реНрд╡реАрдХрд╛рд░ рд╢реАрд░реНрд╖ рд▓реЗрдЦ рдореЗрдВ рд╕рдВрд╕реНрдХрд░рдг рд╕реВрдЪрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ , рдЗрд╕ рд╕реНрдерд┐рддрд┐ рдореЗрдВ рдЖрдкрдХреЛ рд╕рд╛рдордЧреНрд░реА рдХреЗ рдкреНрд░рдХрд╛рд░ рдХреЛ рдмрджрд▓рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИ:
 application/vnd.acme.user+xml;v=1 


рдЖрдк рдЪреБрдиреЗрдВ рдХрд┐ рдХрд┐рд╕ рддрд░реАрдХреЗ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рд╣реИред рдкрд╣рд▓реА рд╡рд┐рдзрд┐ рд╕рдмрд╕реЗ рдЖрд╕рд╛рди рд╣реИ, рд▓реЗрдХрд┐рди рдпрд╣ рдЕрдиреНрдп рджреЛ рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рдХрдо Restful рднреА рд╣реИред рд╕рдЪ рд╣реИ, рдЕрдиреНрдп рджреЛ рдХреЛ рд╣реЛрд╢рд┐рдпрд╛рд░ рдЧреНрд░рд╛рд╣рдХреЛрдВ рдХреА рдЬрд░реВрд░рдд рд╣реИред

рдкрд░реАрдХреНрд╖рдг


рдИрдорд╛рдирджрд╛рд░ рд╣реЛрдиреЗ рдХреЗ рд▓рд┐рдП, рдпрджрд┐ рдЖрдк рдЧреНрд░рд╛рд╣рдХ рдХреЛ рдЕрдкрдиреА рдПрдкреАрдЖрдИ рд╕реЗрд╡рд╛ рджреЗрдиреЗ рдХрд╛ рдирд┐рд░реНрдгрдп рд▓реЗрддреЗ рд╣реИрдВ, рддреЛ рдпрд╣ рдЕрдиреБрднрд╛рдЧ рд╕рдмрд╕реЗ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИред рдЖрдк рдпрд╣ рдЪреБрди рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ REST рд╡рд┐рдЪрд╛рд░рдзрд╛рд░рд╛ рдХрд╛ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдкрд╛рд▓рди рдХрд┐рдпрд╛ рдЬрд╛рдП рдпрд╛ рдирд╣реАрдВ, рд▓реЗрдХрд┐рди рдЖрдкрдХреА API рд╕реЗрд╡рд╛ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдХрд╛рдо рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП, рдЬрд┐рд╕рдХрд╛ рдЕрд░реНрде рд╣реИ рдЕрдЪреНрдЫреА рддрд░рд╣ рд╕реЗ рдкрд░реАрдХреНрд╖рдг рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ред

рдореИрдВ рдХрд╛рд░реНрдпрд╛рддреНрдордХ рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреЗ рд╕рд╛рде рдЕрдкрдиреА рдПрдкреАрдЖрдИ рд╕реЗрд╡рд╛рдУрдВ рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд░рдирд╛ рдкрд╕рдВрдж рдХрд░рддрд╛ рд╣реВрдВ, рдЬрд┐рд╕рдХрд╛ рдЕрд░реНрде рд╣реИ рдХрд┐ рдореИрдВ рд╕рд┐рд╕реНрдЯрдо рдХреЛ рдПрдХ рдмреНрд▓реИрдХ рдмреЙрдХреНрд╕ рдорд╛рдирддрд╛ рд╣реВрдВред Symfony2 рдореЗрдВ рдПрдХ рдЕрдЪреНрдЫрд╛ рдХреНрд▓рд╛рдЗрдВрдЯ рд╢рд╛рдорд┐рд▓ рд╣реИ рдЬреЛ рдЖрдкрдХреЛ рдкрд░реАрдХреНрд╖рдг рдХрдХреНрд╖рд╛рдУрдВ рдореЗрдВ рд╕реАрдзреЗ рдЕрдкрдиреЗ рдПрдкреАрдЖрдИ рддрд░реАрдХреЛрдВ рдХреЛ рдХреЙрд▓ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ:
 $client = static::createClient(); $crawler = $client->request('GET', '/users'); $response = $this->client->getResponse(); $this->assertJsonResponse($response, 200); 


рдореИрдВ рдЕрдкрдиреЗ WebTestCase рдХреНрд▓рд╛рд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реВрдВ рдЬрд┐рд╕рдореЗрдВ рдореИрдВрдиреЗ assertJsonResponse () рд╡рд┐рдзрд┐ рд▓рд╛рдЧреВ рдХреА рд╣реИ:
 <?php // ... protected function assertJsonResponse($response, $statusCode = 200) { $this->assertEquals( $statusCode, $response->getStatusCode(), $response->getContent() ); $this->assertTrue( $response->headers->contains('Content-Type', 'application/json'), $response->headers ); } 


рдпрд╣ рдкрд╣рд▓рд╛ рд╕рддреНрдпрд╛рдкрди рдХрджрдо рд╣реИ рдЬреЛ рдПрдкреАрдЖрдИ рдХреЙрд▓ рдХреЗ рддреБрд░рдВрдд рдмрд╛рдж рдЪрд▓рддрд╛ рд╣реИред рдпрджрд┐ рд╕рдм рдХреБрдЫ рдареАрдХ рд░рд╣рд╛, рддреЛ рдореИрдВ рдЕрдиреНрдп рдЬрд╛рдВрдЪ рдХрд░рддрд╛ рд╣реВрдВ рдЬреЛ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдореЗрд░реЗ рджреНрд╡рд╛рд░рд╛ рдкреНрд░рд╛рдкреНрдд рдбреЗрдЯрд╛ рд╕реЗ рд╕рдВрдмрдВрдзрд┐рдд рд╣реИрдВред

рдЬрдм рдЖрдк рдЕрдкрдиреЗ рдПрдкреАрдЖрдИ рд╕реЗрд╡рд╛рдУрдВ рдХреЗ рд▓рд┐рдП рдкрд░реАрдХреНрд╖рдг рд▓рд┐рдЦрддреЗ рд╣реИрдВ, рддреЛ рдЖрдкрдХреЗ рджрд┐рдорд╛рдЧ рдореЗрдВ рдЖрдиреЗ рд╡рд╛рд▓реА рдХрд┐рд╕реА рднреА рдЪреАрдЬрд╝ рдХреА рдЬрд╛рдВрдЪ рдХрд░реЗрдВред рдЦрд░рд╛рдм рдЕрдиреБрд░реЛрдзреЛрдВ рдХреА рдЬрд╛рдВрдЪ рдХрд░рдирд╛ рди рднреВрд▓реЗрдВ рдФрд░ рдкрд░реАрдХреНрд╖рдг рдореЗрдВ рдкреНрд░рддреНрдпреЗрдХ рд╕рдВрднрд╛рд╡рд┐рдд рд╕реНрдерд┐рддрд┐ рдХреЛрдб рдФрд░ рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЛ рд╕рд╣реА рд╕рдВрджреЗрд╢ рдХреЗ рд▓рд┐рдП рдХрдо рд╕реЗ рдХрдо рдПрдХ рд╡рд┐рдзрд┐ рд╢рд╛рдорд┐рд▓ рдХрд░реЗрдВред рдХреЛрдб 500 рдХрд╛ рдорддрд▓рдм 400 рдХреЗ рд╕рдорд╛рди рдирд╣реАрдВ рд╣реИред

рдкреНрд░рд▓реЗрдЦрди


рдЕрдЪреНрдЫрд╛ рдПрдкреАрдЖрдИ рдкреНрд░рд▓реЗрдЦрди рдПрдХ рдмрд╣реБрдд рд╣реА рдорд╣рддреНрд╡рдкреВрд░реНрдг рдкреИрд░рд╛рдореАрдЯрд░ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рдПрдХрдорд╛рддреНрд░ рдРрд╕реА рдЪреАрдЬ рд╣реИ рдЬрд┐рд╕рдХрд╛ рдЧреНрд░рд╛рд╣рдХреЛрдВ рддрдХ рдкрд╣реБрдВрдЪ рд╣реЛрдЧреАред рдЖрдк рдЙрдиреНрд╣реЗрдВ рд╕рднреА рдХреЛрдб рдкреНрд░рджрд╛рди рдирд╣реАрдВ рдХрд░реЗрдВрдЧреЗ?

рдпрджрд┐ рдЖрдк HATEOAS рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдЖрдкрдХреЗ API рдореЗрдВ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рджрд╕реНрддрд╛рд╡реЗрдЬрд╝ рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП рдЖрдкрдХреЛ рдЗрд╕реЗ рд╕реНрд╡рдпрдВ рд▓рд┐рдЦрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдЧреНрд░рд╛рд╣рдХ рд╕реНрд╡рдпрдВ рд╕рднреА рдЙрдкрд▓рдмреНрдз рд╡рд┐рдХрд▓реНрдкреЛрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЬрд╛рдиреЗрдВрдЧреЗред

рд▓реЗрдХрд┐рди рдлрд┐рд░, рд╣реЗрдЯреЛрд╕ рдПрдкреАрдЖрдИ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдирд╛ рдХрд╛рдлреА рдореБрд╢реНрдХрд┐рд▓ рд╣реИ, рдФрд░ рд╡реЗ рдЕрднреА рдмрд╣реБрдд рдЖрдо рдирд╣реАрдВ рд╣реИрдВред рдпрджрд┐ рдЖрдкрдХреА рдПрдкреАрдЖрдИ рд╕реЗрд╡рд╛ рд░рд┐рдЪрд░реНрдбрд╕рди рдореЙрдбрд▓ рдХреЗ рджреВрд╕рд░реЗ рд╕реНрддрд░ рдХрд╛ рдЕрдиреБрд╕рд░рдг рдХрд░рддреА рд╣реИ, рддреЛ рдпрд╣ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдЕрдЪреНрдЫрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЖрдкрдХреЛ рд╕рднреА рджрд╕реНрддрд╛рд╡реЗрдЬ рд╕реНрд╡рдпрдВ рд▓рд┐рдЦрдиреЗ рд╣реЛрдВрдЧреЗ!

рд▓реЗрдХрд┐рди рдпрд╣рд╛рдБ рдмрдЪрд╛рд╡ рдХреЗ рд▓рд┐рдП NelmioApiDocBundle рдЖрддрд╛ рд╣реИред рдореИрдВрдиреЗ рдпрд╣ рдмрдВрдбрд▓ Nelmio рдореЗрдВ рд▓рд┐рдЦрд╛ рдерд╛рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рд╣рдорд╛рд░реЗ рдПрдкреАрдЖрдИ рд╕реЗрд╡рд╛рдУрдВ рдХреЗ рд▓рд┐рдП рдкреНрд░рд▓реЗрдЦрди рдЙрддреНрдкрдиреНрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдПред рдХреЛрдб рдХреЗ рдЖрддреНрдордирд┐рд░реАрдХреНрд╖рдг рдХреЗ рдЖрдзрд╛рд░ рдкрд░, рдмрдВрдбрд▓ рдХреЛ рдХрдИ рдЕрд▓рдЧ-рдЕрд▓рдЧ рдЬрд╛рдирдХрд╛рд░реА рдорд┐рд▓рддреА рд╣реИ, рдФрд░ рдЗрд╕реЗ рдЕрдЪреНрдЫреА рддрд░рд╣ рд╕реЗ рдбрд┐рдЬрд╝рд╛рдЗрди рдХрд┐рдП рдЧрдП рдкреГрд╖реНрдареЛрдВ рдкрд░ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рддрд╛ рд╣реИред




рдЕрдм рдЖрдкрдХреЗ рдкрд╛рд╕ рдорд╣рд╛рди рдПрдкреАрдЖрдИ рд╕реЗрд╡рд╛рдУрдВ рдХреЗ рдирд┐рд░реНрдорд╛рдг рдХреЗ рд▓рд┐рдП рд╕рдм рдХреБрдЫ рд╣реИред

рдЙрдкрдпреЛрдЧреА рд▓рд┐рдВрдХ




рдЕрдиреБрд╡рд╛рдж рдХреЗ рд▓реЗрдЦрдХ рд╕реЗ: рдореВрд▓ рд▓реЗрдЦ рдХреЗ рд▓реЗрдЦрдХ рдиреЗ рдЗрд╕реЗ рдФрд░ рдЕрдкрдбреЗрдЯ рдХрд░рдиреЗ рдХреА рдпреЛрдЬрдирд╛ рдмрдирд╛рдИ рд╣реИред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдпрджрд┐ рдЖрдкрдХреЛ рдореЗрд░реЗ рдЕрдиреБрд╡рд╛рдж рдореЗрдВ рддреНрд░реБрдЯрд┐рдпрд╛рдВ, рдЧрд▓рддрд┐рдпрд╛рдБ рдпрд╛ рдмрд╕ рдмрджрд╕реВрд░рдд-рдирд┐рд░реНрдорд┐рдд рд╡рд╛рдХреНрдпрд╛рдВрд╢ рдорд┐рд▓рддреЗ рд╣реИрдВ, рддреЛ рдХреГрдкрдпрд╛ рдЗрд╕реЗ рд╡реНрдпрдХреНрддрд┐рдЧрдд рд╕рдВрджреЗрд╢реЛрдВ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд░рд┐рдкреЛрд░реНрдЯ рдХрд░реЗрдВред рд▓реЗрдЦ рдХреА рдорд╛рддреНрд░рд╛ рдФрд░ рдиреАрдВрдж рдХреА рдХрдореА рдХреЛ рджреЗрдЦрддреЗ рд╣реБрдП, рд╢рд╛рдпрдж рдЧрд▓рддрд┐рдпрд╛рдВ рд╣реИрдВред

Source: https://habr.com/ru/post/In148951/


All Articles