{"id":306534,"date":"2020-07-06T21:00:41","date_gmt":"2020-07-06T21:00:41","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=306534"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=306534","title":{"rendered":"REST API \u0432 Symfony (\u0431\u0435\u0437 FosRestBundle) \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c JWT \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438. \u0427\u0430\u0441\u0442\u044c 1"},"content":{"rendered":"\n<div class=\"post__text post__text-html post__text_v1\" id=\"post-content-body\" data-io-article-url=\"https:\/\/habr.com\/ru\/company\/otus\/blog\/509842\/\">\n<p><strong><em>\u041f\u0435\u0440\u0435\u0432\u043e\u0434 \u0441\u0442\u0430\u0442\u044c\u0438 \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043b\u0435\u043d \u0432 \u043f\u0440\u0435\u0434\u0434\u0432\u0435\u0440\u0438\u0438 \u0441\u0442\u0430\u0440\u0442\u0430 \u043a\u0443\u0440\u0441\u0430 <a href=\"https:\/\/otus.pw\/PaVh\/\">\u00abSymfony Framework\u00bb<\/a>.<\/em><\/strong><\/p>\n<p>  <\/p>\n<hr>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/y5\/yc\/ze\/y5yczenkqac4_v8ikptqqkgnkmw.png\"><\/p>\n<p>  <\/p>\n<p>\u0412 \u043f\u0435\u0440\u0432\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u0441\u0442\u0430\u0442\u044c\u0438 \u043c\u044b \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0441\u0430\u043c\u044b\u0439 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 REST API \u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0435 Symfony \u0431\u0435\u0437 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f FosRestBundle. \u0412\u043e \u0432\u0442\u043e\u0440\u043e\u0439 \u0447\u0430\u0441\u0442\u0438, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u044f \u043e\u043f\u0443\u0431\u043b\u0438\u043a\u0443\u044e \u0441\u043b\u0435\u0434\u043e\u043c, \u043c\u044b \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c JWT \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044e. \u041f\u0440\u0435\u0436\u0434\u0435 \u0447\u0435\u043c \u043c\u044b \u043d\u0430\u0447\u043d\u0435\u043c, \u0441\u043f\u0435\u0440\u0432\u0430 \u043c\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u043f\u043e\u043d\u044f\u0442\u044c, \u0447\u0442\u043e \u043d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435 \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442 REST. <a name=\"habracut\"><\/a><\/p>\n<p>  <\/p>\n<h2 id=\"chto-oznachaet-rest\">\u0427\u0442\u043e \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442 Rest?<\/h2>\n<p>  <\/p>\n<p>REST (Representational State Transfer \u2014 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0430 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f) \u2014 \u044d\u0442\u043e \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u043d\u044b\u0439 \u0441\u0442\u0438\u043b\u044c \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0432\u0435\u0431-\u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0432 \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u044d\u043a\u043e\u0441\u0438\u0441\u0442\u0435\u043c\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u0431\u043e\u043b\u044c\u0448\u0430\u044f \u043f\u043e\u0442\u0440\u0435\u0431\u043d\u043e\u0441\u0442\u044c \u0432 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 Restful-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439. \u042d\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0441\u0432\u044f\u0437\u0430\u043d\u043e \u0441 \u0443\u0432\u0435\u0440\u0435\u043d\u043d\u044b\u043c \u043f\u043e\u0434\u044a\u0435\u043c\u043e\u043c \u043f\u043e\u0437\u0438\u0446\u0438\u0439 JavaScript \u0438 \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0445 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u043e\u0432.<\/p>\n<p>  <\/p>\n<p>REST API \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b HTTP. \u042d\u0442\u043e \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442, \u0447\u0442\u043e \u043a\u043e\u0433\u0434\u0430 \u043a\u043b\u0438\u0435\u043d\u0442 \u0434\u0435\u043b\u0430\u0435\u0442 \u043a\u0430\u043a\u043e\u0439-\u043b\u0438\u0431\u043e \u0437\u0430\u043f\u0440\u043e\u0441 \u043a \u0442\u0430\u043a\u043e\u043c\u0443 \u0432\u0435\u0431-\u0441\u0435\u0440\u0432\u0438\u0441\u0443, \u043e\u043d \u043c\u043e\u0436\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043b\u044e\u0431\u043e\u0439 \u0438\u0437 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0445 HTTP-\u0433\u043b\u0430\u0433\u043e\u043b\u043e\u0432: GET, POST, DELETE \u0438 PUT. \u041d\u0438\u0436\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u043e, \u0447\u0442\u043e \u043f\u0440\u043e\u0438\u0437\u043e\u0439\u0434\u0435\u0442, \u0435\u0441\u043b\u0438 \u043a\u043b\u0438\u0435\u043d\u0442 \u0443\u043a\u0430\u0436\u0435\u0442 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 \u0433\u043b\u0430\u0433\u043e\u043b.<\/p>\n<p>  <\/p>\n<ul>\n<li>GET: \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0441\u043f\u0438\u0441\u043a\u0430 \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432 \u0438\u043b\u0438 \u0441\u0432\u0435\u0434\u0435\u043d\u0438\u0439 \u043e \u043d\u0438\u0445.<\/li>\n<li>POST: \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043d\u043e\u0432\u043e\u0433\u043e \u0440\u0435\u0441\u0443\u0440\u0441\u0430.<\/li>\n<li>PUT: \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0434\u043b\u044f \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u0433\u043e \u0440\u0435\u0441\u0443\u0440\u0441\u0430.<\/li>\n<li>DELETE: \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0434\u043b\u044f \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u044f \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u0433\u043e \u0440\u0435\u0441\u0443\u0440\u0441\u0430.<\/li>\n<\/ul>\n<p>  <\/p>\n<p>REST \u043d\u0435 \u0438\u043c\u0435\u0435\u0442 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0439 (state), \u0438 \u044d\u0442\u043e \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442, \u0447\u0442\u043e \u043d\u0430 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0442\u043e\u0436\u0435 \u043d\u0435\u0442 \u043d\u0438\u043a\u0430\u043a\u0438\u0445 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0439 \u0437\u0430\u043f\u0440\u043e\u0441\u0430. \u0421\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u043e\u0441\u0442\u0430\u044e\u0442\u0441\u044f \u043d\u0430 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 \u043a\u043b\u0438\u0435\u043d\u0442\u0430 (\u043f\u0440\u0438\u043c\u0435\u0440 \u2014 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 JWT \u0434\u043b\u044f \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438, \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043c\u044b \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u043c\u0441\u044f \u0437\u0430\u0441\u0435\u043a\u044c\u044e\u0440\u0438\u0442\u044c \u043d\u0430\u0448 REST API). \u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u043f\u0440\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u0432 REST API \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0439 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u0439 \u043e\u0442\u0432\u0435\u0442 \u0431\u0435\u0437 \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f.<\/p>\n<p>  <\/p>\n<h2 id=\"sozdanie-proekta-symfony\">\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 Symfony:<\/h2>\n<p>  <\/p>\n<p>\u0412\u043e-\u043f\u0435\u0440\u0432\u044b\u0445, \u043c\u044b \u043f\u0440\u0435\u0434\u043f\u043e\u043b\u0430\u0433\u0430\u0435\u043c, \u0447\u0442\u043e \u0432\u044b \u0443\u0436\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043b\u0438 PHP \u0438 \u043c\u0435\u043d\u0435\u0434\u0436\u0435\u0440 \u043f\u0430\u043a\u0435\u0442\u043e\u0432 \u0421omposer \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043d\u043e\u0432\u043e\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430 Symfony. \u0421 \u044d\u0442\u0438\u043c \u0432\u0441\u0435\u043c \u0432 \u043d\u0430\u043b\u0438\u0447\u0438\u0438 \u0441\u043e\u0437\u0434\u0430\u0439\u0442\u0435 \u043d\u043e\u0432\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0432 \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b\u0435:<\/p>\n<p>  <\/p>\n<pre><code class=\"php\">composer create-project symfony\/skeleton demo_rest_api<\/code><\/pre>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/q3\/ib\/wh\/q3ibwhhyisioig_vejovpjx_faq.png\"><br \/>  <em>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 Symfony<\/em><\/p>\n<p>  <\/p>\n<p>\u041c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0431\u0430\u0437\u043e\u0432\u044b\u0439 \u0441\u043a\u0435\u043b\u0435\u0442 Symfony, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432 \u0438 API. \u0412\u043e\u0442 \u043a\u0430\u043a \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u043e\u0432:<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/wh\/cw\/tt\/whcwttz5qstpznobo8elvmiwxuc.png\"><br \/>  <em>\u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/em><\/p>\n<p>  <\/p>\n<p><strong>Config:<\/strong> \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0432\u0441\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0431\u0430\u043d\u0434\u043b\u0430 \u0438 \u0441\u043f\u0438\u0441\u043e\u043a \u0431\u0430\u043d\u0434\u043b\u043e\u0432 \u0432 bundle.php.<br \/>  <strong>Public:<\/strong> \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044e \u0447\u0435\u0440\u0435\u0437 index.php.<br \/>  <strong>Src:<\/strong> \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0432\u0441\u0435 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u044b, \u043c\u043e\u0434\u0435\u043b\u0438 \u0438 \u0441\u0435\u0440\u0432\u0438\u0441\u044b<br \/>  <strong>Var:<\/strong> \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u044b\u0435 \u043b\u043e\u0433\u0438 \u0438 \u0444\u0430\u0439\u043b\u044b \u043a\u044d\u0448\u0430.<br \/>  <strong>Vendor:<\/strong> \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0432\u0441\u0435 \u0432\u043d\u0435\u0448\u043d\u0438\u0435 \u043f\u0430\u043a\u0435\u0442\u044b.<\/p>\n<p>  <\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043c \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u043f\u0430\u043a\u0435\u0442\u044b \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0421omposer:<\/p>\n<p>  <\/p>\n<pre><code class=\"php\">composer require symfony\/orm-pack composer require sensio\/framework-extra-bundle<\/code><\/pre>\n<p>  <\/p>\n<p>\u041c\u044b \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043b\u0438 <code>sensio\/framework-extra-bundle<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u043c\u043e\u0436\u0435\u0442 \u043d\u0430\u043c \u0443\u043f\u0440\u043e\u0441\u0442\u0438\u0442\u044c \u043a\u043e\u0434, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0438 \u0434\u043b\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u043d\u0430\u0448\u0438\u0445 \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u043e\u0432.<\/p>\n<p>  <\/p>\n<p>\u041d\u0430\u043c \u0442\u0430\u043a\u0436\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c <code>symphony\/orm-pack<\/code> \u0434\u043b\u044f \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0438 \u0441 Doctrine ORM, \u0447\u0442\u043e\u0431\u044b \u0441\u043e\u0435\u0434\u0438\u043d\u0438\u0442\u044c\u0441\u044f \u0441 \u0431\u0430\u0437\u043e\u0439 \u0434\u0430\u043d\u043d\u044b\u0445. \u041d\u0438\u0436\u0435 \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u0430 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u043e\u0439 \u043c\u043d\u043e\u0439 \u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0437\u0430\u0434\u0430\u043d\u0430 \u0432 \u0444\u0430\u0439\u043b\u0435 .env.<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/cq\/0f\/zs\/cq0fzs5zrdznjlvehivq7lt3w5q.png\"><br \/>  <em>.env \u0444\u0430\u0439\u043b \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438<\/em><\/p>\n<p>  <\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043d\u0430\u0448\u0443 \u043f\u0435\u0440\u0432\u0443\u044e \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u044c. \u0421\u043e\u0437\u0434\u0430\u0439\u0442\u0435 \u043d\u043e\u0432\u044b\u0439 \u0444\u0430\u0439\u043b \u0441 \u0438\u043c\u0435\u043d\u0435\u043c <strong>Post.php<\/strong> \u0432 \u043f\u0430\u043f\u043a\u0435 <code>src\/Entity<\/code>.<\/p>\n<p>  <\/p>\n<pre><code class=\"php\">&lt;?php  namespace App\\Entity;  use Doctrine\\ORM\\Mapping as ORM;  use Symfony\\Component\\Validator\\Constraints as Assert;  \/**   * @ORM\\Entity   * @ORM\\Table(name=&quot;post&quot;)   * @ORM\\HasLifecycleCallbacks()   *\/  class Post implements \\JsonSerializable {   \/**    * @ORM\\Column(type=&quot;integer&quot;)    * @ORM\\Id    * @ORM\\GeneratedValue(strategy=&quot;AUTO&quot;)    *\/   private $id;    \/**    * @ORM\\Column(type=&quot;string&quot;, length=100    *    *\/   private $name;   \/**    * @ORM\\Column(type=&quot;text&quot;)    *\/   private $description;    \/**    * @ORM\\Column(type=&quot;datetime&quot;)    *\/   private $create_date;    \/**    * @return mixed    *\/   public function getId()   {    return $this-&gt;id;   }   \/**    * @param mixed $id    *\/   public function setId($id)   {    $this-&gt;id = $id;   }   \/**    * @return mixed    *\/   public function getName()   {    return $this-&gt;name;   }   \/**    * @param mixed $name    *\/   public function setName($name)   {    $this-&gt;name = $name;   }   \/**    * @return mixed    *\/   public function getDescription()   {    return $this-&gt;description;   }   \/**    * @param mixed $description    *\/   public function setDescription($description)   {    $this-&gt;description = $description;   }    \/**    * @return mixed    *\/   public function getCreateDate(): ?\\DateTime   {    return $this-&gt;create_date;   }    \/**    * @param \\DateTime $create_date    * @return Post    *\/   public function setCreateDate(\\DateTime $create_date): self   {    $this-&gt;create_date = $create_date;    return $this;   }    \/**    * @throws \\Exception    * @ORM\\PrePersist()    *\/   public function beforeSave(){     $this-&gt;create_date = new \\DateTime('now', new \\DateTimeZone('Africa\/Casablanca'));   }    \/**    * Specify data which should be serialized to JSON    * @link https:\/\/php.net\/manual\/en\/jsonserializable.jsonserialize.php    * @return mixed data which can be serialized by &lt;b&gt;json_encode&lt;\/b&gt;,    * which is a value of any type other than a resource.    * @since 5.4.0    *\/   public function jsonSerialize()   {    return [     &quot;name&quot; =&gt; $this-&gt;getName(),     &quot;description&quot; =&gt; $this-&gt;getDescription()    ];   }  }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0418 \u043f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0433\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u0443: <code>php bin\/console doctrine:schema:create<\/code> \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0442\u0430\u0431\u043b\u0438\u0446\u044b \u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u0438 \u0441 \u043d\u0430\u0448\u0435\u0439 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u044c\u044e Post.<\/p>\n<p>  <\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c <code>PostController.php<\/code>, \u043a\u0443\u0434\u0430 \u043c\u044b \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0432\u0441\u0435 \u043c\u0435\u0442\u043e\u0434\u044b, \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u0441 API. \u041e\u043d \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u043f\u043e\u043c\u0435\u0449\u0435\u043d \u0432 \u043f\u0430\u043f\u043a\u0443 <code>src\/Controller<\/code>.<\/p>\n<p>  <\/p>\n<pre><code class=\"php\">&lt;?php  \/**   * Created by PhpStorm.   * User: hicham benkachoud   * Date: 02\/01\/2020   * Time: 22:44   *\/   namespace App\\Controller;   use App\\Entity\\Post;  use App\\Repository\\PostRepository;  use Doctrine\\ORM\\EntityManagerInterface;  use Symfony\\Bundle\\FrameworkBundle\\Controller\\AbstractController;  use Symfony\\Component\\HttpFoundation\\JsonResponse;  use Symfony\\Component\\HttpFoundation\\Request;  use Symfony\\Component\\Routing\\Annotation\\Route;   \/**   * Class PostController   * @package App\\Controller   * @Route(&quot;\/api&quot;, name=&quot;post_api&quot;)   *\/  class PostController extends AbstractController  {   \/**    * @param PostRepository $postRepository    * @return JsonResponse    * @Route(&quot;\/posts&quot;, name=&quot;posts&quot;, methods={&quot;GET&quot;})    *\/   public function getPosts(PostRepository $postRepository){    $data = $postRepository-&gt;findAll();    return $this-&gt;response($data);   }    \/**    * @param Request $request    * @param EntityManagerInterface $entityManager    * @param PostRepository $postRepository    * @return JsonResponse    * @throws \\Exception    * @Route(&quot;\/posts&quot;, name=&quot;posts_add&quot;, methods={&quot;POST&quot;})    *\/   public function addPost(Request $request, EntityManagerInterface $entityManager, PostRepository $postRepository){     try{     $request = $this-&gt;transformJsonBody($request);      if (!$request || !$request-&gt;get('name') || !$request-&gt;request-&gt;get('description')){      throw new \\Exception();     }      $post = new Post();     $post-&gt;setName($request-&gt;get('name'));     $post-&gt;setDescription($request-&gt;get('description'));     $entityManager-&gt;persist($post);     $entityManager-&gt;flush();      $data = [      'status' =&gt; 200,      'success' =&gt; &quot;Post added successfully&quot;,     ];     return $this-&gt;response($data);     }catch (\\Exception $e){     $data = [      'status' =&gt; 422,      'errors' =&gt; &quot;Data no valid&quot;,     ];     return $this-&gt;response($data, 422);    }    }    \/**    * @param PostRepository $postRepository    * @param $id    * @return JsonResponse    * @Route(&quot;\/posts\/{id}&quot;, name=&quot;posts_get&quot;, methods={&quot;GET&quot;})    *\/   public function getPost(PostRepository $postRepository, $id){    $post = $postRepository-&gt;find($id);     if (!$post){     $data = [      'status' =&gt; 404,      'errors' =&gt; &quot;Post not found&quot;,     ];     return $this-&gt;response($data, 404);    }    return $this-&gt;response($post);   }    \/**    * @param Request $request    * @param EntityManagerInterface $entityManager    * @param PostRepository $postRepository    * @param $id    * @return JsonResponse    * @Route(&quot;\/posts\/{id}&quot;, name=&quot;posts_put&quot;, methods={&quot;PUT&quot;})    *\/   public function updatePost(Request $request, EntityManagerInterface $entityManager, PostRepository $postRepository, $id){     try{     $post = $postRepository-&gt;find($id);      if (!$post){      $data = [       'status' =&gt; 404,       'errors' =&gt; &quot;Post not found&quot;,      ];      return $this-&gt;response($data, 404);     }      $request = $this-&gt;transformJsonBody($request);      if (!$request || !$request-&gt;get('name') || !$request-&gt;request-&gt;get('description')){      throw new \\Exception();     }      $post-&gt;setName($request-&gt;get('name'));     $post-&gt;setDescription($request-&gt;get('description'));     $entityManager-&gt;flush();      $data = [      'status' =&gt; 200,      'errors' =&gt; &quot;Post updated successfully&quot;,     ];     return $this-&gt;response($data);     }catch (\\Exception $e){     $data = [      'status' =&gt; 422,      'errors' =&gt; &quot;Data no valid&quot;,     ];     return $this-&gt;response($data, 422);    }    }    \/**    * @param PostRepository $postRepository    * @param $id    * @return JsonResponse    * @Route(&quot;\/posts\/{id}&quot;, name=&quot;posts_delete&quot;, methods={&quot;DELETE&quot;})    *\/   public function deletePost(EntityManagerInterface $entityManager, PostRepository $postRepository, $id){    $post = $postRepository-&gt;find($id);     if (!$post){     $data = [      'status' =&gt; 404,      'errors' =&gt; &quot;Post not found&quot;,     ];     return $this-&gt;response($data, 404);    }     $entityManager-&gt;remove($post);    $entityManager-&gt;flush();    $data = [     'status' =&gt; 200,     'errors' =&gt; &quot;Post deleted successfully&quot;,    ];    return $this-&gt;response($data);   }    \/**    * Returns a JSON response    *    * @param array $data    * @param $status    * @param array $headers    * @return JsonResponse    *\/   public function response($data, $status = 200, $headers = [])   {    return new JsonResponse($data, $status, $headers);   }    protected function transformJsonBody(\\Symfony\\Component\\HttpFoundation\\Request $request)   {    $data = json_decode($request-&gt;getContent(), true);     if ($data === null) {     return $request;    }     $request-&gt;request-&gt;replace($data);     return $request;   }   }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0417\u0434\u0435\u0441\u044c \u043c\u044b \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043b\u0438 \u043f\u044f\u0442\u044c \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u043e\u0432:<\/p>\n<p>  <\/p>\n<p>\u25cf GET \/api\/posts: \u0432\u0435\u0440\u043d\u0435\u0442 \u0441\u043f\u0438\u0441\u043e\u043a \u043f\u043e\u0441\u0442\u043e\u0432.<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/9m\/ff\/ag\/9mffagvpdyp3crbsfhvwjkmkpig.png\"><br \/>  <em>api \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0432\u0441\u0435\u0445 \u043f\u043e\u0441\u0442\u043e\u0432<\/em><\/p>\n<p>  <\/p>\n<p>\u25cf POST \/api\/posts: \u0441\u043e\u0437\u0434\u0430\u0441\u0442 \u043d\u043e\u0432\u044b\u0439 \u043f\u043e\u0441\u0442.<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/sw\/ln\/ee\/swlneessyrpmfkat3kzfjmzqq1q.png\"><br \/>  <em>api \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043d\u043e\u0432\u043e\u0433\u043e \u043f\u043e\u0441\u0442\u0430<\/em><\/p>\n<p>  <\/p>\n<p>\u25cf GET \/api\/posts\/id: \u0432\u0435\u0440\u043d\u0435\u0442 \u043f\u043e\u0441\u0442, \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u043c\u0443 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u0443,<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/9_\/e3\/pr\/9_e3pr7xsciqmepcjonp247juye.png\"><br \/>  <em>\u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0433\u043e \u043f\u043e\u0441\u0442\u0430<\/em><\/p>\n<p>  <\/p>\n<p>\u25cf PUT \/api\/posts\/id: \u043e\u0431\u043d\u043e\u0432\u0438\u0442 \u043f\u043e\u0441\u0442.<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/xz\/sh\/e6\/xzshe61brrtkzvtebtwap4h5lcm.png\"><br \/>  <em>\u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u043e\u0441\u0442\u0430<\/em><\/p>\n<p>  <\/p>\n<p>\u042d\u0442\u043e \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u043f\u043e\u0441\u043b\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f:<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/7e\/0i\/ty\/7e0ityi-jfrmhqbkak9bxkhxrjm.png\"><br \/>  <em>\u043f\u043e\u0441\u0442 \u043f\u043e\u0441\u043b\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f<\/em><\/p>\n<p>  <\/p>\n<p>\u25cf DELETE \/api\/posts\/id: \u0443\u0434\u0430\u043b\u0438\u0442 \u043f\u043e\u0441\u0442.<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/0_\/l5\/3x\/0_l53xaonceankn7hgzlri_p8ta.png\"><br \/>  <em>\u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u043f\u043e\u0441\u0442\u0430<\/em><\/p>\n<p>  <\/p>\n<p>\u042d\u0442\u043e \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0432\u0441\u0435\u0445 \u043f\u043e\u0441\u0442\u043e\u0432 \u043f\u043e\u0441\u043b\u0435 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u044f \u043f\u043e\u0441\u0442\u0430 \u0441 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u043e\u043c 3:<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/mu\/oh\/l2\/muohl2oh5fg3wcrz-hv2tcaqkck.png\"><br \/>  <em>\u0432\u0441\u0435 \u043f\u043e\u0441\u0442\u044b \u043f\u043e\u0441\u043b\u0435 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u044f<\/em><\/p>\n<p>  <\/p>\n<p>\u0418\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043a\u043e\u0434 \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0439\u0442\u0438 <a href=\"https:\/\/github.com\/hichambenkachoud\/demo-rest-api\">\u0437\u0434\u0435\u0441\u044c<\/a><\/p>\n<p>  <\/p>\n<h2 id=\"zaklyuchenie\">\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/h2>\n<p>  <\/p>\n<p>\u0418\u0442\u0430\u043a, \u0442\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u043f\u043e\u043d\u0438\u043c\u0430\u0435\u043c, \u0447\u0442\u043e \u0442\u0430\u043a\u043e\u0435 REST \u0438 Restful. Restful API \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u0431\u0435\u0437 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0439. \u041c\u044b \u0437\u043d\u0430\u0435\u043c, \u043a\u0430\u043a \u0441\u043e\u0437\u0434\u0430\u0442\u044c Restful-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f HTTP-\u0433\u043b\u0430\u0433\u043e\u043b\u044b. \u0412 \u043e\u0431\u0449\u0435\u043c, \u0442\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u0445\u043e\u0440\u043e\u0448\u043e \u043f\u043e\u043d\u0438\u043c\u0430\u0435\u043c REST \u0438 \u0433\u043e\u0442\u043e\u0432\u044b \u043f\u0440\u043e\u0444\u0435\u0441\u0441\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c Restful-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f.<\/p>\n<p>  <\/p>\n<p>\u0412 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u043a\u0430\u043a \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0442\u044c \u0441\u0435\u043a\u044c\u044e\u0440\u043d\u043e\u0441\u0442\u044c API \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e JWT \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438.<\/p>\n<p>  <\/p>\n<hr>\n<p>  <\/p>\n<p><a href=\"https:\/\/otus.pw\/WECQ\/\">\u0423\u0437\u043d\u0430\u0442\u044c \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043e \u043a\u0443\u0440\u0441\u0435 \u00abSymfony Framework\u00bb<\/a><\/p>\n<p>  <\/p>\n<hr>\n<\/div>\n<p> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/company\/otus\/blog\/509842\/\"> https:\/\/habr.com\/ru\/company\/otus\/blog\/509842\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"\n<div class=\"post__text post__text-html post__text_v1\" id=\"post-content-body\" data-io-article-url=\"https:\/\/habr.com\/ru\/company\/otus\/blog\/509842\/\">\n<p><strong><em>\u041f\u0435\u0440\u0435\u0432\u043e\u0434 \u0441\u0442\u0430\u0442\u044c\u0438 \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043b\u0435\u043d \u0432 \u043f\u0440\u0435\u0434\u0434\u0432\u0435\u0440\u0438\u0438 \u0441\u0442\u0430\u0440\u0442\u0430 \u043a\u0443\u0440\u0441\u0430 <a href=\"https:\/\/otus.pw\/PaVh\/\">\u00abSymfony Framework\u00bb<\/a>.<\/em><\/strong><\/p>\n<p>  <\/p>\n<hr>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/y5\/yc\/ze\/y5yczenkqac4_v8ikptqqkgnkmw.png\"><\/p>\n<p>  <\/p>\n<p>\u0412 \u043f\u0435\u0440\u0432\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u0441\u0442\u0430\u0442\u044c\u0438 \u043c\u044b \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0441\u0430\u043c\u044b\u0439 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 REST API \u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0435 Symfony \u0431\u0435\u0437 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f FosRestBundle. \u0412\u043e \u0432\u0442\u043e\u0440\u043e\u0439 \u0447\u0430\u0441\u0442\u0438, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u044f \u043e\u043f\u0443\u0431\u043b\u0438\u043a\u0443\u044e \u0441\u043b\u0435\u0434\u043e\u043c, \u043c\u044b \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c JWT \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044e. \u041f\u0440\u0435\u0436\u0434\u0435 \u0447\u0435\u043c \u043c\u044b \u043d\u0430\u0447\u043d\u0435\u043c, \u0441\u043f\u0435\u0440\u0432\u0430 \u043c\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u043f\u043e\u043d\u044f\u0442\u044c, \u0447\u0442\u043e \u043d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435 \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442 REST. <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-306534","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/306534","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=306534"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/306534\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=306534"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=306534"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=306534"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}