{"id":301666,"date":"2020-04-10T21:00:17","date_gmt":"2020-04-10T21:00:17","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=301666"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=301666","title":{"rendered":"\u041a\u0430\u043a \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u0432 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u043c \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0432 Laravel \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e Pusher"},"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\/496652\/\"><i><b>\u041f\u0435\u0440\u0435\u0432\u043e\u0434 \u0441\u0442\u0430\u0442\u044c\u0438 \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043b\u0435\u043d \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u043e \u0434\u043b\u044f \u0441\u0442\u0443\u0434\u0435\u043d\u0442\u043e\u0432 \u043a\u0443\u0440\u0441\u0430 <a href=\"https:\/\/otus.pw\/yZGW\/\">\u00abFramework Laravel\u00bb<\/a>.<\/b><\/i><\/p>\n<hr>\n<p>  \u0421\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0439 \u0432\u0435\u0431-\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043e\u0436\u0438\u0434\u0430\u0435\u0442 \u0431\u044b\u0442\u044c \u0438\u043d\u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u043c \u043e\u0431\u043e \u0432\u0441\u0435\u043c, \u0447\u0442\u043e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438. \u0412\u044b \u0431\u044b \u043d\u0435 \u0445\u043e\u0442\u0435\u043b\u0438 \u0431\u044b\u0442\u044c \u0442\u0435\u043c \u0432\u0435\u0431-\u0441\u0430\u0439\u0442\u043e\u043c, \u0443 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043d\u0435\u0442 \u0445\u043e\u0442\u044f \u0431\u044b \u0440\u0430\u0441\u043a\u0440\u044b\u0432\u0430\u044e\u0449\u0435\u0433\u043e\u0441\u044f \u0441\u043f\u0438\u0441\u043a\u0430 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0442\u0435\u043f\u0435\u0440\u044c \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0439\u0442\u0438 \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430 \u0432\u0441\u0435\u0445 \u0441\u0430\u0439\u0442\u0430\u0445 \u0441\u043e\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0445 \u0441\u0435\u0442\u0435\u0439, \u043d\u043e \u0438 \u0432\u043e\u043e\u0431\u0449\u0435 \u043f\u043e\u0432\u0441\u044e\u0434\u0443 \u0432 \u043d\u0430\u0448\u0438 \u0434\u043d\u0438.<\/p>\n<p>  \u041a \u0441\u0447\u0430\u0441\u0442\u044c\u044e, \u0441 Laravel \u0438 <a href=\"https:\/\/pusher.com\/\">Pusher<\/a> \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u044d\u0442\u043e\u0433\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u0430 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u0430.<\/p>\n<h3>\u0423\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u0432 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u043c \u0432\u0440\u0435\u043c\u0435\u043d\u0438<\/h3>\n<p>  \u0414\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0442\u044c \u043f\u043e\u043b\u043e\u0436\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u043e\u043f\u044b\u0442, \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u0434\u043e\u043b\u0436\u043d\u044b \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c\u0441\u044f \u0432 \u0440\u0435\u0436\u0438\u043c\u0435 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438. \u041e\u0434\u043d\u0438\u043c \u0438\u0437 \u043f\u043e\u0434\u0445\u043e\u0434\u043e\u0432 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043d\u0430\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 AJAX-\u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440 \u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u043d\u043e\u0432\u0435\u0439\u0448\u0438\u0445 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439, \u0435\u0441\u043b\u0438 \u0442\u0430\u043a\u043e\u0432\u044b\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0442.<\/p>\n<p>  \u041b\u0443\u0447\u0448\u0438\u043c \u043f\u043e\u0434\u0445\u043e\u0434\u043e\u043c \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0435\u0439 WebSockets \u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439 \u0432 \u043c\u043e\u043c\u0435\u043d\u0442 \u0438\u0445 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438. \u042d\u0442\u043e \u0438\u043c\u0435\u043d\u043d\u043e \u0442\u043e, \u0447\u0442\u043e \u043c\u044b \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u043c\u0441\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0432 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435.<a name=\"habracut\"><\/a><\/p>\n<h3>Pusher<\/h3>\n<p>  <i>Pusher \u2014 \u044d\u0442\u043e \u0432\u0435\u0431-\u0441\u0435\u0440\u0432\u0438\u0441 \u0434\u043b\u044f \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0438 \u0434\u0432\u0443\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0432 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u043c \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0447\u0435\u0440\u0435\u0437 WebSockets \u0432 \u0432\u0435\u0431 \u0438 \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u044b\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f.<\/i><\/p>\n<p>  \u0423 \u043d\u0435\u0433\u043e \u043e\u0447\u0435\u043d\u044c \u043f\u0440\u043e\u0441\u0442\u043e\u0439 API, \u043d\u043e \u043c\u044b \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u043c\u0441\u044f \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0435\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0435\u0449\u0435 \u043f\u0440\u043e\u0449\u0435 \u0441 Laravel Broadcasting \u0438 Laravel Echo.<\/p>\n<p>  \u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u043c\u0441\u044f \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u0432 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u043c \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0432 \u0443\u0436\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 \u0431\u043b\u043e\u0433.<\/p>\n<h2>\u041f\u0440\u043e\u0435\u043a\u0442<\/h2>\n<p>  <\/p>\n<h3>\u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f<\/h3>\n<p>  \u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u043c\u044b \u043a\u043b\u043e\u043d\u0438\u0440\u0443\u0435\u043c \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0431\u043b\u043e\u0433 Laravel:<\/p>\n<pre><code class=\"php\">git clone   https:\/\/github.com\/marslan-ali\/laravel-blog<\/code><\/pre>\n<p>  \u0417\u0430\u0442\u0435\u043c \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0431\u0430\u0437\u0443 \u0434\u0430\u043d\u043d\u044b\u0445 MySQL \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u043c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0441\u0440\u0435\u0434\u044b, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044e \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u0431\u0430\u0437\u0435 \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<p>  \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0441\u043a\u043e\u043f\u0438\u0440\u0443\u0435\u043c <code>env.example<\/code> \u0432 <code>.env<\/code> \u0438 \u043e\u0431\u043d\u043e\u0432\u0438\u043c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435, \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0435 \u0441 \u0431\u0430\u0437\u043e\u0439 \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<pre><code class=\"php\">cp .env.example .envDB_HOST=localhost DB_DATABASE=homestead DB_USERNAME=homestead DB_PASSWORD=secret<\/code><\/pre>\n<p>  \u0422\u0435\u043f\u0435\u0440\u044c \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043c \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e<\/p>\n<pre><code class=\"plaintext\">composer install<\/code><\/pre>\n<p>  \u0418 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u043a\u043e\u043c\u0430\u043d\u0434\u0443 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0438 \u0438 \u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f, \u0447\u0442\u043e\u0431\u044b \u0437\u0430\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u0431\u0430\u0437\u0443 \u0434\u0430\u043d\u043d\u044b\u0445 \u043a\u0430\u043a\u0438\u043c\u0438-\u043d\u0438\u0431\u0443\u0434\u044c \u0434\u0430\u043d\u043d\u044b\u043c\u0438:<\/p>\n<pre><code class=\"plaintext\">php artisan migrate --seed<\/code><\/pre>\n<p>  \u0415\u0441\u043b\u0438 \u0432\u044b \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0438 \u0437\u0430\u0439\u0434\u0438\u0442\u0435 \u0432 <code>\/posts<\/code>, \u0432\u044b \u0441\u043c\u043e\u0436\u0435\u0442\u0435 \u0443\u0432\u0438\u0434\u0435\u0442\u044c \u0441\u043f\u0438\u0441\u043e\u043a \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u043f\u043e\u0441\u0442\u043e\u0432.<\/p>\n<p>  \u041f\u0440\u043e\u0432\u0435\u0440\u044c\u0442\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0439\u0442\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0438 \u0441\u043e\u0437\u0434\u0430\u0439\u0442\u0435 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439. \u042d\u0442\u043e \u043e\u0447\u0435\u043d\u044c \u043f\u0440\u043e\u0441\u0442\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u043d\u043e \u043e\u043d\u043e \u043e\u0442\u043b\u0438\u0447\u043d\u043e \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442 \u0434\u043b\u044f \u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u0438.<\/p>\n<h3>\u041f\u043e\u0434\u043f\u0438\u0441\u043a\u0430 \u043d\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439<\/h3>\n<p>  \u041c\u044b \u0445\u043e\u0442\u0435\u043b\u0438 \u0431\u044b \u0434\u0430\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u043c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043f\u043e\u0434\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u0434\u0440\u0443\u0433 \u043d\u0430 \u0434\u0440\u0443\u0433\u0430, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043c\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0435 \u00ab\u043c\u043d\u043e\u0433\u0438\u0435 \u043a\u043e \u043c\u043d\u043e\u0433\u0438\u043c\u00bb \u043c\u0435\u0436\u0434\u0443 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u043c\u0438, \u0447\u0442\u043e\u0431\u044b \u044d\u0442\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c.<\/p>\n<p>  \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0441\u0432\u043e\u0434\u043d\u0443\u044e \u0442\u0430\u0431\u043b\u0438\u0446\u0443, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0441\u0432\u044f\u0437\u044b\u0432\u0430\u0435\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0441 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u043c\u0438. \u0421\u0434\u0435\u043b\u0430\u0435\u043c \u043d\u043e\u0432\u0443\u044e \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u044e <code>followers<\/code>:<\/p>\n<pre><code class=\"php\">php artisan make:migration create_followers_table --create=followers<\/code><\/pre>\n<p>  \u041d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u043b\u0435\u0439 \u043a \u044d\u0442\u043e\u0439 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0438: <code>user_id<\/code> \u0434\u043b\u044f \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0434\u043f\u0438\u0441\u0430\u043d, \u0438 \u043f\u043e\u043b\u0435 <code>follows_id<\/code> \u0434\u043b\u044f \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043f\u043e\u0434\u043f\u0438\u0441\u0430\u043b\u0438\u0441\u044c.<\/p>\n<p>  \u041e\u0431\u043d\u043e\u0432\u0438\u0442\u0435 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u044e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<pre><code class=\"php\">public function up() {     Schema::create('followers', function (Blueprint $table) {         $table-&gt;increments('id');         $table-&gt;integer('user_id')-&gt;index();         $table-&gt;integer('follows_id')-&gt;index();         $table-&gt;timestamps();     }); }<\/code><\/pre>\n<p>  \u0422\u0435\u043f\u0435\u0440\u044c \u043f\u0435\u0440\u0435\u0439\u0434\u0435\u043c \u043a \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044e \u0442\u0430\u0431\u043b\u0438\u0446\u044b:<\/p>\n<pre><code class=\"php\">php artisan migrate<\/code><\/pre>\n<p>  \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043c\u0435\u0442\u043e\u0434\u044b \u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0439 \u0432 \u043c\u043e\u0434\u0435\u043b\u044c <code>User<\/code>.<\/p>\n<pre><code class=\"php\">\/\/ ...  class extends Authenticatable {     \/\/ ...      public function followers()      {         return $this-&gt;belongsToMany(self::class, 'followers', 'follows_id', 'user_id')                     -&gt;withTimestamps();     }      public function follows()      {         return $this-&gt;belongsToMany(self::class, 'followers', 'user_id', 'follows_id')                     -&gt;withTimestamps();     } }<\/code><\/pre>\n<p>  \u0422\u0435\u043f\u0435\u0440\u044c, \u043a\u043e\u0433\u0434\u0430 \u043c\u043e\u0434\u0435\u043b\u044c <code>User<\/code> \u0438\u043c\u0435\u0435\u0442 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u044f, <code>followers<\/code> \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0432\u0441\u0435\u0445 \u043f\u043e\u0434\u043f\u0438\u0441\u0447\u0438\u043a\u043e\u0432 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f, \u0430 <code>follows<\/code> \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0432\u0441\u0435\u0445, \u043d\u0430 \u043a\u043e\u0433\u043e \u043f\u043e\u0434\u043f\u0438\u0441\u0430\u043d \u0441\u0430\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c.<\/p>\n<p>  \u041d\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u044f\u0442\u0441\u044f \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0449\u0438\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u043f\u043e\u0434\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u0434\u0440\u0443\u0433\u0438\u0445 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u2014 <code>follow<\/code>, \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c, \u043f\u043e\u0434\u043f\u0438\u0441\u0430\u043d \u043b\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043d\u0430 \u043a\u0430\u043a\u043e\u0433\u043e-\u043d\u0438\u0431\u0443\u0434\u044c \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u2014 <code>isFollowing<\/code>.<\/p>\n<pre><code class=\"php\">\/\/ ...  class extends Authenticatable {     \/\/ ...      public function follow($userId)      {         $this-&gt;follows()-&gt;attach($userId);         return $this;     }      public function unfollow($userId)     {         $this-&gt;follows()-&gt;detach($userId);         return $this;     }      public function isFollowing($userId)      {         return (boolean) $this-&gt;follows()-&gt;where('follows_id', $userId)-&gt;first(['id']);     }  }<\/code><\/pre>\n<p>  \u041e\u0442\u043b\u0438\u0447\u043d\u043e. \u041f\u043e\u0441\u043b\u0435 \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0438 \u043c\u043e\u0434\u0435\u043b\u0438 \u043d\u0443\u0436\u043d\u043e \u0441\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0441\u043f\u0438\u0441\u043e\u043a \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439.<\/p>\n<h3>\u0421\u043f\u0438\u0441\u043e\u043a \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439<\/h3>\n<p>  \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043d\u0430\u0447\u043d\u0435\u043c \u0441 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0445 \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u043e\u0432<\/p>\n<pre><code class=\"php\">\/... Route::group(['middleware' =&gt; 'auth'], function () {     Route::get('users', 'UsersController@index')-&gt;name('users');     Route::post('users\/{user}\/follow', 'UsersController@follow')-&gt;name('follow');     Route::delete('users\/{user}\/unfollow', 'UsersController@unfollow')-&gt;name('unfollow'); });<\/code><\/pre>\n<p>  \u0417\u0430\u0442\u0435\u043c \u043f\u0440\u0438\u0448\u043b\u043e \u0432\u0440\u0435\u043c\u044f \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043d\u043e\u0432\u044b\u0439 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440 \u0434\u043b\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439:<\/p>\n<pre><code class=\"php\">php artisan make:controller UsersController<\/code><\/pre>\n<p>  \u041c\u044b \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043a \u043d\u0435\u043c\u0443 \u043c\u0435\u0442\u043e\u0434 <code>index<\/code>:<\/p>\n<pre><code class=\"php\">\/\/ ... use App\\User; class UsersController extends Controller {     \/\/..     public function index()     {         $users = User::where('id', '!=', auth()-&gt;user()-&gt;id)-&gt;get();         return view('users.index', compact('users'));     } }<\/code><\/pre>\n<p>  \u041c\u0435\u0442\u043e\u0434 \u043d\u0443\u0436\u0434\u0430\u0435\u0442\u0441\u044f \u0432 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0438. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 <code>users.index<\/code> \u0438 \u043f\u043e\u043c\u0435\u0441\u0442\u0438\u043c \u0432 \u043d\u0435\u0433\u043e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0443\u044e \u0440\u0430\u0437\u043c\u0435\u0442\u043a\u0443:<\/p>\n<pre><code class=\"php\">@extends('layouts.app')  @section('content')     &lt;div class=&quot;container&quot;&gt;         &lt;div class=&quot;col-sm-offset-2 col-sm-8&quot;&gt;              &lt;!-- Following --&gt;             &lt;div class=&quot;panel panel-default&quot;&gt;                 &lt;div class=&quot;panel-heading&quot;&gt;                     All Users                 &lt;\/div&gt;                  &lt;div class=&quot;panel-body&quot;&gt;                     &lt;table class=&quot;table table-striped task-table&quot;&gt;                         &lt;thead&gt;                         &lt;th&gt;User&lt;\/th&gt;                         &lt;th&gt; &lt;\/th&gt;                         &lt;\/thead&gt;                         &lt;tbody&gt;                         @foreach ($users as $user)                             &lt;tr&gt;                                 &lt;td clphpass=&quot;table-text&quot;&gt;&lt;div&gt;{{ $user-&gt;name }}&lt;\/div&gt;&lt;\/td&gt;                                 @if (auth()-&gt;user()-&gt;isFollowing($user-&gt;id))                                     &lt;td&gt;                                         &lt;form action=&quot;{{route('unfollow', ['id' =&gt; $user-&gt;id])}}&quot; method=&quot;POST&quot;&gt;                                             {{ csrf_field() }}                                             {{ method_field('DELETE') }}                                              &lt;button type=&quot;submit&quot; id=&quot;delete-follow-{{ $user-&gt;id }}&quot; class=&quot;btn btn-danger&quot;&gt;                                                 &lt;i class=&quot;fa fa-btn fa-trash&quot;&gt;&lt;\/i&gt;Unfollow                                             &lt;\/button&gt;                                         &lt;\/form&gt;                                     &lt;\/td&gt;                                 @else                                     &lt;td&gt;                                         &lt;form action=&quot;{{route('follow', ['id' =&gt; $user-&gt;id])}}&quot; method=&quot;POST&quot;&gt;                                             {{ csrf_field() }}                                              &lt;button type=&quot;submit&quot; id=&quot;follow-user-{{ $user-&gt;id }}&quot; class=&quot;btn btn-success&quot;&gt;                                                 &lt;i class=&quot;fa fa-btn fa-user&quot;&gt;&lt;\/i&gt;Follow                                             &lt;\/button&gt;                                         &lt;\/form&gt;                                     &lt;\/td&gt;                                 @endif                             &lt;\/tr&gt;                         @endforeach                         &lt;\/tbody&gt;                     &lt;\/table&gt;                 &lt;\/div&gt;             &lt;\/div&gt;         &lt;\/div&gt;     &lt;\/div&gt; @endsection<\/code><\/pre>\n<p>  \u0422\u0435\u043f\u0435\u0440\u044c \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u043e\u0441\u0435\u0442\u0438\u0442\u044c \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 <code>\/users<\/code>, \u0447\u0442\u043e\u0431\u044b \u0443\u0432\u0438\u0434\u0435\u0442\u044c \u0441\u043f\u0438\u0441\u043e\u043a \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439.<\/p>\n<h3>Follow \u0438 Unfollow<\/h3>\n<p>  \u0412 <code>UsersController<\/code> \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u044e\u0442 \u043c\u0435\u0442\u043e\u0434\u044b <code>follow<\/code> \u0438 <code>unfollow<\/code>. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u0438\u0445, \u0447\u0442\u043e\u0431\u044b \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u044c \u044d\u0442\u0443 \u0447\u0430\u0441\u0442\u044c.<\/p>\n<pre><code class=\"php\">\/\/... class UsersController extends Controller {     \/\/...<\/code><\/pre>\n<p>  <\/p>\n<pre><code class=\"php\">    public function follow(User $user)     {         $follower = auth()-&gt;user();         if ($follower-&gt;id == $user-&gt;id) {             return back()-&gt;withError(&quot;You can't follow yourself&quot;);         }         if(!$follower-&gt;isFollowing($user-&gt;id)) {             $follower-&gt;follow($user-&gt;id);              \/\/ \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f             $user-&gt;notify(new UserFollowed($follower));              return back()-&gt;withSuccess(&quot;You are now friends with {$user-&gt;name}&quot;);         }         return back()-&gt;withError(&quot;You are already following {$user-&gt;name}&quot;);     }      public function unfollow(User $user)     {         $follower = auth()-&gt;user();         if($follower-&gt;isFollowing($user-&gt;id)) {             $follower-&gt;unfollow($user-&gt;id);             return back()-&gt;withSuccess(&quot;You are no longer friends with {$user-&gt;name}&quot;);         }         return back()-&gt;withError(&quot;You are not following {$user-&gt;name}&quot;);     } }<\/code><\/pre>\n<p>  \u0421 \u044d\u0442\u0438\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u043e\u043c \u043c\u044b \u0437\u0430\u043a\u043e\u043d\u0447\u0438\u043b\u0438. \u0422\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u043e\u0434\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0438 \u043e\u0442\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u043e\u0442 \u043d\u0438\u0445 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 <code>\/users<\/code>.<\/p>\n<h3>\u0423\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f<\/h3>\n<p>  Laravel \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 API \u0434\u043b\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439 \u043f\u043e \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u043c \u043a\u0430\u043d\u0430\u043b\u0430\u043c. \u042d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u0430\u044f \u043f\u043e\u0447\u0442\u0430, SMS, \u0432\u0435\u0431-\u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u0438 \u043b\u044e\u0431\u044b\u0435 \u0434\u0440\u0443\u0433\u0438\u0435 \u0442\u0438\u043f\u044b \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u044b \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043a\u043b\u0430\u0441\u0441\u0430 <a href=\"https:\/\/laravel.com\/docs\/5.4\/notifications\">Notification<\/a>.<\/p>\n<p>  \u0423 \u043d\u0430\u0441 \u0431\u0443\u0434\u0435\u0442 \u0434\u0432\u0430 \u0442\u0438\u043f\u0430 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439:<\/p>\n<ul>\n<li>\u0423\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435 \u043e \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0435: \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e, \u043a\u043e\u0433\u0434\u0430 \u043d\u0430 \u043d\u0435\u0433\u043e \u043f\u043e\u0434\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0434\u0440\u0443\u0433\u043e\u0439 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c<\/li>\n<li>\u0423\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435 \u043e \u043f\u043e\u0441\u0442\u0435: \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u043e\u0434\u043f\u0438\u0441\u0447\u0438\u043a\u0430\u043c \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u043f\u0440\u0438 \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438 \u043d\u043e\u0432\u043e\u0433\u043e \u043f\u043e\u0441\u0442\u0430.<\/li>\n<\/ul>\n<p>  <\/p>\n<h3>\u0423\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435 \u043e \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0435<\/h3>\n<p>  \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f artisan-\u043a\u043e\u043c\u0430\u043d\u0434\u044b, \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u044e \u0434\u043b\u044f \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439:<\/p>\n<pre><code class=\"php\">php artisan notifications:table<\/code><\/pre>\n<p>  \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u043c \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u044e \u0438 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u044d\u0442\u0443 \u0442\u0430\u0431\u043b\u0438\u0446\u0443.<\/p>\n<pre><code class=\"php\">php artisan migrate<\/code><\/pre>\n<p>  \u041c\u044b \u043d\u0430\u0447\u043d\u0435\u043c \u0441 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439 \u043e \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0435. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u043c \u044d\u0442\u0443 \u043a\u043e\u043c\u0430\u043d\u0434\u0443 \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043a\u043b\u0430\u0441\u0441\u0430 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439:<\/p>\n<pre><code class=\"php\">php artisan make:notification UserFollowed<\/code><\/pre>\n<p>  \u0417\u0430\u0442\u0435\u043c \u043c\u044b \u043c\u043e\u0434\u0438\u0444\u0438\u0446\u0438\u0440\u0443\u0435\u043c \u0444\u0430\u0439\u043b \u043a\u043b\u0430\u0441\u0441\u0430 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u044b \u0442\u043e\u043b\u044c\u043a\u043e \u0447\u0442\u043e \u0441\u043e\u0437\u0434\u0430\u043b\u0438:<\/p>\n<pre><code class=\"php\">class UserFollowed extends Notification implements ShouldQueue {     use Queueable;      protected $follower;      public function __construct(User $follower)     {         $this-&gt;follower = $follower;     }      public function via($notifiable)     {         return ['database'];     }      public function toDatabase($notifiable)     {         return [             'follower_id' =&gt; $this-&gt;follower-&gt;id,             'follower_name' =&gt; $this-&gt;follower-&gt;name,         ];     } }<\/code><\/pre>\n<p>  \u0421 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u044d\u0442\u0438\u0445 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u0441\u0442\u0440\u043e\u043a \u043a\u043e\u0434\u0430 \u043c\u044b \u0443\u0436\u0435 \u043c\u043e\u0436\u0435\u043c \u0434\u043e\u0441\u0442\u0438\u0447\u044c \u043c\u043d\u043e\u0433\u043e\u0433\u043e. \u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u043c\u044b \u0442\u0440\u0435\u0431\u0443\u0435\u043c, \u0447\u0442\u043e\u0431\u044b \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 <code>$follower<\/code> \u0431\u044b\u043b \u0432\u043d\u0435\u0434\u0440\u0435\u043d \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u044d\u0442\u043e\u0433\u043e \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f.<\/p>\n<p>  \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u043c\u0435\u0442\u043e\u0434 <code>via<\/code>, \u043c\u044b \u0433\u043e\u0432\u043e\u0440\u0438\u043c Laravel \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u044d\u0442\u043e \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435 \u0447\u0435\u0440\u0435\u0437 \u043a\u0430\u043d\u0430\u043b <code>database<\/code>. \u041a\u043e\u0433\u0434\u0430 Laravel \u0441\u0442\u0430\u043b\u043a\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0441 \u044d\u0442\u0438\u043c, \u043e\u043d \u0441\u043e\u0437\u0434\u0430\u0435\u0442 \u043d\u043e\u0432\u0443\u044e \u0437\u0430\u043f\u0438\u0441\u044c \u0432 \u0442\u0430\u0431\u043b\u0438\u0446\u0435 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439.<\/p>\n<p>  <code>user_id<\/code> \u0438 <code>type<\/code> \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438, \u043f\u043b\u044e\u0441 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0440\u0430\u0441\u0448\u0438\u0440\u0438\u0442\u044c \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u043c\u0438. \u0412\u043e\u0442 \u0434\u043b\u044f \u0447\u0435\u0433\u043e \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d <code>toDatabase<\/code>. \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u044b\u0439 \u043c\u0430\u0441\u0441\u0438\u0432 \u0431\u0443\u0434\u0435\u0442 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d \u0432 \u043f\u043e\u043b\u0435 <code>data<\/code> \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f.<\/p>\n<p>  \u0418, \u043d\u0430\u043a\u043e\u043d\u0435\u0446, \u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 <code>ShouldQueue<\/code>, Laravel \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043f\u043e\u043c\u0435\u0441\u0442\u0438\u0442 \u044d\u0442\u043e \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435 \u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u044c, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c\u0441\u044f \u0432 \u0444\u043e\u043d\u043e\u0432\u043e\u043c \u0440\u0435\u0436\u0438\u043c\u0435, \u0447\u0442\u043e \u0443\u0441\u043a\u043e\u0440\u0438\u0442 \u043e\u0442\u0432\u0435\u0442. \u042d\u0442\u043e \u0438\u043c\u0435\u0435\u0442 \u0441\u043c\u044b\u0441\u043b, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c HTTP-\u0432\u044b\u0437\u043e\u0432\u044b, \u043a\u043e\u0433\u0434\u0430 \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c Pusher \u043f\u043e\u0437\u0436\u0435.<\/p>\n<p>  \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435 \u043e \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0435 \u043d\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f.<\/p>\n<pre><code class=\"php\">\/\/ ... use App\\Notifications\\UserFollowed; class UsersController extends Controller {     \/\/ ...     public function follow(User $user)     {         $follower = auth()-&gt;user();         if ( ! $follower-&gt;isFollowing($user-&gt;id)) {             $follower-&gt;follow($user-&gt;id);              \/\/ \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u044d\u0442\u043e, \u0447\u0442\u043e\u0431\u044b \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435             $user-&gt;notify(new UserFollowed($follower));              return back()-&gt;withSuccess(&quot;You are now friends with {$user-&gt;name}&quot;);         }          return back()-&gt;withSuccess(&quot;You are already following {$user-&gt;name}&quot;);     }      \/\/... }<\/code><\/pre>\n<p>  \u041c\u044b \u043c\u043e\u0436\u0435\u043c \u0432\u044b\u0437\u0432\u0430\u0442\u044c \u043c\u0435\u0442\u043e\u0434 notify \u0434\u043b\u044f \u043c\u043e\u0434\u0435\u043b\u0438 User, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043e\u043d\u0430 \u0443\u0436\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u0447\u0435\u0440\u0442\u0443 Notifiable.<\/p>\n<p>  \u041b\u044e\u0431\u0430\u044f \u043c\u043e\u0434\u0435\u043b\u044c, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u0432\u044b \u0445\u043e\u0442\u0438\u0442\u0435 \u0443\u0432\u0435\u0434\u043e\u043c\u0438\u0442\u044c, \u0434\u043e\u043b\u0436\u043d\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0435\u0435 \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u043c\u0435\u0442\u043e\u0434\u0443 notify.<\/p>\n<p>  <b>\u041e\u0442\u043c\u0435\u0447\u0430\u0435\u043c \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435 \u043a\u0430\u043a \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u043d\u043d\u043e\u0435<\/b><\/p>\n<p>  \u0423\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u0431\u0443\u0434\u0443\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u0443\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u0438 \u0441\u0441\u044b\u043b\u043a\u0443 \u043d\u0430 \u0440\u0435\u0441\u0443\u0440\u0441. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440: \u043a\u043e\u0433\u0434\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435 \u043e \u043d\u043e\u0432\u043e\u043c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0438, \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435 \u0434\u043e\u043b\u0436\u043d\u043e \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0432\u043d\u044b\u0439 \u0442\u0435\u043a\u0441\u0442, \u043f\u0435\u0440\u0435\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u043d\u0430 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u043f\u0440\u0438 \u043d\u0430\u0436\u0430\u0442\u0438\u0438 \u0438 \u043f\u043e\u043c\u0435\u0447\u0430\u0442\u044c\u0441\u044f \u043a\u0430\u043a \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u043d\u043d\u043e\u0435.<\/p>\n<p>  \u041c\u044b \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u043c\u0441\u044f \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043f\u0440\u043e\u0441\u043b\u043e\u0439\u043a\u0443, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c, \u0435\u0441\u0442\u044c \u043b\u0438 \u0432 \u0437\u0430\u043f\u0440\u043e\u0441\u0435 \u0432\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u0435 <code>?read=notification_id<\/code> \u0438 \u043f\u043e\u043c\u0435\u0447\u0430\u0435\u0442 \u0435\u0433\u043e \u043a\u0430\u043a \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u043d\u043d\u043e\u0435.<\/p>\n<p>  \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u044d\u0442\u0443 \u043f\u0440\u043e\u0441\u043b\u043e\u0439\u043a\u0443 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u043a\u043e\u043c\u0430\u043d\u0434\u044b:<\/p>\n<pre><code class=\"php\">php artisan make:middleware MarkNotificationAsRead<\/code><\/pre>\n<p>  \u0417\u0430\u0442\u0435\u043c \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u043e\u043c\u0435\u0441\u0442\u0438\u043c \u044d\u0442\u043e\u0442 \u043a\u043e\u0434 \u0432 \u043c\u0435\u0442\u043e\u0434 <code>handle<\/code> \u043f\u0440\u043e\u0441\u043b\u043e\u0439\u043a\u0438:<\/p>\n<pre><code class=\"php\">class MarkNotificationAsRead {     public function handle($request, Closure $next)     {         if($request-&gt;has('read')) {             $notification = $request-&gt;user()-&gt;notifications()-&gt;where('id', $request-&gt;read)-&gt;first();             if($notification) {                 $notification-&gt;markAsRead();             }         }         return $next($request);     } }<\/code><\/pre>\n<p>  \u0414\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u043d\u0430\u0448\u0430 \u043f\u0440\u043e\u0441\u043b\u043e\u0439\u043a\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u043b\u0430\u0441\u044c \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0430, \u043c\u044b \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0435\u0435 \u0432 <code>$middlewareGroups<\/code>.<\/p>\n<pre><code class=\"php\">\/\/... class Kernel extends HttpKernel {     \/\/...     protected $middlewareGroups = [         'web' =&gt; [             \/\/...             \\App\\Http\\Middleware\\MarkNotificationAsRead::class,         ],         \/\/ ...     ];     \/\/... }<\/code><\/pre>\n<p>  \u041f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0433\u043e \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0437\u0430\u0439\u043c\u0435\u043c\u0441\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435\u043c \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439.<\/p>\n<h3>\u041e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439<\/h3>\n<p>  \u041c\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0441\u043f\u0438\u0441\u043e\u043a \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f AJAX, \u0430 \u0437\u0430\u0442\u0435\u043c \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0435\u0433\u043e \u0432 \u0440\u0435\u0436\u0438\u043c\u0435 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e Pusher. \u0412\u043e-\u043f\u0435\u0440\u0432\u044b\u0445, \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043c\u0435\u0442\u043e\u0434 <code>notifications<\/code> \u0432 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440:<\/p>\n<pre><code class=\"php\">\/\/ ... class UsersController extends Controller {     \/\/ ...     public function notifications()     {         return auth()-&gt;user()-&gt;unreadNotifications()-&gt;limit(5)-&gt;get()-&gt;toArray();     } }<\/code><\/pre>\n<p>  \u042d\u0442\u043e\u0442 \u043a\u043e\u0434 \u0432\u0435\u0440\u043d\u0435\u0442 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0435 5 \u043d\u0435\u043f\u0440\u043e\u0447\u0438\u0442\u0430\u043d\u043d\u044b\u0445 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439. \u041d\u0430\u043c \u043f\u0440\u043e\u0441\u0442\u043e \u043d\u0443\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043c\u0430\u0440\u0448\u0440\u0443\u0442, \u0447\u0442\u043e\u0431\u044b \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0435\u0433\u043e \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u043c.<\/p>\n<pre><code class=\"php\">\/\/... Route::group([ 'middleware' =&gt; 'auth' ], function () {     \/\/ ...     Route::get('\/notifications', 'UsersController@notifications'); });<\/code><\/pre>\n<p>  \u0422\u0435\u043f\u0435\u0440\u044c \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0432\u044b\u043f\u0430\u0434\u0430\u044e\u0449\u0438\u0439 \u0441\u043f\u0438\u0441\u043e\u043a \u0434\u043b\u044f \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439 \u0432 \u0448\u0430\u043f\u043a\u0435.<\/p>\n<pre><code class=\"php\">&lt;head&gt;     &lt;!-- \/\/ ... \/\/ --&gt;     &lt;!-- Scripts --&gt;     &lt;script&gt;         window.Laravel = &lt;?php echo json_encode([             'csrfToken' =&gt; csrf_token(),         ]); ?&gt;     &lt;\/script&gt;     &lt;!-- \u042d\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442 id \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u043c \u0432 JavaScript --&gt;     @if(!auth()-&gt;guest())         &lt;script&gt;             window.Laravel.userId = &lt;?php echo auth()-&gt;user()-&gt;id; ?&gt;         &lt;\/script&gt;     @endif &lt;\/head&gt; &lt;body&gt;     &lt;!-- \/\/ ... \/\/ --&gt;     @if (Auth::guest())         &lt;li&gt;&lt;a href=&quot;{{ url('\/login') }}&quot;&gt;Login&lt;\/a&gt;&lt;\/li&gt;         &lt;li&gt;&lt;a href=&quot;{{ url('\/register') }}&quot;&gt;Register&lt;\/a&gt;&lt;\/li&gt;     @else         &lt;!-- \/\/ add this dropdown \/\/ --&gt;         &lt;li class=&quot;dropdown&quot;&gt;             &lt;a class=&quot;dropdown-toggle&quot; id=&quot;notifications&quot; data-toggle=&quot;dropdown&quot; aria-haspopup=&quot;true&quot; aria-expanded=&quot;true&quot;&gt;                 &lt;span class=&quot;glyphicon glyphicon-user&quot;&gt;&lt;\/span&gt;             &lt;\/a&gt;             &lt;ul class=&quot;dropdown-menu&quot; aria-labelledby=&quot;notificationsMenu&quot; id=&quot;notificationsMenu&quot;&gt;                 &lt;li class=&quot;dropdown-header&quot;&gt;No notifications&lt;\/li&gt;             &lt;\/ul&gt;         &lt;\/li&gt; &lt;!-- \/\/ ... \/\/ --&gt;<\/code><\/pre>\n<p>  \u041c\u044b \u0442\u0430\u043a\u0436\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u043b\u0438 \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u0443\u044e \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e <code>window.Laravel.userId<\/code> \u0432 \u0441\u043a\u0440\u0438\u043f\u0442, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c ID \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f.<\/p>\n<h3>JavaScript \u0438 SASS<\/h3>\n<p>  \u041c\u044b \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u043c\u0441\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c Laravel Mix \u0434\u043b\u044f \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438 JavaScript \u0438 SASS. \u0412\u043e-\u043f\u0435\u0440\u0432\u044b\u0445, \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c npm-\u043f\u0430\u043a\u0435\u0442\u044b.<\/p>\n<pre><code class=\"php\">npm install<\/code><\/pre>\n<p>  \u0422\u0435\u043f\u0435\u0440\u044c \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u044d\u0442\u043e\u0442 \u043a\u043e\u0434 \u0432 <code>app.js<\/code>:<\/p>\n<pre><code class=\"javascript\">window._ = require('lodash'); window.$ = window.jQuery = require('jquery'); require('bootstrap-sass'); var notifications = []; const NOTIFICATION_TYPES = {     follow: 'App\\\\Notifications\\\\UserFollowed' };<\/code><\/pre>\n<p>  \u042d\u0442\u043e \u0432\u0441\u0435\u0433\u043e \u043b\u0438\u0448\u044c \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f. \u041c\u044b \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u043c\u0441\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c notifications \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0432\u0441\u0435\u0445 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439, \u043d\u0435\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e \u043e\u0442 \u0442\u043e\u0433\u043e, \u0438\u0437\u0432\u043b\u0435\u043a\u0430\u044e\u0442\u0441\u044f \u043b\u0438 \u043e\u043d\u0438 \u0447\u0435\u0440\u0435\u0437 AJAX \u0438\u043b\u0438 Pusher.<\/p>\n<p>  \u041a\u0430\u043a \u0432\u044b, \u043d\u0430\u0432\u0435\u0440\u043d\u043e\u0435, \u0443\u0436\u0435 \u0434\u043e\u0433\u0430\u0434\u0430\u043b\u0438\u0441\u044c, <code>NOTIFICATION_TYPES<\/code> \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0442\u0438\u043f\u044b \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439.<\/p>\n<p>  \u0422\u0435\u043f\u0435\u0440\u044c \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u043c (\u201cGET\u201d) \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u0447\u0435\u0440\u0435\u0437 AJAX.<\/p>\n<pre><code class=\"javascript\">\/\/... $(document).ready(function() {     \/\/ \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c, \u0435\u0441\u0442\u044c \u043b\u0438 \u0432\u043e\u0448\u0435\u0434\u0448\u0438\u0439 \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c     if(Laravel.userId) {         $.get('\/notifications', function (data) {             addNotifications(data, &quot;#notifications&quot;);         });     } }); function addNotifications(newNotifications, target) {     notifications = _.concat(notifications, newNotifications);     \/\/ \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0435 5 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439     notifications.slice(0, 5);     showNotifications(notifications, target); }<\/code><\/pre>\n<p>  \u0411\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u044d\u0442\u043e\u043c\u0443 \u043a\u043e\u0434\u0443 \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0435 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u043e\u0442 \u043d\u0430\u0448\u0435\u0433\u043e API \u0438 \u043f\u043e\u043c\u0435\u0449\u0430\u0435\u043c \u0438\u0445 \u0432 \u0440\u0430\u0441\u043a\u0440\u044b\u0432\u0430\u044e\u0449\u0438\u0439\u0441\u044f \u0441\u043f\u0438\u0441\u043e\u043a.<\/p>\n<p>  \u0412\u043d\u0443\u0442\u0440\u0438 <code>addNotifications<\/code> \u043c\u044b \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u044f\u0435\u043c \u0438\u043c\u0435\u044e\u0449\u0438\u0435\u0441\u044f \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u0441 \u043d\u043e\u0432\u044b\u043c\u0438, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f <a href=\"https:\/\/www.sitepoint.com\/tag\/lodash\/\">Lodash<\/a>, \u0438 \u0431\u0435\u0440\u0435\u043c \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0435 5, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0438 \u0431\u0443\u0434\u0443\u0442 \u043f\u043e\u043a\u0430\u0437\u0430\u043d\u044b.<\/p>\n<p>  \u041d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0435\u0449\u0435 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u0439, \u0447\u0442\u043e\u0431\u044b \u0437\u0430\u043a\u043e\u043d\u0447\u0438\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0443.<\/p>\n<pre><code class=\"javascript\">\/\/... function showNotifications(notifications, target) {     if(notifications.length) {         var htmlElements = notifications.map(function (notification) {             return makeNotification(notification);         });         $(target + 'Menu').html(htmlElements.join(''));         $(target).addClass('has-notifications')     } else {         $(target + 'Menu').html('&lt;li class=&quot;dropdown-header&quot;&gt;No notifications&lt;\/li&gt;');         $(target).removeClass('has-notifications');     } }<\/code><\/pre>\n<p>  \u042d\u0442\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0441\u043e\u0437\u0434\u0430\u0435\u0442 \u0441\u0442\u0440\u043e\u043a\u0443 \u0432\u0441\u0435\u0445 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439 \u0438 \u043f\u043e\u043c\u0435\u0449\u0430\u0435\u0442 \u0435\u0435 \u0432 \u0440\u0430\u0441\u043a\u0440\u044b\u0432\u0430\u044e\u0449\u0438\u0439\u0441\u044f \u0441\u043f\u0438\u0441\u043e\u043a.<br \/>  \u0415\u0441\u043b\u0438 \u043d\u0435 \u0431\u044b\u043b\u043e \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043e \u043d\u0438 \u043e\u0434\u043d\u043e\u0433\u043e \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f, \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u0442\u0441\u044f \u043f\u0440\u043e\u0441\u0442\u043e \u00ab\u041d\u0435\u0442 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439\u00bb.<\/p>\n<p>  \u041e\u043d\u0430 \u0442\u0430\u043a\u0436\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442 \u043a\u043b\u0430\u0441\u0441 \u043a \u0432\u044b\u043f\u0430\u0434\u0430\u044e\u0449\u0435\u0439 \u043a\u043d\u043e\u043f\u043a\u0435, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u0440\u043e\u0441\u0442\u043e \u0438\u0437\u043c\u0435\u043d\u0438\u0442 \u0441\u0432\u043e\u0439 \u0446\u0432\u0435\u0442 \u043f\u0440\u0438 \u043d\u0430\u043b\u0438\u0447\u0438\u0438 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439. \u041d\u0435\u043c\u043d\u043e\u0433\u043e \u043d\u0430\u043f\u043e\u043c\u0438\u043d\u0430\u0435\u0442 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u043d\u0430 Github.<\/p>\n<p>  \u041d\u0430\u043a\u043e\u043d\u0435\u0446, \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0441\u0442\u0440\u043e\u043a \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439.<\/p>\n<pre><code class=\"javascript\">\/\/... \/\/ \u0421\u0434\u0435\u043b\u0430\u0442\u044c \u0441\u0442\u0440\u043e\u043a\u0443 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f function makeNotification(notification) {     var to = routeNotification(notification);     var notificationText = makeNotificationText(notification);     return '&lt;li&gt;&lt;a href=&quot;' + to + '&quot;&gt;' + notificationText + '&lt;\/a&gt;&lt;\/li&gt;'; } \/\/ \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043c\u0430\u0440\u0448\u0440\u0443\u0442 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0435\u0433\u043e \u0442\u0438\u043f\u0430 function routeNotification(notification) {     var to = '?read=' + notification.id;     if(notification.type === NOTIFICATION_TYPES.follow) {         to = 'users' + to;     }     return '\/' + to; } \/\/ \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0442\u0435\u043a\u0441\u0442 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0435\u0433\u043e \u0442\u0438\u043f\u0430 function makeNotificationText(notification) {     var text = '';     if(notification.type === NOTIFICATION_TYPES.follow) {         const name = notification.data.follower_name;         text += '&lt;strong&gt;' + name + '&lt;\/strong&gt; followed you';     }     return text; } <\/code><\/pre>\n<p>  \u0422\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u043f\u0440\u043e\u0441\u0442\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u044d\u0442\u043e \u0432 \u043d\u0430\u0448 \u0444\u0430\u0439\u043b <code>app.scss<\/code>:<\/p>\n<pre><code class=\"php\">\/\/...  #notifications.has-notifications {   color: #bf5329 }<\/code><\/pre>\n<p>  \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0441\u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u0443\u0435\u043c \u0430\u0441\u0441\u0435\u0442\u044b:<\/p>\n<pre><code class=\"php\">npm run dev<\/code><\/pre>\n<p>  \u0422\u0435\u043f\u0435\u0440\u044c \u0435\u0441\u043b\u0438 \u0432\u044b \u043f\u043e\u043f\u044b\u0442\u0430\u0435\u0442\u0435\u0441\u044c \u043f\u043e\u0434\u043f\u0438\u0441\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f, \u043e\u043d \u043f\u043e\u043b\u0443\u0447\u0438\u0442 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435. \u041a\u043e\u0433\u0434\u0430 \u043e\u043d \u043a\u043b\u0438\u043a\u043d\u0435\u0442 \u043f\u043e \u043d\u0435\u043c\u0443, \u043e\u043d \u0431\u0443\u0434\u0435\u0442 \u043f\u0435\u0440\u0435\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d \u0432 <code>\/users<\/code>, \u0430 \u0441\u0430\u043c\u043e \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435 \u0438\u0441\u0447\u0435\u0437\u0430\u0435\u0442.<\/p>\n<h2>\u0423\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435 \u043e \u043d\u043e\u0432\u043e\u043c \u043f\u043e\u0441\u0442\u0435<\/h2>\n<p>  \u041c\u044b \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u043c\u0441\u044f \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u044f\u0442\u044c \u043f\u043e\u0434\u043f\u0438\u0441\u0447\u0438\u043a\u043e\u0432, \u043a\u043e\u0433\u0434\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043f\u0443\u0431\u043b\u0438\u043a\u0443\u0435\u0442 \u043d\u043e\u0432\u044b\u0439 \u043f\u043e\u0441\u0442.<\/p>\n<p>  \u041d\u0430\u0447\u043d\u0435\u043c \u0441 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043a\u043b\u0430\u0441\u0441\u0430 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439.<\/p>\n<pre><code class=\"php\">php artisan make:notification NewPost<\/code><\/pre>\n<p>  \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043c\u043e\u0434\u0438\u0444\u0438\u0446\u0438\u0440\u0443\u0435\u043c \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<pre><code class=\"php\">\/\/ .. use App\\Post; use App\\User; class NewArticle extends Notification implements ShouldQueue {     \/\/ ..     protected $following;     protected $post;     public function __construct(User $following, Post $post)     {         $this-&gt;following = $following;         $this-&gt;post = $post;     }     public function via($notifiable)     {         return ['database'];     }     public function toDatabase($notifiable)     {         return [             'following_id' =&gt; $this-&gt;following-&gt;id,             'following_name' =&gt; $this-&gt;following-&gt;name,             'post_id' =&gt; $this-&gt;post-&gt;id,         ];     } }<\/code><\/pre>\n<p>  \u0414\u0430\u043b\u0435\u0435 \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435. \u0415\u0441\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0441\u043f\u043e\u0441\u043e\u0431\u043e\u0432 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u044d\u0442\u043e.<\/p>\n<p>  \u041c\u043d\u0435 \u043d\u0440\u0430\u0432\u0438\u0442\u0441\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043d\u0430\u0431\u043b\u044e\u0434\u0430\u0442\u0435\u043b\u0438 Eloquent.<\/p>\n<p>  \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043d\u0430\u0431\u043b\u044e\u0434\u0430\u0442\u0435\u043b\u044f \u0437\u0430 Post \u0438 \u0431\u0443\u0434\u0435\u043c \u0441\u043b\u0443\u0448\u0430\u0442\u044c \u0435\u0433\u043e \u0441\u043e\u0431\u044b\u0442\u0438\u044f. \u041c\u044b \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043d\u043e\u0432\u044b\u0439 \u043a\u043b\u0430\u0441\u0441: <code>app\/Observers\/PostObserver.php<\/code><\/p>\n<pre><code class=\"php\">namespace App\\Observers; use App\\Notifications\\NewPost; use App\\Post; class PostObserver {     public function created(Post $post)     {         $user = $post-&gt;user;         foreach ($user-&gt;followers as $follower) {             $follower-&gt;notify(new NewPost($user, $post));         }     } }<\/code><\/pre>\n<p>  \u0417\u0430\u0442\u0435\u043c \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u043c \u043d\u0430\u0431\u043b\u044e\u0434\u0430\u0442\u0435\u043b\u044f \u0432 <code>AppServiceProvider<\/code>:<\/p>\n<pre><code class=\"php\">\/\/... use App\\Observers\\PostObserver; use App\\Post; class AppServiceProvider extends ServiceProvider {     \/\/...     public function boot()     {         Post::observe(PostObserver::class);     }     \/\/... }<\/code><\/pre>\n<p>  \u0422\u0435\u043f\u0435\u0440\u044c \u043d\u0430\u043c \u043f\u0440\u043e\u0441\u0442\u043e \u043d\u0443\u0436\u043d\u043e \u043e\u0442\u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0432 JS:<\/p>\n<pre><code class=\"javascript\">\/\/ ... const NOTIFICATION_TYPES = {     follow: 'App\\\\Notifications\\\\UserFollowed',     newPost: 'App\\\\Notifications\\\\NewPost' }; \/\/... function routeNotification(notification) {     var to = `?read=${notification.id}`;     if(notification.type === NOTIFICATION_TYPES.follow) {         to = 'users' + to;     } else if(notification.type === NOTIFICATION_TYPES.newPost) {         const postId = notification.data.post_id;         to = `posts\/${postId}` + to;     }     return '\/' + to; } function makeNotificationText(notification) {     var text = '';     if(notification.type === NOTIFICATION_TYPES.follow) {         const name = notification.data.follower_name;         text += `&lt;strong&gt;${name}&lt;\/strong&gt; followed you`;     } else if(notification.type === NOTIFICATION_TYPES.newPost) {         const name = notification.data.following_name;         text += `&lt;strong&gt;${name}&lt;\/strong&gt; published a post`;     }     return text; }<\/code><\/pre>\n<p>  \u0418 \u0432\u0443\u0430\u043b\u044f! \u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438 \u043f\u043e\u043b\u0443\u0447\u0430\u044e\u0442 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u043e \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0430\u0445 \u0438 \u043d\u043e\u0432\u044b\u0445 \u043f\u043e\u0441\u0442\u0430\u0445! \u041f\u043e\u043f\u0440\u043e\u0431\u0443\u0439\u0442\u0435 \u0441\u0430\u043c\u0438!<\/p>\n<h3>\u0412\u044b\u0445\u043e\u0434\u0438\u043c \u0432 \u0440\u0435\u0436\u0438\u043c \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0441 Pusher<\/h3>\n<p>  \u041f\u0440\u0438\u0448\u043b\u043e \u0432\u0440\u0435\u043c\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c Pusher \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439 \u0432 \u0440\u0435\u0436\u0438\u043c\u0435 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0447\u0435\u0440\u0435\u0437 \u0432\u0435\u0431-\u0441\u043e\u043a\u0435\u0442\u044b.<\/p>\n<p>  \u0417\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0439\u0442\u0435 \u0431\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u0443\u044e \u0443\u0447\u0435\u0442\u043d\u0443\u044e \u0437\u0430\u043f\u0438\u0441\u044c Pusher \u043d\u0430 <a href=\"https:\/\/pusher.com\/\">pusher.com<\/a> \u0438 \u0441\u043e\u0437\u0434\u0430\u0439\u0442\u0435 \u043d\u043e\u0432\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435.<\/p>\n<pre><code class=\"php\">... BROADCAST_DRIVER=pusher PUSHER_KEY= PUSHER_SECRET= PUSHER_APP_ID=<\/code><\/pre>\n<p>  \u0417\u0430\u0434\u0430\u0439\u0442\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0441\u0432\u043e\u0435\u0439 \u0443\u0447\u0435\u0442\u043d\u043e\u0439 \u0437\u0430\u043f\u0438\u0441\u0438 \u0432 \u0444\u0430\u0439\u043b\u0435 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 <code>broadcasting<\/code>:<\/p>\n<pre><code class=\"php\">\/\/...     'connections' =&gt; [             'pusher' =&gt; [                 \/\/...                 'options' =&gt; [                     'cluster' =&gt; 'eu',                     'encrypted' =&gt; true                 ],             ],     \/\/...<\/code><\/pre>\n<p>  \u0417\u0430\u0442\u0435\u043c \u043c\u044b \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u043c <code>App\\Providers\\BroadcastServiceProvider<\/code> \u0432 \u043c\u0430\u0441\u0441\u0438\u0432\u0435 <code>providers<\/code>.<\/p>\n<pre><code class=\"php\">\/\/ ... 'providers' =&gt; [     \/\/ ...     App\\Providers\\BroadcastServiceProvider     \/\/... ], \/\/...<\/code><\/pre>\n<p>  \u0422\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c PHP SDK \u0438 Laravel Echo \u043e\u0442 Pusher:<\/p>\n<pre><code class=\"php\">composer require pusher\/pusher-php-server npm install --save laravel-echo pusher-js<\/code><\/pre>\n<p>  \u041d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439 \u0434\u043b\u044f \u0442\u0440\u0430\u043d\u0441\u043b\u044f\u0446\u0438\u0438. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043c\u043e\u0434\u0438\u0444\u0438\u0446\u0438\u0440\u0443\u0435\u043c \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435 <code>UserFollowed<\/code>:<\/p>\n<pre><code class=\"php\">\/\/... class UserFollowed extends Notification implements ShouldQueue {     \/\/ ..     public function via($notifiable)     {         return ['database', 'broadcast'];     }     \/\/...     public function toArray($notifiable)     {         return [             'id' =&gt; $this-&gt;id,             'read_at' =&gt; null,             'data' =&gt; [                 'follower_id' =&gt; $this-&gt;follower-&gt;id,                 'follower_name' =&gt; $this-&gt;follower-&gt;name,             ],         ];     } }<\/code><\/pre>\n<p>  \u0418 <code>NewPost<\/code>:<\/p>\n<pre><code class=\"php\">\/\/... class NewPost extends Notification implements ShouldQueue {     \/\/...     public function via($notifiable)     {         return ['database', 'broadcast'];     }     \/\/...     public function toArray($notifiable)     {         return [             'id' =&gt; $this-&gt;id,             'read_at' =&gt; null,             'data' =&gt; [                 'following_id' =&gt; $this-&gt;following-&gt;id,                 'following_name' =&gt; $this-&gt;following-&gt;name,                 'post_id' =&gt; $this-&gt;post-&gt;id,             ],         ];     } }<\/code><\/pre>\n<p>  \u041f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0435, \u0447\u0442\u043e \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c, \u044d\u0442\u043e \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u043d\u0430\u0448 JS. \u041e\u0442\u043a\u0440\u043e\u0439\u0442\u0435 <code>app.js<\/code> \u0438 \u0434\u043e\u0431\u0430\u0432\u044c\u0442\u0435 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u043a\u043e\u0434<\/p>\n<pre><code class=\"javascript\">\/\/ ... window.Pusher = require('pusher-js'); import Echo from &quot;laravel-echo&quot;; window.Echo = new Echo({     broadcaster: 'pusher',     key: 'your-pusher-key',     cluster: 'eu',     encrypted: true }); var notifications = []; \/\/... $(document).ready(function() {     if(Laravel.userId) {         \/\/...         window.Echo.private(`App.User.${Laravel.userId}`)             .notification((notification) =&gt; {                 addNotifications([notification], '#notifications');             });     } });<\/code><\/pre>\n<p>  \u0418 \u043d\u0430 \u044d\u0442\u043e\u043c \u0432\u0441\u0435. \u0423\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0432 \u0440\u0435\u0436\u0438\u043c\u0435 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438. \u0422\u0435\u043f\u0435\u0440\u044c \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u043e\u0438\u0433\u0440\u0430\u0442\u044c \u0441 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435\u043c \u0438 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c, \u043a\u0430\u043a \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f.<\/p>\n<h2>\u0412\u044b\u0432\u043e\u0434<\/h2>\n<p>  \u0423 Pusher \u043e\u0447\u0435\u043d\u044c \u0443\u0434\u043e\u0431\u043d\u044b\u0439 API, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0434\u0435\u043b\u0430\u0435\u0442 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u0441\u043e\u0431\u044b\u0442\u0438\u0439 \u0432 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u043c \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u043d\u0435\u0432\u0435\u0440\u043e\u044f\u0442\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u043e\u0439. \u0412 \u0441\u043e\u0447\u0435\u0442\u0430\u043d\u0438\u0438 \u0441 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f\u043c\u0438 Laravel \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u043f\u043e \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u043c \u043a\u0430\u043d\u0430\u043b\u0430\u043c (\u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u0430\u044f \u043f\u043e\u0447\u0442\u0430, SMS, Slack \u0438 \u0442. \u0434.) \u0438\u0437 \u043e\u0434\u043d\u043e\u0433\u043e \u043c\u0435\u0441\u0442\u0430. \u0412 \u044d\u0442\u043e\u043c \u0440\u0443\u043a\u043e\u0432\u043e\u0434\u0441\u0442\u0432\u0435 \u043c\u044b \u0434\u043e\u0431\u0430\u0432\u0438\u043b\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0434\u043b\u044f \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u043d\u0438\u044f \u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0432 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0431\u043b\u043e\u0433 \u0438 \u0443\u0441\u043e\u0432\u0435\u0440\u0448\u0435\u043d\u0441\u0442\u0432\u043e\u0432\u0430\u043b\u0438 \u0435\u0433\u043e \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0432\u044b\u0448\u0435\u0443\u043f\u043e\u043c\u044f\u043d\u0443\u0442\u044b\u0445 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043b\u0430\u0432\u043d\u044b\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b \u0432 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u043c \u0432\u0440\u0435\u043c\u0435\u043d\u0438.<\/p>\n<p>  \u0423 Pusher \u0438 Laravel \u0435\u0441\u0442\u044c \u0433\u043e\u0440\u0430\u0437\u0434\u043e \u0431\u043e\u043b\u044c\u0448\u0435 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439: \u0432 \u0442\u0430\u043d\u0434\u0435\u043c\u0435 \u0441\u0435\u0440\u0432\u0438\u0441\u044b \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c pub\/sub-\u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0432 \u0440\u0435\u0436\u0438\u043c\u0435 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u043d\u0430 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u044b, \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u044b\u0435 \u0442\u0435\u043b\u0435\u0444\u043e\u043d\u044b \u0438 IOT-\u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430. \u0421\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u0442\u0430\u043a\u0436\u0435 API \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f online\/offline \u0441\u0442\u0430\u0442\u0443\u0441\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439.<\/p>\n<p>  \u041f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u044c\u0442\u0435\u0441\u044c \u0441 \u0438\u0445 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0435\u0439 (<a href=\"https:\/\/pusher.com\/docs\">Pusher docs<\/a>, <a href=\"https:\/\/pusher.com\/tutorials\">Pusher tutorials<\/a>, <a href=\"https:\/\/laravel.com\/docs\/5.4\/notifications\">Laravel docs<\/a>), \u0447\u0442\u043e\u0431\u044b \u0443\u0437\u043d\u0430\u0442\u044c \u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0443\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u0438\u0445 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 \u0438 \u0438\u0441\u0442\u0438\u043d\u043d\u043e\u043c \u043f\u043e\u0442\u0435\u043d\u0446\u0438\u0430\u043b\u0435.<\/p>\n<p>  \u0415\u0441\u043b\u0438 \u0443 \u0432\u0430\u0441 \u0435\u0441\u0442\u044c \u043a\u0430\u043a\u0438\u0435-\u043b\u0438\u0431\u043e \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0438, \u0432\u043e\u043f\u0440\u043e\u0441\u044b \u0438\u043b\u0438 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0430\u0446\u0438\u0438, \u043d\u0435 \u0441\u0442\u0435\u0441\u043d\u044f\u0439\u0442\u0435\u0441\u044c \u0434\u0435\u043b\u0438\u0442\u044c\u0441\u044f \u0438\u043c\u0438 \u0432 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u044f\u0445 \u043d\u0438\u0436\u0435!<\/p>\n<hr>\n<p>  <a href=\"https:\/\/otus.pw\/yZGW\/\">\u0423\u0437\u043d\u0430\u0442\u044c \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043e \u043a\u0443\u0440\u0441\u0435.<br \/>  <\/a>  <\/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\/496652\/\"> https:\/\/habr.com\/ru\/company\/otus\/blog\/496652\/<\/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\/496652\/\"><i><b>\u041f\u0435\u0440\u0435\u0432\u043e\u0434 \u0441\u0442\u0430\u0442\u044c\u0438 \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043b\u0435\u043d \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u043e \u0434\u043b\u044f \u0441\u0442\u0443\u0434\u0435\u043d\u0442\u043e\u0432 \u043a\u0443\u0440\u0441\u0430 <a href=\"https:\/\/otus.pw\/yZGW\/\">\u00abFramework Laravel\u00bb<\/a>.<\/b><\/i><\/p>\n<hr>\n<p>  \u0421\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0439 \u0432\u0435\u0431-\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043e\u0436\u0438\u0434\u0430\u0435\u0442 \u0431\u044b\u0442\u044c \u0438\u043d\u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u043c \u043e\u0431\u043e \u0432\u0441\u0435\u043c, \u0447\u0442\u043e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438. \u0412\u044b \u0431\u044b \u043d\u0435 \u0445\u043e\u0442\u0435\u043b\u0438 \u0431\u044b\u0442\u044c \u0442\u0435\u043c \u0432\u0435\u0431-\u0441\u0430\u0439\u0442\u043e\u043c, \u0443 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043d\u0435\u0442 \u0445\u043e\u0442\u044f \u0431\u044b \u0440\u0430\u0441\u043a\u0440\u044b\u0432\u0430\u044e\u0449\u0435\u0433\u043e\u0441\u044f \u0441\u043f\u0438\u0441\u043a\u0430 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0442\u0435\u043f\u0435\u0440\u044c \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0439\u0442\u0438 \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430 \u0432\u0441\u0435\u0445 \u0441\u0430\u0439\u0442\u0430\u0445 \u0441\u043e\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0445 \u0441\u0435\u0442\u0435\u0439, \u043d\u043e \u0438 \u0432\u043e\u043e\u0431\u0449\u0435 \u043f\u043e\u0432\u0441\u044e\u0434\u0443 \u0432 \u043d\u0430\u0448\u0438 \u0434\u043d\u0438.<\/p>\n<p>  \u041a \u0441\u0447\u0430\u0441\u0442\u044c\u044e, \u0441 Laravel \u0438 <a href=\"https:\/\/pusher.com\/\">Pusher<\/a> \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u044d\u0442\u043e\u0433\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u0430 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u0430.<\/p>\n<h3>\u0423\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u0432 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u043c \u0432\u0440\u0435\u043c\u0435\u043d\u0438<\/h3>\n<p>  \u0414\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0442\u044c \u043f\u043e\u043b\u043e\u0436\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u043e\u043f\u044b\u0442, \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u0434\u043e\u043b\u0436\u043d\u044b \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c\u0441\u044f \u0432 \u0440\u0435\u0436\u0438\u043c\u0435 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438. \u041e\u0434\u043d\u0438\u043c \u0438\u0437 \u043f\u043e\u0434\u0445\u043e\u0434\u043e\u0432 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043d\u0430\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 AJAX-\u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440 \u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u043d\u043e\u0432\u0435\u0439\u0448\u0438\u0445 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439, \u0435\u0441\u043b\u0438 \u0442\u0430\u043a\u043e\u0432\u044b\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0442.<\/p>\n<p>  \u041b\u0443\u0447\u0448\u0438\u043c \u043f\u043e\u0434\u0445\u043e\u0434\u043e\u043c \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0435\u0439 WebSockets \u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439 \u0432 \u043c\u043e\u043c\u0435\u043d\u0442 \u0438\u0445 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438. \u042d\u0442\u043e \u0438\u043c\u0435\u043d\u043d\u043e \u0442\u043e, \u0447\u0442\u043e \u043c\u044b \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u043c\u0441\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0432 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435.<\/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-301666","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/301666","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=301666"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/301666\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=301666"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=301666"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=301666"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}