{"id":499410,"date":"2026-10-20T13:36:14","date_gmt":"2026-10-20T10:36:14","guid":{"rendered":"https:\/\/savepearlharbor.com\/?p=499410"},"modified":"2026-10-20T13:36:14","modified_gmt":"2026-10-20T10:36:14","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=499410","title":{"rendered":"Rig: \u041a\u0430\u043a \u044f \u0441\u0434\u0435\u043b\u0430\u043b \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u043d\u0430 PHP \u0431\u0435\u0437 Node \u0438 \u0441\u0431\u043e\u0440\u0449\u0438\u043a\u0430"},"content":{"rendered":"<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u041f\u0440\u0438\u0432\u0435\u0442, \u0425\u0430\u0431\u0440! \u041f\u0438\u0448\u0443 \u0441\u0432\u043e\u044e \u043f\u0435\u0440\u0432\u0443\u044e \u0441\u0442\u0430\u0442\u044c\u044e. \u0423\u0436\u0435 \u0431\u043e\u043b\u044c\u0448\u0435 \u0434\u0435\u0441\u044f\u0442\u0438 \u043b\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u044e \u0441 PHP: \u0434\u0435\u043b\u0430\u044e \u0430\u0434\u043c\u0438\u043d\u043a\u0438, CRM, \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442-\u043c\u0430\u0433\u0430\u0437\u0438\u043d\u044b \u0438 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u0435 \u0441\u0438\u0441\u0442\u0435\u043c\u044b.<\/p>\n<p>\u041f\u043e\u0447\u0442\u0438 \u0432 \u043a\u0430\u0436\u0434\u043e\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u0440\u0430\u043d\u043e \u0438\u043b\u0438 \u043f\u043e\u0437\u0434\u043d\u043e \u043f\u043e\u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0437\u0430\u043f\u0440\u043e\u0441 \u00ab\u0447\u0442\u043e\u0431\u044b \u0431\u0435\u0437 \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438\u00bb. \u0418 \u0440\u044f\u0434\u043e\u043c \u0441 PHP \u0432\u044b\u0440\u0430\u0441\u0442\u0430\u0435\u0442 \u0432\u0442\u043e\u0440\u043e\u0439 \u043a\u0443\u0441\u043e\u043a: \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434 \u0441\u043e \u0441\u0431\u043e\u0440\u0449\u0438\u043a\u043e\u043c, <code>node_modules<\/code>, API \u043c\u0435\u0436\u0434\u0443 \u0434\u0432\u0443\u043c\u044f \u0447\u0430\u0441\u0442\u044f\u043c\u0438, \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u044f \u0432 \u0434\u0432\u0443\u0445 \u043c\u0435\u0441\u0442\u0430\u0445, \u0430 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0442\u043e \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435, \u0442\u043e \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435. \u041c\u0435\u043d\u044f \u044d\u0442\u043e \u0434\u043e\u0441\u0442\u0430\u043b\u043e, \u0438 \u044f \u0441\u043e\u0437\u0434\u0430\u043b rig. \u042d\u0442\u043e PHP-\u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a, \u0433\u0434\u0435 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u043e\u0442\u043a\u043b\u0438\u043a\u0430\u0435\u0442\u0441\u044f \u0441\u0440\u0430\u0437\u0443, \u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043e\u0441\u0442\u0430\u0451\u0442\u0441\u044f \u043e\u0431\u044b\u0447\u043d\u044b\u043c PHP-\u043f\u0440\u043e\u0435\u043a\u0442\u043e\u043c. \u0420\u0430\u0441\u0441\u043a\u0430\u0436\u0443, \u043a\u0430\u043a \u043e\u043d \u0443\u0441\u0442\u0440\u043e\u0435\u043d, \u0447\u0442\u043e \u0443\u0436\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0438 \u0433\u0434\u0435 \u0435\u0433\u043e \u043b\u0443\u0447\u0448\u0435 \u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c.<\/p>\n<h3>\u041a\u0430\u043a \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442<\/h3>\n<p>\u041e\u0434\u0438\u043d \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0436\u0438\u0432\u0451\u0442 \u0432 \u043e\u0434\u043d\u043e\u043c <code>.php<\/code>-\u0444\u0430\u0439\u043b\u0435. \u0421\u0432\u0435\u0440\u0445\u0443 \u043a\u043b\u0430\u0441\u0441 \u0441 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435\u043c \u0438 \u043b\u043e\u0433\u0438\u043a\u043e\u0439, \u043f\u043e\u0434 \u043d\u0438\u043c \u0448\u0430\u0431\u043b\u043e\u043d \u0438 \u0441\u0442\u0438\u043b\u0438.<\/p>\n<pre><code class=\"php\">&lt;?phpnamespace App\\Components;use Rig\\Attr\\{Action, Computed};use Rig\\Component;final class Counter extends Component{    public int $count = 0;    #[Computed('count * 2')]    public int $double;    #[Action(optimistic: 'count = count + 1')]    public function increment(): void    {        $this-&gt;count++;    }}?&gt;&lt;template&gt;  &lt;p&gt;{{ count }} \u00d7 2 = {{ double }}&lt;\/p&gt;  &lt;button @click=\"increment\"&gt;+&lt;\/button&gt;&lt;\/template&gt;&lt;style&gt;  p { font-size: 24px; }&lt;\/style&gt;<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><span class=\"sc-logo-wrapper\"><\/span><\/a><\/div><\/pre>\n<p>\u041d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u0435\u0433\u043e \u0432\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0442 \u0442\u0435\u0433\u043e\u043c:<\/p>\n<pre><code class=\"php\">&lt;?php $title = '\u0421\u0447\u0451\u0442\u0447\u0438\u043a'; ?&gt;&lt;h1&gt;\u0421\u0447\u0451\u0442\u0447\u0438\u043a&lt;\/h1&gt;&lt;Counter \/&gt;<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><span class=\"sc-logo-wrapper icon-only\"><\/span><\/a><\/div><\/pre>\n<p>\u0412\u043e\u0442 \u0447\u0442\u043e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442, \u043a\u043e\u0433\u0434\u0430 \u043d\u0430\u0436\u0438\u043c\u0430\u044e\u0442 \u00ab+\u00bb:<\/p>\n<ol>\n<li>\n<p>\u0427\u0438\u0441\u043b\u043e \u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f \u0441\u0440\u0430\u0437\u0443. \u041e\u043f\u0442\u0438\u043c\u0438\u0441\u0442\u0438\u0447\u043d\u043e\u0435 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435 <code>count = count + 1<\/code> \u0431\u0440\u0430\u0443\u0437\u0435\u0440 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u0441\u0430\u043c, \u043d\u0435 \u0434\u043e\u0436\u0438\u0434\u0430\u044f\u0441\u044c \u043e\u0442\u0432\u0435\u0442\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0430.<\/p>\n<\/li>\n<li>\n<p><code>\u00d72<\/code> \u043f\u0435\u0440\u0435\u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043c\u0433\u043d\u043e\u0432\u0435\u043d\u043d\u043e: <code>#[Computed('count * 2')]<\/code> \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0438 \u0432 PHP, \u0438 \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435.<\/p>\n<\/li>\n<li>\n<p>\u041d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440 \u0443\u0445\u043e\u0434\u0438\u0442 JSON-\u0437\u0430\u043f\u0440\u043e\u0441: \u00ab\u0443 \u044d\u0442\u043e\u0433\u043e Counter \u0441 \u0442\u0435\u043a\u0443\u0449\u0438\u043c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435\u043c \u0432\u044b\u0437\u043e\u0432\u0438 <code>increment()<\/code>\u00bb.<\/p>\n<\/li>\n<li>\n<p>PHP \u0438\u0441\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u043e\u0431\u044b\u0447\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434 \u043a\u043b\u0430\u0441\u0441\u0430 \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043d\u043e\u0432\u043e\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435.<\/p>\n<\/li>\n<li>\n<p>\u0411\u0440\u0430\u0443\u0437\u0435\u0440 \u043c\u0435\u043d\u044f\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u0435 \u0443\u0437\u043b\u044b DOM, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0438\u0437\u043c\u0435\u043d\u0438\u043b\u0438\u0441\u044c.<\/p>\n<\/li>\n<\/ol>\n<p>JavaScript \u0432 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0435 \u0438 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 \u043d\u0435\u0442 \u0432\u043e\u043e\u0431\u0449\u0435. \u041e\u043d \u0436\u0438\u0432\u0451\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0432\u043d\u0443\u0442\u0440\u0438 \u0440\u0430\u043d\u0442\u0430\u0439\u043c\u0430 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0430, \u0432\u0435\u0441\u0438\u0442 21 \u041a\u0411 \u0432 gzip, \u0438 \u0437\u0430\u0433\u043b\u044f\u0434\u044b\u0432\u0430\u0442\u044c \u0432 \u043d\u0435\u0433\u043e \u043f\u0440\u0438 \u0440\u0430\u0431\u043e\u0442\u0435 \u043d\u0430\u0434 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435\u043c \u043d\u0435 \u043f\u0440\u0438\u0434\u0451\u0442\u0441\u044f.<\/p>\n<h3>\u0417\u0430\u0447\u0435\u043c<\/h3>\n<p>\u0414\u043b\u044f \u0431\u044d\u043a\u0435\u043d\u0434-\u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0436\u0438\u0432\u043e\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0441\u0442\u043e\u0438\u0442 \u0434\u043e\u0440\u043e\u0433\u043e. \u041b\u043e\u0433\u0438\u043a\u0430 \u0440\u0430\u0437\u0431\u0440\u043e\u0441\u0430\u043d\u0430 \u043c\u0435\u0436\u0434\u0443 PHP \u0438 JS, \u0438 \u043a\u0430\u0436\u0434\u044b\u0439 \u0432 \u043a\u043e\u043c\u0430\u043d\u0434\u0435 \u0437\u043d\u0430\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0441\u0432\u043e\u044e \u0447\u0430\u0441\u0442\u044c. \u0412\u043e\u0437\u044c\u043c\u0451\u043c \u043a\u043d\u043e\u043f\u043a\u0443 \u00ab\u0423\u0434\u0430\u043b\u0438\u0442\u044c\u00bb \u0431\u0435\u0437 \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438: \u043d\u0443\u0436\u0435\u043d \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442, \u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f, \u0432\u044b\u0437\u043e\u0432 \u0438\u0437 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430 \u0438 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u043e\u0448\u0438\u0431\u043e\u043a. \u041f\u0440\u0438 \u044d\u0442\u043e\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0438 \u0441\u0435\u0440\u0432\u0435\u0440 \u0432\u0441\u0451 \u0440\u0430\u0432\u043d\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u0432 \u043e\u0434\u043d\u043e\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438. \u0412\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u044e, \u043f\u0440\u0430\u0432\u0430 \u0438 \u0444\u043e\u0440\u043c\u0430\u0442 \u0434\u0430\u0442 \u043f\u0438\u0448\u0435\u0448\u044c \u0434\u0432\u0430\u0436\u0434\u044b. \u0423 \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434\u0430 \u0441\u0432\u043e\u0439 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d \u0438 \u0441\u0432\u043e\u0438 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438, \u0438\u0445 \u0442\u043e\u0436\u0435 \u043d\u0443\u0436\u043d\u043e \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0442\u044c. \u0410 \u0435\u0441\u043b\u0438 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u0442\u0441\u044f \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435, \u0435\u0433\u043e \u0435\u0449\u0451 \u0443\u0447\u0430\u0442 \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u0442\u044c\u0441\u044f \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435, \u0438\u043d\u0430\u0447\u0435 \u043f\u043e\u0438\u0441\u043a\u043e\u0432\u0438\u043a\u0438 \u0443\u0432\u0438\u0434\u044f\u0442 \u043f\u0443\u0441\u0442\u0443\u044e \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443.<\/p>\n<p>\u0412 rig \u044d\u0442\u043e \u043e\u0434\u043d\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043d\u0430 \u043e\u0434\u043d\u043e\u043c \u044f\u0437\u044b\u043a\u0435. \u0428\u0430\u0431\u043b\u043e\u043d \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u0442\u0441\u044f \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435, \u0442\u0430\u043a \u0447\u0442\u043e \u043f\u043e\u0438\u0441\u043a\u043e\u0432\u0438\u043a \u0441\u0440\u0430\u0437\u0443 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u0433\u043e\u0442\u043e\u0432\u044b\u0439 HTML. \u0411\u0440\u0430\u0443\u0437\u0435\u0440 \u043f\u043e\u0442\u043e\u043c \u00ab\u043e\u0436\u0438\u0432\u043b\u044f\u0435\u0442\u00bb \u044d\u0442\u0443 \u0440\u0430\u0437\u043c\u0435\u0442\u043a\u0443. \u0412\u0441\u0451, \u0433\u0434\u0435 \u043d\u0443\u0436\u043d\u044b \u0434\u0430\u043d\u043d\u044b\u0435, \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0432 PHP, \u0440\u044f\u0434\u043e\u043c \u0441 \u0431\u0430\u0437\u043e\u0439, \u043f\u0440\u0430\u0432\u0430\u043c\u0438 \u0438 \u0431\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u043e\u0439.<\/p>\n<h3>\u041a\u0430\u043a \u044d\u0442\u043e \u0443\u0441\u0442\u0440\u043e\u0435\u043d\u043e<\/h3>\n<h4>\u041e\u0434\u0438\u043d \u044f\u0437\u044b\u043a \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0439 \u0438 \u0434\u0432\u0430 \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0442\u043e\u0440\u0430<\/h4>\n<p>\u0421\u0430\u043c\u043e\u0435 \u043f\u0440\u0438\u044f\u0442\u043d\u043e\u0435 \u0432 rig \u0434\u043b\u044f \u043c\u0435\u043d\u044f \u044d\u0442\u043e \u0448\u0430\u0431\u043b\u043e\u043d\u044b. \u0412\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0432 \u043d\u0438\u0445 \u043f\u0438\u0448\u0443\u0442\u0441\u044f \u043d\u0430 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u043c \u044f\u0437\u044b\u043a\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u043d\u0438\u043c\u0430\u044e\u0442 \u0438 \u0441\u0435\u0440\u0432\u0435\u0440, \u0438 \u0431\u0440\u0430\u0443\u0437\u0435\u0440: <code>{{ count }}<\/code>, <code>:class=\"{active: filter == f}\"<\/code>, <code>r-for=\"t in todos\"<\/code>, <code>@click=\"remove(t.id)\"<\/code>.<\/p>\n<p>\u041f\u0440\u0438 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438 PHP \u0440\u0430\u0437\u0431\u0438\u0440\u0430\u0435\u0442 \u0448\u0430\u0431\u043b\u043e\u043d \u0432 \u0434\u0435\u0440\u0435\u0432\u043e (AST \u0438\u0437 \u043e\u0431\u044b\u0447\u043d\u044b\u0445 \u043c\u0430\u0441\u0441\u0438\u0432\u043e\u0432). \u042d\u0442\u043e \u0434\u0435\u0440\u0435\u0432\u043e \u0438\u0441\u043f\u043e\u043b\u043d\u044f\u044e\u0442 \u0434\u0432\u0430 \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0442\u043e\u0440\u0430: PHP, \u043a\u043e\u0433\u0434\u0430 \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u0442 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443, \u0438 \u0440\u0430\u043d\u0442\u0430\u0439\u043c \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435. \u0421\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0435, \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0442\u0438\u043f\u043e\u0432, \u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043d\u0430 \u043d\u043e\u043b\u044c \u0438 \u0432\u044b\u0432\u043e\u0434 \u0432 \u0441\u0442\u0440\u043e\u043a\u0443 \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u043e, \u0434\u043e \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0433\u043e \u0441\u0438\u043c\u0432\u043e\u043b\u0430. \u0427\u0442\u043e\u0431\u044b \u0442\u0430\u043a \u0438 \u043e\u0441\u0442\u0430\u0432\u0430\u043b\u043e\u0441\u044c, \u0435\u0441\u0442\u044c \u0442\u0435\u0441\u0442\u044b: \u043e\u0434\u043d\u043e \u0438 \u0442\u043e \u0436\u0435 \u0434\u0435\u0440\u0435\u0432\u043e \u043f\u0440\u043e\u0433\u043e\u043d\u044f\u0435\u0442\u0441\u044f \u0447\u0435\u0440\u0435\u0437 \u043e\u0431\u0430 \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0442\u043e\u0440\u0430, \u0438 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u0441\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u044e\u0442\u0441\u044f.<\/p>\n<p>\u0427\u0442\u043e \u044d\u0442\u043e \u0434\u0430\u0451\u0442 \u043d\u0430 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0435? \u0412\u0441\u0451, \u0447\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0441\u0447\u0438\u0442\u0430\u0442\u044c \u0431\u0435\u0437 \u0441\u0435\u0440\u0432\u0435\u0440\u0430, \u0431\u0440\u0430\u0443\u0437\u0435\u0440 \u0441\u0447\u0438\u0442\u0430\u0435\u0442 \u0441\u0440\u0430\u0437\u0443. \u0410 \u043a\u043e\u0433\u0434\u0430 \u043d\u0443\u0436\u043d\u044b \u0434\u0430\u043d\u043d\u044b\u0435, \u0441\u0447\u0438\u0442\u0430\u0435\u0442 PHP. HTML \u0441 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442 \u0440\u043e\u0432\u043d\u043e \u0442\u0430\u043a\u0438\u043c, \u043a\u0430\u043a\u0438\u043c \u0435\u0433\u043e \u043d\u0430\u0440\u0438\u0441\u043e\u0432\u0430\u043b \u0431\u044b \u0431\u0440\u0430\u0443\u0437\u0435\u0440, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u0440\u0438 \u0433\u0438\u0434\u0440\u0430\u0446\u0438\u0438 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u043d\u0435 \u043f\u0435\u0440\u0435\u0440\u0438\u0441\u043e\u0432\u044b\u0432\u0430\u0435\u0442\u0441\u044f.<\/p>\n<h4>\u041e\u0448\u0438\u0431\u043a\u0438 \u043b\u043e\u0432\u0438\u0442 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440<\/h4>\n<p>\u0428\u0430\u0431\u043b\u043e\u043d\u044b \u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u0437\u0430\u0440\u0430\u043d\u0435\u0435, \u0438 \u043a\u0430\u0436\u0434\u043e\u0435 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0441\u0432\u0435\u0440\u044f\u0435\u0442\u0441\u044f \u0441\u043e \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430\u043c\u0438 \u043a\u043b\u0430\u0441\u0441\u0430. \u041e\u0448\u0438\u0431\u043b\u0438\u0441\u044c, \u0438 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u044f \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f:<\/p>\n<pre><code>\u2716 TodoItem  \u041d\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043d\u0430\u044f \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0430\u044f \u00abnmae\u00bb \u2014 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c, \u00abname\u00bb?  app\/components\/TodoItem.php:15<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><span class=\"sc-logo-wrapper icon-only\"><\/span><\/a><\/div><\/pre>\n<p>\u0412 \u0440\u0435\u0436\u0438\u043c\u0435 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0442\u0430 \u0436\u0435 \u043e\u0448\u0438\u0431\u043a\u0430 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0439 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435\u0439: \u043a\u043e\u0434 \u0432\u043e\u043a\u0440\u0443\u0433 \u0441\u0442\u0440\u043e\u043a\u0438, \u043a\u043d\u043e\u043f\u043a\u0430 \u00ab\u041e\u0442\u043a\u0440\u044b\u0442\u044c \u0432 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0435\u00bb \u0438 \u0433\u043e\u0442\u043e\u0432\u044b\u0439 \u043f\u0440\u043e\u043c\u043f\u0442 \u0434\u043b\u044f \u0418\u0418-\u0430\u0433\u0435\u043d\u0442\u0430. \u0412 \u043f\u0440\u043e\u043c\u043f\u0442\u0435 \u0443\u0436\u0435 \u043b\u0435\u0436\u0430\u0442 \u043e\u0448\u0438\u0431\u043a\u0430, \u043a\u043e\u0434, \u043f\u0443\u0442\u044c \u0432\u044b\u0437\u043e\u0432\u0430 \u0438 \u0437\u0430\u0434\u0430\u0447\u0430 \u043d\u0430\u0439\u0442\u0438 \u043f\u0440\u0438\u0447\u0438\u043d\u0443 \u0438 \u043f\u043e\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0435\u0451 \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u043c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435\u043c.<\/p>\n<h4>\u0413\u0434\u0435 \u0436\u0438\u0432\u0451\u0442 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435<\/h4>\n<p>\u0417\u0430 \u044d\u0442\u043e \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0430\u0442\u0440\u0438\u0431\u0443\u0442 \u043d\u0430\u0434 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e\u043c:<\/p>\n<pre><code class=\"php\">public array $todos = [];              \/\/ \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435, \u043c\u0435\u0436\u0434\u0443 \u0437\u0430\u043f\u0440\u043e\u0441\u0430\u043c\u0438 \u043b\u0435\u0436\u0438\u0442 \u0432 \u043f\u043e\u0434\u043f\u0438\u0441\u0430\u043d\u043d\u043e\u043c \u0441\u043d\u0438\u043c\u043a\u0435#[Locked]                              \/\/ \u0431\u0440\u0430\u0443\u0437\u0435\u0440 \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0438\u0441\u043b\u0430\u0442\u044c \u043d\u043e\u0432\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435public int $userId;#[Client]                              \/\/ \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435: \u0432\u043a\u043b\u0430\u0434\u043a\u0438, \u043c\u043e\u0434\u0430\u043b\u043a\u0438, \u0444\u0438\u043b\u044c\u0442\u0440\u044b, \u0431\u0435\u0437 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432public string $filter = 'all';#[Computed(\"where(todos, 'done', false) | len\")]public int $left;                      \/\/ \u0441\u0447\u0438\u0442\u0430\u0435\u0442\u0441\u044f \u0438 \u0432 PHP, \u0438 \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435#[Shared('cart', persist: true)]       \/\/ \u043e\u0434\u043d\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u0441 \u044d\u0442\u0438\u043c \u043a\u043b\u044e\u0447\u043e\u043cpublic array $cart = [];<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><span class=\"sc-logo-wrapper icon-only\"><\/span><\/a><\/div><\/pre>\n<p>\u0421\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043c\u0435\u0436\u0434\u0443 \u0437\u0430\u043f\u0440\u043e\u0441\u0430\u043c\u0438 \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f \u043f\u0440\u044f\u043c\u043e \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435, \u0432 \u0441\u043d\u0438\u043c\u043a\u0435 \u0441 \u043f\u043e\u0434\u043f\u0438\u0441\u044c\u044e HMAC-SHA256. \u0411\u0435\u0437 \u043a\u043b\u044e\u0447\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0435\u0433\u043e \u043d\u0435 \u043f\u043e\u0434\u0434\u0435\u043b\u0430\u0435\u0448\u044c. \u0417\u0430\u043e\u0434\u043d\u043e \u0441\u0435\u0440\u0432\u0435\u0440\u0443 \u043d\u0435 \u043d\u0443\u0436\u043d\u043e \u043f\u043e\u043c\u043d\u0438\u0442\u044c \u043a\u0430\u0436\u0434\u0443\u044e \u043e\u0442\u043a\u0440\u044b\u0442\u0443\u044e \u0432\u043a\u043b\u0430\u0434\u043a\u0443.<\/p>\n<h4>\u0412\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b<\/h4>\n<p>\u041e\u0434\u0438\u043d \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0432\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0432 \u0448\u0430\u0431\u043b\u043e\u043d \u0434\u0440\u0443\u0433\u043e\u0433\u043e \u0442\u0435\u0433\u043e\u043c. \u0420\u043e\u0434\u0438\u0442\u0435\u043b\u044c \u043e\u0442\u0434\u0430\u0451\u0442 \u0435\u043c\u0443 \u0434\u0430\u043d\u043d\u044b\u0435 \u0447\u0435\u0440\u0435\u0437 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b, \u0430 \u0434\u043e\u0447\u0435\u0440\u043d\u0438\u0439 \u0441\u043e\u043e\u0431\u0449\u0430\u0435\u0442 \u0441\u043e\u0431\u044b\u0442\u0438\u044f\u043c\u0438, \u0447\u0442\u043e \u0441\u0434\u0435\u043b\u0430\u043b \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c. \u041a\u0430\u043a \u043d\u0430 \u044d\u0442\u043e \u0440\u0435\u0430\u0433\u0438\u0440\u043e\u0432\u0430\u0442\u044c, \u0440\u0435\u0448\u0430\u0435\u0442 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c.<\/p>\n<p>\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0441\u0442\u0440\u043e\u043a\u0430 \u0441\u043f\u0438\u0441\u043a\u0430 \u0437\u0430\u0434\u0430\u0447 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u0437\u0430\u0434\u0430\u0447\u0443 \u0447\u0435\u0440\u0435\u0437 <code>#[Prop]<\/code> \u0438 \u0441\u043e\u043e\u0431\u0449\u0430\u0435\u0442 \u043e \u043a\u043b\u0438\u043a\u0435 \u0447\u0435\u0440\u0435\u0437 <code>emit()<\/code>:<\/p>\n<pre><code class=\"php\">\/\/ \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 TodoItem: app\/components\/TodoItem.phpfinal class TodoItem extends Component{    public const TAG = 'li';   \/\/ \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u0442\u0441\u044f \u0432\u043d\u0443\u0442\u0440\u0438 &lt;li&gt;, \u0430 \u043d\u0435 &lt;div&gt;    #[Prop]    public array $todo = [];}?&gt;&lt;template&gt;  &lt;input type=\"checkbox\" :checked=\"todo.done\" @change=\"emit('toggle', $event.target.checked)\"&gt;  {{ todo.title }}  &lt;button @click=\"emit('remove')\"&gt;\u00d7&lt;\/button&gt;&lt;\/template&gt;<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><span class=\"sc-logo-wrapper icon-only\"><\/span><\/a><\/div><\/pre>\n<p>\u0421\u043f\u0438\u0441\u043e\u043a \u0432\u044b\u0432\u043e\u0434\u0438\u0442 \u043f\u043e \u0441\u0442\u0440\u043e\u043a\u0435 \u043d\u0430 \u043a\u0430\u0436\u0434\u0443\u044e \u0437\u0430\u0434\u0430\u0447\u0443 \u0438 \u043d\u0430 \u0435\u0451 \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442 \u0441\u0432\u043e\u0438 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f. \u0412 <code>$event<\/code> \u043f\u043e\u043f\u0430\u0434\u0430\u0435\u0442 \u0442\u043e, \u0447\u0442\u043e \u0441\u0442\u0440\u043e\u043a\u0430 \u043f\u0435\u0440\u0435\u0434\u0430\u043b\u0430 \u0432 <code>emit()<\/code>, \u0432 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0447\u0435\u043a\u0431\u043e\u043a\u0441\u0430:<\/p>\n<pre><code class=\"php\">&lt;!-- \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 TodoList: \u0448\u0430\u0431\u043b\u043e\u043d \u0432 app\/components\/TodoList.php --&gt;&lt;ul&gt;  &lt;TodoItem r-for=\"t in todos\" :key=\"t.id\" :todo=\"t\"            @toggle=\"setDone(t.id, $event)\"            @remove=\"remove(t.id)\" \/&gt;&lt;\/ul&gt;<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><span class=\"sc-logo-wrapper icon-only\"><\/span><\/a><\/div><\/pre>\n<p>\u0418\u043d\u043e\u0433\u0434\u0430 \u0434\u043e\u0447\u0435\u0440\u043d\u0438\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u043c\u0435\u043d\u044f\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u043d\u043e-\u0435\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435. \u0422\u043e\u0433\u0434\u0430 \u0443\u0434\u043e\u0431\u043d\u043e \u043f\u0440\u0438\u0432\u044f\u0437\u0430\u0442\u044c \u0435\u0433\u043e \u043a \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044e \u0447\u0435\u0440\u0435\u0437 <code>r-model<\/code>, \u043a\u0430\u043a \u043e\u0431\u044b\u0447\u043d\u043e\u0435 \u043f\u043e\u043b\u0435 \u0432\u0432\u043e\u0434\u0430. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043f\u043e\u043c\u0435\u0447\u0430\u0435\u043c \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u043e\u043c <code>#[Model]<\/code>:<\/p>\n<pre><code class=\"php\">\/\/ \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 Rating: app\/components\/Rating.phpfinal class Rating extends Component{    #[Prop, Model]    public int $value = 0;}?&gt;&lt;template&gt;  &lt;button r-for=\"n in [1, 2, 3, 4, 5]\" :key=\"n\" :class=\"{on: n &lt;= value}\" @click=\"value = n\"&gt;\u2605&lt;\/button&gt;&lt;\/template&gt;<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><span class=\"sc-logo-wrapper icon-only\"><\/span><\/a><\/div><\/pre>\n<pre><code class=\"php\">&lt;Rating r-model=\"score\" \/&gt;   &lt;!-- \u043a\u043b\u0438\u043a \u043f\u043e \u0437\u0432\u0435\u0437\u0434\u0435 \u043c\u0435\u043d\u044f\u0435\u0442 score \u0443 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044f --&gt;<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><span class=\"sc-logo-wrapper icon-only\"><\/span><\/a><\/div><\/pre>\n<p>\u0420\u0430\u0437\u043c\u0435\u0442\u043a\u0443 \u0432\u043d\u0443\u0442\u0440\u044c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u043f\u0435\u0440\u0435\u0434\u0430\u044e\u0442 \u0441\u043b\u043e\u0442\u0430\u043c\u0438. \u0412 \u0448\u0430\u0431\u043b\u043e\u043d\u0435 \u043a\u0430\u0440\u0442\u043e\u0447\u043a\u0438 \u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u044b \u043c\u0435\u0441\u0442\u0430 <code>&lt;slot&gt;<\/code> \u0438 <code>&lt;slot name=\"footer\"&gt;<\/code>. \u0421\u043d\u0430\u0440\u0443\u0436\u0438 \u044d\u0442\u043e \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0442\u0430\u043a:<\/p>\n<pre><code class=\"php\">&lt;Card title=\"\u0417\u0430\u0434\u0430\u0447\u0438\"&gt;  &lt;TodoList \/&gt;  &lt;template #footer&gt;\u0414\u0432\u043e\u0439\u043d\u043e\u0439 \u0449\u0435\u043b\u0447\u043e\u043a \u043f\u043e \u0437\u0430\u0434\u0430\u0447\u0435 \u043f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u043e\u0432\u044b\u0432\u0430\u0435\u0442 \u0435\u0451&lt;\/template&gt;&lt;\/Card&gt;<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><span class=\"sc-logo-wrapper icon-only\"><\/span><\/a><\/div><\/pre>\n<p>\u041f\u043e\u0447\u0435\u043c\u0443 \u0443 <code>TodoList<\/code> \u043d\u0435\u0442 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u043e\u0432? \u041f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043e\u043d \u0441\u0430\u043c \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0442 \u0437\u0430\u0434\u0430\u0447\u0438 \u0432 <code>mount()<\/code> \u0438 \u0441\u0430\u043c \u043c\u0435\u043d\u044f\u0435\u0442 \u0438\u0445 \u0447\u0435\u0440\u0435\u0437 <code>setDone()<\/code> \u0438 <code>remove()<\/code>. \u0415\u0441\u043b\u0438 \u0431\u044b \u0441\u043f\u0438\u0441\u043e\u043a \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u043b \u0438\u0437\u0432\u043d\u0435 \u0447\u0435\u0440\u0435\u0437 <code>#[Prop]<\/code>, \u043c\u0435\u043d\u044f\u0442\u044c \u0435\u0433\u043e \u0432\u043d\u0443\u0442\u0440\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u0431\u044b\u043b\u043e \u0431\u044b \u043d\u0435\u043b\u044c\u0437\u044f, \u0438 \u0432\u0441\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u0431\u044b \u043f\u0435\u0440\u0435\u043d\u043e\u0441\u0438\u0442\u044c \u0432 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044f. \u0414\u043b\u044f \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u0441\u0434\u0435\u043b\u0430\u043d\u043e \u0432\u043d\u0443\u0442\u0440\u0438 \u043a\u043e\u043c\u043f\u0430\u043d\u0435\u043d\u0442\u0430.<\/p>\n<h4>\u041f\u0435\u0440\u0435\u0445\u043e\u0434\u044b, \u043a\u0435\u0448 \u0438 \u043b\u0435\u043d\u0438\u0432\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435<\/h4>\n<p>\u0421\u0441\u044b\u043b\u043a\u0438 \u0432\u043d\u0443\u0442\u0440\u0438 \u0441\u0430\u0439\u0442\u0430 \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u0431\u0435\u0437 \u043f\u043e\u043b\u043d\u043e\u0439 \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438. \u0421\u0435\u0440\u0432\u0435\u0440 \u043e\u0442\u0434\u0430\u0451\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u043d\u0443\u0436\u043d\u043e\u0439 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b, \u0430 layout \u0438 \u0435\u0433\u043e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u043e\u0441\u0442\u0430\u044e\u0442\u0441\u044f \u043d\u0430 \u043c\u0435\u0441\u0442\u0435 \u0441\u043e \u0441\u0432\u043e\u0438\u043c \u0442\u0435\u043a\u0443\u0449\u0438\u043c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435\u043c.<\/p>\n<p>\u0421\u0442\u0440\u0430\u043d\u0438\u0446\u0430, \u0441 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0443\u0448\u043b\u0438, \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u0442\u0441\u044f \u0432 rig \u0432\u043c\u0435\u0441\u0442\u0435 \u0441 \u0436\u0438\u0432\u044b\u043c\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430\u043c\u0438. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043a\u043d\u043e\u043f\u043a\u0430 \u00ab\u041d\u0430\u0437\u0430\u0434\u00bb \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u0435\u0451 \u043c\u0433\u043d\u043e\u0432\u0435\u043d\u043d\u043e, \u0431\u0435\u0437 \u043d\u043e\u0432\u043e\u0433\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0430, \u0441 \u0442\u0435\u043c\u0438 \u0436\u0435 \u0444\u0438\u043b\u044c\u0442\u0440\u0430\u043c\u0438, \u043f\u043e\u0434\u0433\u0440\u0443\u0436\u0435\u043d\u043d\u044b\u043c\u0438 \u0442\u043e\u0432\u0430\u0440\u0430\u043c\u0438, \u0432\u0432\u0435\u0434\u0451\u043d\u043d\u044b\u043c \u0442\u0435\u043a\u0441\u0442\u043e\u043c \u0438 \u0442\u0435\u043a\u0443\u0449\u0435\u0439 \u043f\u0440\u043e\u043a\u0440\u0443\u0442\u043a\u043e\u0439. \u0415\u0441\u043b\u0438 \u0437\u0430 \u044d\u0442\u043e \u0432\u0440\u0435\u043c\u044f \u0434\u0430\u043d\u043d\u044b\u0435 \u0438\u0437\u043c\u0435\u043d\u0438\u043b\u0438\u0441\u044c, \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u0442\u0438\u0445\u043e \u043e\u0431\u043d\u043e\u0432\u044f\u0442\u0441\u044f \u0432 \u0444\u043e\u043d\u0435.<\/p>\n<p>\u041f\u043e\u043a\u0430 \u043a\u0443\u0440\u0441\u043e\u0440 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u043d\u0430\u0434 \u0441\u0441\u044b\u043b\u043a\u043e\u0439, rig \u0443\u0436\u0435 \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u0442 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443, \u0438 \u043a \u043c\u043e\u043c\u0435\u043d\u0442\u0443 \u043a\u043b\u0438\u043a\u0430 \u043e\u0442\u0432\u0435\u0442 \u0433\u043e\u0442\u043e\u0432.<\/p>\n<p>\u041c\u0435\u0434\u043b\u0435\u043d\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u043d\u0435 \u0436\u0434\u0451\u0442. \u041a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0441 <code>#[Lazy]<\/code> \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442 \u0441\u0440\u0430\u0437\u0443 \u0432 \u0432\u0438\u0434\u0435 \u0441\u043a\u0435\u043b\u0435\u0442\u043e\u043d\u0430, \u0430 \u0442\u044f\u0436\u0451\u043b\u0430\u044f \u0432\u044b\u0431\u043e\u0440\u043a\u0430 \u0434\u0435\u043b\u0430\u0435\u0442\u0441\u044f \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u043c \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u043c, \u043a\u043e\u0433\u0434\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u0443\u0436\u0435 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0430. \u0415\u0441\u043b\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0437\u0430 \u044d\u0442\u043e \u0432\u0440\u0435\u043c\u044f \u0443\u0448\u0451\u043b \u0434\u0430\u043b\u044c\u0448\u0435, \u043f\u0435\u0440\u0435\u0445\u043e\u0434 \u0442\u043e\u0436\u0435 \u043d\u0435 \u0436\u0434\u0451\u0442 \u044d\u0442\u0443 \u0432\u044b\u0431\u043e\u0440\u043a\u0443.<\/p>\n<pre><code class=\"php\">#[Lazy]final class ProductList extends Component{    #[Locked] public array $items = [];    #[Locked] public int $page = 0;    #[Locked] public bool $hasMore = false;    public function mount(): void    {        $this-&gt;more();   \/\/ \u043f\u0435\u0440\u0432\u0430\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430: \u043c\u0435\u0434\u043b\u0435\u043d\u043d\u0430\u044f \u0432\u044b\u0431\u043e\u0440\u043a\u0430    }    #[Action]    public function more(): void    {        $p = Product::orderBy('id')-&gt;paginate(9, $this-&gt;page + 1);        $this-&gt;items = [...$this-&gt;items, ...$p['items']];        $this-&gt;page = $p['page'];        $this-&gt;hasMore = $p['page'] &lt; $p['pages'];    }}?&gt;&lt;template&gt;  &lt;ul class=\"grid\"&gt;    &lt;li r-for=\"p in items\" :key=\"p.id\"&gt;{{ p.name }}, {{ p.price }} \u20bd&lt;\/li&gt;    &lt;!-- \u043f\u043e\u043a\u0430 \u0433\u0440\u0443\u0437\u0438\u0442\u0441\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0430\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430, \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u0442\u0440\u0438 \u0441\u043a\u0435\u043b\u0435\u0442\u043e\u043d\u0430 --&gt;    &lt;li r-for=\"i in ($pending.more ? [1, 2, 3] : [])\" :key=\"'sk' + i\" aria-hidden=\"true\"&gt;      &lt;div class=\"r-sk r-sk-block\"&gt;&lt;\/div&gt;    &lt;\/li&gt;  &lt;\/ul&gt;  &lt;button r-if=\"hasMore\" @click=\"more\" :disabled=\"$busy\"&gt;    {{ $pending.more ? '\u0417\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c\u2026' : '\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0435\u0449\u0451' }}  &lt;\/button&gt;&lt;\/template&gt;&lt;!-- \u0441\u043a\u0435\u043b\u0435\u0442\u043e\u043d, \u0432\u0438\u0434\u0438\u043c\u044b\u0439 \u043f\u043e\u043a\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f mount() --&gt;&lt;skeleton&gt;  &lt;ul class=\"grid\" aria-hidden=\"true\"&gt;    &lt;li r-for=\"i in [1, 2, 3, 4, 5, 6]\" :key=\"i\"&gt;      &lt;div class=\"r-sk r-sk-block\"&gt;&lt;\/div&gt;      &lt;div class=\"r-sk r-sk-line\" style=\"width: 60%\"&gt;&lt;\/div&gt;    &lt;\/li&gt;  &lt;\/ul&gt;&lt;\/skeleton&gt;<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><span class=\"sc-logo-wrapper icon-only\"><\/span><\/a><\/div><\/pre>\n<p>\u0421\u043a\u0435\u043b\u0435\u0442\u043e\u043d \u043f\u0438\u0448\u0435\u0442\u0441\u044f \u0442\u0435\u043c \u0436\u0435 \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441\u043e\u043c, \u0447\u0442\u043e \u0438 \u0448\u0430\u0431\u043b\u043e\u043d, \u0438 \u0441\u0442\u0438\u043b\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u043a \u043d\u0435\u043c\u0443 \u0442\u043e\u0436\u0435 \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u044e\u0442\u0441\u044f. \u0414\u043b\u044f \u043f\u043b\u0430\u0448\u0435\u043a \u0435\u0441\u0442\u044c \u0433\u043e\u0442\u043e\u0432\u044b\u0435 \u043a\u043b\u0430\u0441\u0441\u044b <code>r-sk<\/code>, <code>r-sk-line<\/code> \u0438 <code>r-sk-block<\/code>. \u041e\u043d\u0438 \u043c\u0435\u0440\u0446\u0430\u044e\u0442, \u0443\u0447\u0438\u0442\u044b\u0432\u0430\u044e\u0442 \u0442\u0451\u043c\u043d\u0443\u044e \u0442\u0435\u043c\u0443 \u0438 <code>prefers-reduced-motion<\/code>.<\/p>\n<h4>\u0421\u043e\u0431\u044b\u0442\u0438\u044f \u0441 \u0441\u0435\u0440\u0432\u0435\u0440\u0430<\/h4>\n<pre><code class=\"php\">$this-&gt;broadcast('todos-changed');     \/\/ \u0434\u0440\u0443\u0433\u0438\u043c \u0432\u043a\u043b\u0430\u0434\u043a\u0430\u043c \u0438 \u0434\u0440\u0443\u0433\u0438\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u043c#[On('todos-changed')]public function reload(): void{    $this-&gt;todos = Todo::all();}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><span class=\"sc-logo-wrapper icon-only\"><\/span><\/a><\/div><\/pre>\n<p>\u0414\u043e\u0441\u0442\u0430\u0432\u043a\u043e\u0439 \u0437\u0430\u043d\u0438\u043c\u0430\u0435\u0442\u0441\u044f \u0445\u0430\u0431. \u0423 \u0432\u043a\u043b\u0430\u0434\u043a\u0438 \u043e\u0434\u043d\u043e SSE-\u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435, \u0438 \u043f\u043e \u043d\u0435\u043c\u0443 \u043f\u0440\u0438\u0445\u043e\u0434\u044f\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u0435 \u0441\u043e\u0431\u044b\u0442\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0441\u043b\u0443\u0448\u0430\u044e\u0442 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435. \u0421\u043f\u0438\u0441\u043e\u043a \u0441\u043e\u0431\u044b\u0442\u0438\u0439 \u043f\u043e\u0434\u043f\u0438\u0441\u0430\u043d, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u043e\u0434\u043f\u0438\u0441\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u0447\u0443\u0436\u0438\u0435 \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u0432\u043a\u043b\u0430\u0434\u043a\u0430 \u043d\u0435 \u0441\u043c\u043e\u0436\u0435\u0442.<\/p>\n<h4>\u041a\u043e\u0433\u0434\u0430 JavaScript \u0432\u0441\u0451-\u0442\u0430\u043a\u0438 \u043d\u0443\u0436\u0435\u043d<\/h4>\n<p>\u0413\u0440\u0430\u0444\u0438\u043a\u0438, \u043a\u0430\u0440\u0442\u044b \u0438 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u044b \u0443\u0436\u0435 \u0435\u0441\u0442\u044c \u0432 \u0433\u043e\u0442\u043e\u0432\u044b\u0445 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430\u0445, \u043f\u0435\u0440\u0435\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u0438\u0445 \u0432 \u0448\u0430\u0431\u043b\u043e\u043d\u0430\u0445 \u043d\u0435\u0442 \u0441\u043c\u044b\u0441\u043b\u0430. \u0414\u043b\u044f \u043d\u0438\u0445 \u0435\u0441\u0442\u044c <code>r-js<\/code>: \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u044b\u043c \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0432\u0430\u0448 \u043c\u043e\u0434\u0443\u043b\u044c.<\/p>\n<pre><code class=\"php\">&lt;div r-js=\"sparkline\" r-props=\"{points: points}\" @pick=\"picked = $event.detail\"&gt;&lt;\/div&gt;<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><span class=\"sc-logo-wrapper icon-only\"><\/span><\/a><\/div><\/pre>\n<pre><code>\/\/ app\/js\/sparkline.jsexport function mount(el, props, ctx) {  \/\/ \u0440\u0438\u0441\u0443\u0435\u043c; ctx.emit('pick', value) \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442 \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u043e\u0431\u0440\u0430\u0442\u043d\u043e \u0432 \u0448\u0430\u0431\u043b\u043e\u043d  return {    update(next) {      \/* \u043d\u043e\u0432\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0438\u0437 PHP *\/    },    unmount() {},  };}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><span class=\"sc-logo-wrapper icon-only\"><\/span><\/a><\/div><\/pre>\n<p>\u041c\u043e\u0434\u0443\u043b\u044c \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u0434\u0430\u043d\u043d\u044b\u0435 \u0438\u0437 PHP \u0438 \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0441\u043e\u0431\u044b\u0442\u0438\u044f\u043c\u0438 \u0448\u0430\u0431\u043b\u043e\u043d\u0430. \u0412\u0441\u0451 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u043e\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0431\u0435\u0437 JS.<\/p>\n<h3>\u0411\u044d\u043a\u0435\u043d\u0434 \u0432 \u043a\u043e\u043c\u043f\u043b\u0435\u043a\u0442\u0435<\/h3>\n<p>\u0423 rig \u0441\u0432\u043e\u0439 \u0431\u044d\u043a\u0435\u043d\u0434, Composer-\u043f\u0430\u043a\u0435\u0442\u044b \u043d\u0435 \u043d\u0443\u0436\u043d\u044b.<\/p>\n<p>PostgreSQL \u0434\u043b\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0441\u0442\u0430\u0432\u0438\u0442\u044c \u043d\u0435 \u043d\u0443\u0436\u043d\u043e. <code>rig dev<\/code> \u0441\u0430\u043c \u0441\u043e\u0437\u0434\u0430\u0451\u0442 \u043a\u043b\u0430\u0441\u0442\u0435\u0440 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0432 <code>storage\/postgres<\/code>, \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442 \u0435\u0433\u043e \u043d\u0430 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u043c \u043f\u043e\u0440\u0442\u0443 \u0438 \u043d\u0430\u043a\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0438. \u041d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043e\u0431\u044b\u0447\u043d\u044b\u0439 PostgreSQL, \u0430\u0434\u0440\u0435\u0441 \u0431\u0435\u0440\u0451\u0442\u0441\u044f \u0438\u0437 <code>.env<\/code>. MySQL \u0438 SQLite \u0442\u043e\u0436\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442.<\/p>\n<pre><code class=\"php\">$todos = Todo::where('done', false)-&gt;orderBy('id')-&gt;get();DB::table('orders')    -&gt;where('total', '&gt;', 1000)    -&gt;paginate(20, $page);DB::transaction(function () {    \/\/ \u2026});<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><span class=\"sc-logo-wrapper icon-only\"><\/span><\/a><\/div><\/pre>\n<p>\u041c\u043e\u0434\u0435\u043b\u0438 \u043f\u0440\u0438\u0432\u043e\u0434\u044f\u0442 \u0442\u0438\u043f\u044b \u0438 \u0441\u0442\u0440\u043e\u044f\u0442 \u0441\u0432\u044f\u0437\u0438. \u041c\u0438\u0433\u0440\u0430\u0446\u0438\u0438 \u043e\u0442\u043a\u0430\u0442\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u043f\u0430\u0447\u043a\u0430\u043c\u0438, \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0437\u0430\u0432\u043e\u0434\u044f\u0442\u0441\u044f \u0441\u0438\u0434\u0430\u043c\u0438.<\/p>\n<p>\u0414\u043e\u0441\u0442\u0443\u043f \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0432\u0430\u0435\u0442\u0441\u044f middleware \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 \u0438 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u043e\u043c <code>#[Guard]<\/code> \u043d\u0430 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0435:<\/p>\n<pre><code class=\"php\">&lt;?phpRig\\Page::middleware('role:admin'); \/\/ \u043f\u0435\u0440\u0432\u0430\u044f \u0441\u0442\u0440\u043e\u043a\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><span class=\"sc-logo-wrapper icon-only\"><\/span><\/a><\/div><\/pre>\n<pre><code class=\"php\">#[Guard('auth')] \/\/ \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0438 \u0432\u0441\u0435 \u0435\u0433\u043e \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u0442\u043e\u043b\u044c\u043a\u043e \u0432\u043e\u0448\u0435\u0434\u0448\u0438\u043cfinal class Profile extends Component { \u2026 }<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><span class=\"sc-logo-wrapper icon-only\"><\/span><\/a><\/div><\/pre>\n<p>\u0421\u043f\u0438\u0441\u043e\u043a middleware \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u043f\u043e\u043f\u0430\u0434\u0430\u0435\u0442 \u0432 \u043f\u043e\u0434\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0435 \u0441\u043d\u0438\u043c\u043a\u0438 \u0435\u0451 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432, \u0438 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u044e\u0442\u0441\u044f \u043f\u043e \u044d\u0442\u043e\u043c\u0443 \u0436\u0435 \u0441\u043f\u0438\u0441\u043a\u0443. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0432\u044b\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u0438\u0437 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430 \u043d\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0441\u044f. \u0415\u0441\u0442\u044c \u0435\u0449\u0451 \u0441\u0435\u0441\u0441\u0438\u0438, CSRF, \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435 \u043f\u043e\u043f\u044b\u0442\u043e\u043a \u0432\u0432\u043e\u0434\u0430 \u043f\u0430\u0440\u043e\u043b\u044f \u0438 <code>throttle<\/code>.<\/p>\n<p>API \u0440\u0430\u0441\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043f\u043e \u0444\u0430\u0439\u043b\u0430\u043c, <code>app\/api\/todos\/[id].php<\/code> \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u043d\u0430 \u0437\u0430\u043f\u0440\u043e\u0441 <code>\/api\/todos\/5<\/code>:<\/p>\n<pre><code class=\"php\">return [    'middleware' =&gt; ['auth'],    'GET'  =&gt; fn (int $id) =&gt; Todo::findOrFail($id),    'PATCH' =&gt; function (int $id, Request $request) {        $todo = Todo::findOrFail($id);        $todo-&gt;update($request-&gt;validate(['title' =&gt; 'required|min:3']));        return $todo; \/\/ \u043c\u043e\u0434\u0435\u043b\u044c \u0443\u0439\u0434\u0451\u0442 \u043a\u0430\u043a JSON    },];<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><span class=\"sc-logo-wrapper icon-only\"><\/span><\/a><\/div><\/pre>\n<p>\u0424\u0430\u0439\u043b \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u043f\u0440\u044f\u043c\u043e \u0432 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430:<\/p>\n<pre><code class=\"php\">&lt;input type=\"file\" accept=\"image\/*\" r-model=\"photo\"&gt;&lt;img r-if=\"photo.preview\" :src=\"photo.preview\"&gt;<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><span class=\"sc-logo-wrapper icon-only\"><\/span><\/a><\/div><\/pre>\n<pre><code class=\"php\">public ?UploadedFile $photo = null;#[Action]public function save(): void{    $this-&gt;validate(['photo' =&gt; 'required|image|max:2048']);    $this-&gt;user['avatar'] = $this-&gt;photo-&gt;store('avatars');}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><span class=\"sc-logo-wrapper icon-only\"><\/span><\/a><\/div><\/pre>\n<p>\u0424\u0430\u0439\u043b \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440 \u0441\u0440\u0430\u0437\u0443 \u043f\u043e\u0441\u043b\u0435 \u0432\u044b\u0431\u043e\u0440\u0430, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u0440\u0435\u0432\u044c\u044e \u0432\u0438\u0434\u043d\u043e \u0435\u0449\u0451 \u0434\u043e \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f. \u0421\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0439 \u0444\u0430\u0439\u043b \u043f\u043e\u0434\u043f\u0438\u0441\u0430\u043d\u0430, \u0442\u0438\u043f \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442\u0441\u044f \u043f\u043e \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u043c\u0443.<\/p>\n<p>\u0414\u043b\u044f \u0444\u043e\u043d\u043e\u0432\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u044b \u0435\u0441\u0442\u044c \u043e\u0447\u0435\u0440\u0435\u0434\u044c, \u043f\u043e\u0447\u0442\u0430 \u0438 \u0440\u0430\u0441\u043f\u0438\u0441\u0430\u043d\u0438\u0435:<\/p>\n<pre><code class=\"php\">Queue::push(SendWelcome::class, ['email' =&gt; $email]);Mail::to($email)    -&gt;subject('\u0417\u0430\u043a\u0430\u0437 \u043e\u0444\u043e\u0440\u043c\u043b\u0435\u043d')    -&gt;view('order', $data)    -&gt;queue();Schedule::call(fn () =&gt; Report::send(), '\u043e\u0442\u0447\u0451\u0442')    -&gt;dailyAt('09:00')    -&gt;weekdays();<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><span class=\"sc-logo-wrapper icon-only\"><\/span><\/a><\/div><\/pre>\n<p>\u041e\u0447\u0435\u0440\u0435\u0434\u044c \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f \u0432 \u0444\u0430\u0439\u043b\u0430\u0445, Redis \u043d\u0435 \u043d\u0443\u0436\u0435\u043d. \u041f\u043e\u0447\u0442\u0443 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u0447\u0435\u0440\u0435\u0437 SMTP, \u0430 \u0432 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u0438\u0448\u0435\u043c \u0432 \u0436\u0443\u0440\u043d\u0430\u043b. \u041e\u0447\u0435\u0440\u0435\u0434\u044c \u0438 \u0440\u0430\u0441\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0432 \u0440\u0435\u0436\u0438\u043c\u0435 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043a\u0440\u0443\u0442\u0438\u0442 <code>rig dev<\/code>.<\/p>\n<p>\u041a\u0440\u0430\u0442\u043a\u043e \u043f\u0440\u043e \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u043e\u0435: <code>.env<\/code>, \u0436\u0443\u0440\u043d\u0430\u043b, \u043a\u0435\u0448 \u0434\u0430\u043d\u043d\u044b\u0445, \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0430 <code>t()<\/code> \u0441 \u0444\u043e\u0440\u043c\u0430\u043c\u0438 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0433\u043e \u0447\u0438\u0441\u043b\u0430 (\u0432 PHP \u0438 \u0432 \u0448\u0430\u0431\u043b\u043e\u043d\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u043e), \u0442\u0435\u0433\u0438 <code>&lt;head&gt;<\/code> \u0438 Open Graph \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b, \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u0438 <code>r-transition<\/code>, <code>debounce<\/code> \u0438 <code>throttle<\/code> \u0434\u043b\u044f \u0441\u043e\u0431\u044b\u0442\u0438\u0439 \u0438 \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u0441\u0431\u043e\u0440\u043a\u0430 <code>rig generate<\/code>.<\/p>\n<h3>\u0420\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0430: \u043e\u0434\u043d\u0430 \u043a\u043e\u043c\u0430\u043d\u0434\u0430<\/h3>\n<pre><code>$ rig dev  rig v0.6.0  \u00b7  PHP 8.4.19  \u00b7  dev  \u2714 \u041e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435 (PHP 8.4.19)                          0 ms  \u2714 \u0411\u0430\u0437\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 PostgreSQL 18.3 \u00b7 \u043f\u043e\u0440\u0442 54329        1.02 s  \u2714 \u041c\u0438\u0433\u0440\u0430\u0446\u0438\u0438 (\u043d\u043e\u0432\u044b\u0445 \u043d\u0435\u0442)                            48 ms  \u2714 \u041a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b (18)                                 4 ms  \u2714 \u0425\u0430\u0431: HMR \u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u0441 \u0441\u0435\u0440\u0432\u0435\u0440\u0430                    18 ms  \u2714 \u0421\u0435\u0440\u0432\u0435\u0440 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f                               192 ms  \u279c  Local:    http:\/\/127.0.0.1:8000\/  \u279c  \u0411\u0430\u0437\u0430:     pgsql:\/\/127.0.0.1:54329\/rig<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><span class=\"sc-logo-wrapper icon-only\"><\/span><\/a><\/div><\/pre>\n<p>\u041e\u0442 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u043d\u0443\u0436\u0435\u043d \u0442\u043e\u043b\u044c\u043a\u043e PHP 8.1 \u0438\u043b\u0438 \u043d\u043e\u0432\u0435\u0435. <code>rig dev<\/code> \u043f\u043e\u0434\u043d\u0438\u043c\u0430\u0435\u0442 \u0441\u0435\u0440\u0432\u0435\u0440, \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0432\u043e\u0440\u043a\u0435\u0440\u043e\u0432, \u0431\u0430\u0437\u0443, \u0445\u0430\u0431 \u0441\u043e\u0431\u044b\u0442\u0438\u0439, \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u043e\u0447\u0435\u0440\u0435\u0434\u0438 \u0438 \u043f\u043b\u0430\u043d\u0438\u0440\u043e\u0432\u0449\u0438\u043a. \u0415\u0441\u043b\u0438 \u043c\u0435\u043d\u044f\u0435\u0442\u0435 \u0448\u0430\u0431\u043b\u043e\u043d, \u0441\u0442\u0438\u043b\u044c \u0438\u043b\u0438 PHP-\u043a\u043e\u0434 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430, \u043f\u0440\u0430\u0432\u043a\u0430 \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f \u0441\u0440\u0430\u0437\u0443, \u0431\u0435\u0437 \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438, \u0438 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u0442\u0441\u044f: \u0432\u0432\u0435\u0434\u0451\u043d\u043d\u044b\u0439 \u0442\u0435\u043a\u0441\u0442 \u043e\u0441\u0442\u0430\u0451\u0442\u0441\u044f \u0432 \u043f\u043e\u043b\u044f\u0445, \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u0435 \u043f\u0430\u043d\u0435\u043b\u0438 \u043d\u0435 \u0437\u0430\u043a\u0440\u044b\u0432\u0430\u044e\u0442\u0441\u044f.<\/p>\n<p><code>rig check<\/code> \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u0442 \u0432\u0441\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442 \u0442\u0435\u0441\u0442\u044b \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0430. \u0421\u0435\u0439\u0447\u0430\u0441 \u0438\u0445 327, \u0431\u044d\u043a\u0435\u043d\u0434 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442\u0441\u044f \u0438 \u043d\u0430 SQLite, \u0438 \u043d\u0430 PostgreSQL. <code>rig build<\/code> \u0433\u043e\u0442\u043e\u0432\u0438\u0442 \u0432\u044b\u043a\u043b\u0430\u0434\u043a\u0443 \u0438 \u043e\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442 \u0435\u0451, \u0435\u0441\u043b\u0438 \u0432 \u0448\u0430\u0431\u043b\u043e\u043d\u0435 \u043e\u0448\u0438\u0431\u043a\u0430 \u0438\u043b\u0438 \u043d\u0430 \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u0435\u043d\u0435 \u0437\u0430\u0431\u044b\u043b\u0438 \u0432\u044b\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u043e\u0442\u043b\u0430\u0434\u043a\u0443.<\/p>\n<h3>\u0427\u0442\u043e \u0434\u0430\u0451\u0442 \u0442\u0430\u043a\u043e\u0439 \u043f\u043e\u0434\u0445\u043e\u0434<\/h3>\n<p>\u0412\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u044e, \u043f\u0440\u0430\u0432\u0430 \u0438 \u0431\u0438\u0437\u043d\u0435\u0441-\u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u043f\u0438\u0448\u0443\u0442 \u043e\u0434\u0438\u043d \u0440\u0430\u0437 \u043d\u0430 PHP. \u041e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 API-\u0441\u043b\u043e\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0443\u0436\u0435\u043d \u0442\u043e\u043b\u044c\u043a\u043e \u0441\u0432\u043e\u0435\u043c\u0443 \u0436\u0435 \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434\u0443, \u043d\u0435 \u043f\u043e\u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f. \u041d\u0435\u0442 \u0438 \u0441\u0431\u043e\u0440\u0449\u0438\u043a\u0430 \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434\u0430: \u043d\u0438 Node, \u043d\u0438 \u0431\u0430\u043d\u0434\u043b\u0435\u0440\u0430, \u043d\u0438 <code>node_modules<\/code>. \u041a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u0441\u043e\u0431\u0438\u0440\u0430\u044e\u0442\u0441\u044f \u0441\u0430\u043c\u0438 \u043f\u0440\u0438 \u043f\u0435\u0440\u0432\u043e\u043c \u0437\u0430\u043f\u0440\u043e\u0441\u0435, \u0430 <code>rig build<\/code> \u043f\u0435\u0440\u0435\u0434 \u0432\u044b\u043a\u043b\u0430\u0434\u043a\u043e\u0439 \u043f\u0440\u043e\u0433\u0440\u0435\u0432\u0430\u0435\u0442 \u043a\u0435\u0448 \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442 \u0448\u0430\u0431\u043b\u043e\u043d\u044b \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438. \u041f\u0435\u0440\u0432\u0430\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u043e\u0442\u0434\u0430\u0451\u0442 \u0433\u043e\u0442\u043e\u0432\u044b\u0439 HTML, \u044d\u0442\u043e \u0431\u044b\u0441\u0442\u0440\u043e \u0434\u043b\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0438 \u0443\u0434\u043e\u0431\u043d\u043e \u0434\u043b\u044f \u043f\u043e\u0438\u0441\u043a\u043e\u0432\u0438\u043a\u043e\u0432.<\/p>\n<p>\u0422\u0430\u043c, \u0433\u0434\u0435 \u0432\u0430\u0436\u0435\u043d \u043e\u0442\u043a\u043b\u0438\u043a, \u0437\u0430\u0434\u0435\u0440\u0436\u043a\u0438 \u043d\u0435\u0442: <code>#[Client]<\/code>, \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f <code>#[Computed]<\/code> \u0438 optimistic-\u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u0431\u0435\u0437 \u043e\u0431\u0440\u0430\u0449\u0435\u043d\u0438\u044f \u043a \u0441\u0435\u0442\u0438. \u041f\u0440\u0438 \u044d\u0442\u043e\u043c \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u043e\u0441\u0442\u0430\u044e\u0442\u0441\u044f \u043f\u043e\u0434 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0435\u043c PHP.<\/p>\n<p>\u0421 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u044c\u044e \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0442\u044c \u043d\u0435 \u043d\u0443\u0436\u043d\u043e. \u0421\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043f\u043e\u0434\u043f\u0438\u0441\u0430\u043d\u043e, \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \u0441 <code>#[Locked]<\/code> \u0438 <code>#[Prop]<\/code> \u0438\u0437 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430 \u043d\u0435 \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c, \u0432\u044b\u0437\u0432\u0430\u0442\u044c \u043c\u043e\u0436\u043d\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u043c\u0435\u0442\u043e\u0434\u044b \u0441 <code>#[Action]<\/code>. CSRF \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u044b \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e. \u041e\u0448\u0438\u0431\u043a\u0443 \u0432 \u0448\u0430\u0431\u043b\u043e\u043d\u0435 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440 \u043d\u0430\u0439\u0434\u0451\u0442 \u0440\u0430\u043d\u044c\u0448\u0435, \u0447\u0435\u043c \u0435\u0451 \u0443\u0432\u0438\u0434\u0438\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c.<\/p>\n<p>\u0414\u043b\u044f \u043c\u0435\u043d\u044f \u0433\u043b\u0430\u0432\u043d\u043e\u0435 \u0432\u043e\u0442 \u0447\u0442\u043e: \u0447\u0442\u043e\u0431\u044b \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441, \u0431\u044d\u043a\u0435\u043d\u0434\u0435\u0440\u0443 \u0445\u0432\u0430\u0442\u0430\u0435\u0442 PHP, \u0438 \u043d\u0435 \u043d\u0443\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u0434\u0440\u0443\u0433\u043e\u0439 \u0441\u0442\u0435\u043a.<\/p>\n<h3>\u041e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f<\/h3>\n<p>\u041a\u0430\u0436\u0434\u043e\u0435 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442 \u0437\u0430\u043f\u0440\u043e\u0441, \u0438 \u043d\u0430 \u043c\u0435\u0434\u043b\u0435\u043d\u043d\u043e\u0439 \u0441\u0435\u0442\u0438 \u044d\u0442\u043e \u0437\u0430\u043c\u0435\u0442\u043d\u043e. Optimistic-\u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f, <code>#[Client]<\/code>, <code>#[Computed]<\/code> \u0438 <code>debounce<\/code> \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0441\u0433\u043b\u0430\u0436\u0438\u0432\u0430\u044e\u0442, \u043d\u043e \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0434\u043e\u043b\u0436\u0435\u043d \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043e\u0444\u043b\u0430\u0439\u043d, \u0438\u043b\u0438 \u0442\u044f\u0436\u0451\u043b\u044b\u0439 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440 \u044f \u0431\u044b \u0432\u0441\u0451 \u0440\u0430\u0432\u043d\u043e \u0434\u0435\u043b\u0430\u043b \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435. \u0414\u043b\u044f \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u0432\u0438\u0434\u0436\u0435\u0442\u0430 \u0445\u0432\u0430\u0442\u0430\u0435\u0442 <code>r-js<\/code>.<\/p>\n<p>\u041f\u0440\u043e\u0435\u043a\u0442 \u0435\u0449\u0451 \u043c\u043e\u043b\u043e\u0434\u043e\u0439. \u0413\u043e\u0442\u043e\u0432\u044b\u0445 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u043e\u0442 \u0441\u043e\u043e\u0431\u0449\u0435\u0441\u0442\u0432\u0430 \u043d\u0435\u0442, \u043d\u0435\u0442 \u0432\u0435\u0440\u0441\u0438\u0439 \u043f\u043e semver, \u0432 \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u0435\u043d\u0435 \u043f\u043e\u043a\u0430 \u043d\u0435\u0442 \u0440\u0435\u0430\u043b\u044c\u043d\u044b\u0445 \u0432\u043d\u0435\u0434\u0440\u0435\u043d\u0438\u0439. \u041f\u0435\u0440\u0435\u0432\u043e\u0434\u0438\u0442\u044c \u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u0436\u0438\u0432\u043e\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 \u043d\u0430 rig \u044f \u043f\u043e\u043a\u0430 \u043d\u0435 \u0441\u0442\u0430\u043b \u0431\u044b.<\/p>\n<p>\u0425\u0430\u0431 \u0441\u043e\u0431\u044b\u0442\u0438\u0439 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0432\u043d\u0443\u0442\u0440\u0438 \u043e\u0434\u043d\u043e\u0433\u043e \u0441\u0435\u0440\u0432\u0435\u0440\u0430. \u0414\u043b\u044f \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u0432 \u043d\u0443\u0436\u0435\u043d Redis pub\/sub, \u043e\u043d \u0432 \u043f\u043b\u0430\u043d\u0430\u0445.<\/p>\n<p>\u0422\u0435\u0441\u0442\u0430\u043c\u0438 \u043f\u043e\u043a\u0440\u044b\u0442\u044b \u044f\u0437\u044b\u043a \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0439, \u0431\u044d\u043a\u0435\u043d\u0434 \u0438 \u0434\u0438\u0440\u0435\u043a\u0442\u0438\u0432\u044b \u0448\u0430\u0431\u043b\u043e\u043d\u043e\u0432. \u0410\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432 \u0440\u0430\u043d\u0442\u0430\u0439\u043c\u0430 \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435 \u0438 CI \u043f\u043e\u043a\u0430 \u043d\u0435\u0442. \u041d\u0435\u0442 \u0438 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f \u0434\u043b\u044f \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430 \u0441 \u043f\u043e\u0434\u0441\u043a\u0430\u0437\u043a\u0430\u043c\u0438 \u0432 \u0448\u0430\u0431\u043b\u043e\u043d\u0430\u0445, \u0438 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u043d\u044b\u0445 devtools.<\/p>\n<h3>\u041a\u043e\u043c\u0443 \u043f\u043e\u0434\u043e\u0439\u0434\u0451\u0442<\/h3>\n<ul>\n<li>\n<p>PHP-\u043a\u043e\u043c\u0430\u043d\u0434\u0430\u043c, \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u043d\u0443\u0436\u0435\u043d \u0436\u0438\u0432\u043e\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0431\u0435\u0437 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434\u0430: \u0430\u0434\u043c\u0438\u043d\u043a\u0438, \u043b\u0438\u0447\u043d\u044b\u0435 \u043a\u0430\u0431\u0438\u043d\u0435\u0442\u044b, \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u0435 \u0441\u0438\u0441\u0442\u0435\u043c\u044b, CRM, \u0434\u0430\u0448\u0431\u043e\u0440\u0434\u044b.<\/p>\n<\/li>\n<li>\n<p>\u0421\u0430\u0439\u0442\u0430\u043c, \u0433\u0434\u0435 \u0432\u0430\u0436\u043d\u044b SEO \u0438 \u0431\u044b\u0441\u0442\u0440\u0430\u044f \u043f\u0435\u0440\u0432\u0430\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430, \u043d\u043e \u0431\u0435\u0437 \u0438\u043d\u0442\u0435\u0440\u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u0438 \u043d\u0435 \u043e\u0431\u043e\u0439\u0442\u0438\u0441\u044c: \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0438, \u0444\u0438\u043b\u044c\u0442\u0440\u044b, \u043a\u043e\u0440\u0437\u0438\u043d\u044b.<\/p>\n<\/li>\n<li>\n<p>\u041d\u0435\u0431\u043e\u043b\u044c\u0448\u0438\u043c \u043a\u043e\u043c\u0430\u043d\u0434\u0430\u043c \u0438 \u0442\u0435\u043c, \u043a\u0442\u043e \u043f\u0438\u0448\u0435\u0442 \u0432 \u043e\u0434\u0438\u043d\u043e\u0447\u043a\u0443 \u0438 \u043d\u0435 \u0445\u043e\u0447\u0435\u0442 \u0442\u044f\u043d\u0443\u0442\u044c \u0432\u0442\u043e\u0440\u043e\u0439 \u0441\u0442\u0435\u043a.<\/p>\n<\/li>\n<\/ul>\n<h3>\u041f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c<\/h3>\n<p>\u041a\u043e\u0434 \u043b\u0435\u0436\u0438\u0442 \u043d\u0430 GitHub: <a href=\"https:\/\/github.com\/msdoc11\/rig\" rel=\"noopener nofollow\">github.com\/msdoc11\/rig<\/a>.<\/p>\n<pre><code class=\"bash\">git clone https:\/\/github.com\/msdoc11\/rig.gitcd rigcp .env.example .env   # \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438: \u0431\u0430\u0437\u0430 PostgreSQL \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u043f\u043e\u0447\u0442\u0430 \u0432 \u0436\u0443\u0440\u043d\u0430\u043b.\/rig.sh install       # \u043e\u0434\u0438\u043d \u0440\u0430\u0437: \u043a\u043e\u043c\u0430\u043d\u0434\u0430 rig \u0432 \u043b\u044e\u0431\u043e\u043c \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b\u0435 (PowerShell: .\\rig install)rig dev                # \u0431\u0430\u0437\u0430, \u0441\u0435\u0440\u0432\u0435\u0440, HMR \u0438 \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0441\u0440\u0430\u0437\u0443<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><span class=\"sc-logo-wrapper icon-only\"><\/span><\/a><\/div><\/pre>\n<p>\u0412 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438 \u0435\u0441\u0442\u044c \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f \u043d\u0430 24 \u0440\u0430\u0437\u0434\u0435\u043b\u0430 (<code>\/docs<\/code>) \u0438 \u0434\u0435\u043c\u043e (<code>\/demo<\/code>):<\/p>\n<ul>\n<li>\n<p>\u0441\u0447\u0451\u0442\u0447\u0438\u043a;<\/p>\n<\/li>\n<li>\n<p>\u0437\u0430\u0434\u0430\u0447\u0438 \u0432 PostgreSQL \u0441 \u0441\u043e\u0431\u044b\u0442\u0438\u044f\u043c\u0438 \u043c\u0435\u0436\u0434\u0443 \u0432\u043a\u043b\u0430\u0434\u043a\u0430\u043c\u0438;<\/p>\n<\/li>\n<li>\n<p>\u043b\u0435\u043d\u0438\u0432\u044b\u0439 \u043a\u0430\u0442\u0430\u043b\u043e\u0433;<\/p>\n<\/li>\n<li>\n<p>\u0432\u0445\u043e\u0434 \u0438 \u043a\u0430\u0431\u0438\u043d\u0435\u0442 \u0441 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u043e\u0439 \u0430\u0432\u0430\u0442\u0430\u0440\u0430;<\/p>\n<\/li>\n<li>\n<p>\u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u0441 <code>r-model<\/code> \u043d\u0430 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430\u0445, \u043e\u0431\u0449\u0435\u0439 \u043a\u043e\u0440\u0437\u0438\u043d\u043e\u0439, \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u044f\u043c\u0438, \u0433\u0440\u0430\u0444\u0438\u043a\u043e\u043c \u043d\u0430 <code>r-js<\/code> \u0438 \u043f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435\u043c \u044f\u0437\u044b\u043a\u0430.<\/p>\n<\/li>\n<\/ul>\n<h3>\u0427\u0442\u043e \u0434\u0430\u043b\u044c\u0448\u0435<\/h3>\n<p>\u0412 \u0431\u043b\u0438\u0436\u0430\u0439\u0448\u0438\u0445 \u043f\u043b\u0430\u043d\u0430\u0445:<\/p>\n<ul>\n<li>\n<p>\u0442\u0435\u0441\u0442\u044b \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f: <code>Rig::test(Counter::class)-&gt;call('increment')-&gt;assertSet('count', 1)<\/code>;<\/p>\n<\/li>\n<li>\n<p>\u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 \u0434\u043b\u044f VS Code \u0441 \u043f\u043e\u0434\u0441\u043a\u0430\u0437\u043a\u0430\u043c\u0438 \u0441\u0432\u043e\u0439\u0441\u0442\u0432 \u0438 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439 \u0432 \u0448\u0430\u0431\u043b\u043e\u043d\u0430\u0445;<\/p>\n<\/li>\n<li>\n<p>devtools \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435;<\/p>\n<\/li>\n<li>\n<p>\u0445\u0430\u0431 \u043d\u0430 Redis;<\/p>\n<\/li>\n<li>\n<p>\u0433\u0435\u043d\u0435\u0440\u0430\u0442\u043e\u0440\u044b <code>rig make:*<\/code>;<\/p>\n<\/li>\n<li>\n<p>\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f \u043d\u0430 \u0430\u043d\u0433\u043b\u0438\u0439\u0441\u043a\u043e\u043c.<\/p>\n<\/li>\n<\/ul>\n<p>\u041f\u0438\u0448\u0438\u0442\u0435 \u0432 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u044f\u0445, \u043a\u0430\u043a\u0438\u0435 \u0437\u0430\u0434\u0430\u0447\u0438 \u0432\u044b \u0431\u044b \u0440\u0435\u0448\u0430\u043b\u0438 \u043d\u0430 rig \u0438 \u0433\u0434\u0435, \u043f\u043e-\u0432\u0430\u0448\u0435\u043c\u0443, \u0442\u0430\u043a\u043e\u0439 \u043f\u043e\u0434\u0445\u043e\u0434 \u043d\u0435 \u0441\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442.<\/p>\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\/articles\/1096696\/\">https:\/\/habr.com\/ru\/articles\/1096696\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u041f\u0440\u0438\u0432\u0435\u0442, \u0425\u0430\u0431\u0440! \u041f\u0438\u0448\u0443 \u0441\u0432\u043e\u044e \u043f\u0435\u0440\u0432\u0443\u044e \u0441\u0442\u0430\u0442\u044c\u044e. \u0423\u0436\u0435 \u0431\u043e\u043b\u044c\u0448\u0435 \u0434\u0435\u0441\u044f\u0442\u0438 \u043b\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u044e \u0441 PHP: \u0434\u0435\u043b\u0430\u044e \u0430\u0434\u043c\u0438\u043d\u043a\u0438, CRM, \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442-\u043c\u0430\u0433\u0430\u0437\u0438\u043d\u044b \u0438 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u0435 \u0441\u0438\u0441\u0442\u0435\u043c\u044b.\u041f\u043e\u0447\u0442\u0438 \u0432 \u043a\u0430\u0436\u0434\u043e\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u0440\u0430\u043d\u043e \u0438\u043b\u0438 \u043f\u043e\u0437\u0434\u043d\u043e \u043f\u043e\u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0437\u0430\u043f\u0440\u043e\u0441 \u00ab\u0447\u0442\u043e\u0431\u044b \u0431\u0435\u0437 \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438\u00bb. \u0418 \u0440\u044f\u0434\u043e\u043c \u0441 PHP \u0432\u044b\u0440\u0430\u0441\u0442\u0430\u0435\u0442 \u0432\u0442\u043e\u0440\u043e\u0439 \u043a\u0443\u0441\u043e\u043a: \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434 \u0441\u043e \u0441\u0431\u043e\u0440\u0449\u0438\u043a\u043e\u043c, node_modules, API \u043c\u0435\u0436\u0434\u0443 \u0434\u0432\u0443\u043c\u044f \u0447\u0430\u0441\u0442\u044f\u043c\u0438, \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u044f \u0432 \u0434\u0432\u0443\u0445 \u043c\u0435\u0441\u0442\u0430\u0445, \u0430 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0442\u043e \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435, \u0442\u043e \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435. \u041c\u0435\u043d\u044f \u044d\u0442\u043e \u0434\u043e\u0441\u0442\u0430\u043b\u043e, \u0438 \u044f \u0441\u043e\u0437\u0434\u0430\u043b rig. \u042d\u0442\u043e PHP-\u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a, \u0433\u0434\u0435 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u043e\u0442\u043a\u043b\u0438\u043a\u0430\u0435\u0442\u0441\u044f \u0441\u0440\u0430\u0437\u0443, \u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043e\u0441\u0442\u0430\u0451\u0442\u0441\u044f \u043e\u0431\u044b\u0447\u043d\u044b\u043c PHP-\u043f\u0440\u043e\u0435\u043a\u0442\u043e\u043c. \u0420\u0430\u0441\u0441\u043a\u0430\u0436\u0443, \u043a\u0430\u043a \u043e\u043d \u0443\u0441\u0442\u0440\u043e\u0435\u043d, \u0447\u0442\u043e \u0443\u0436\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0438 \u0433\u0434\u0435 \u0435\u0433\u043e \u043b\u0443\u0447\u0448\u0435 \u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c.\u041a\u0430\u043a \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u041e\u0434\u0438\u043d \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0436\u0438\u0432\u0451\u0442 \u0432 \u043e\u0434\u043d\u043e\u043c .php-\u0444\u0430\u0439\u043b\u0435. \u0421\u0432\u0435\u0440\u0445\u0443 \u043a\u043b\u0430\u0441\u0441 \u0441 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435\u043c \u0438 \u043b\u043e\u0433\u0438\u043a\u043e\u0439, \u043f\u043e\u0434 \u043d\u0438\u043c \u0448\u0430\u0431\u043b\u043e\u043d \u0438 \u0441\u0442\u0438\u043b\u0438.&lt;?phpnamespace App\\Components;use Rig\\Attr\\{Action, Computed};use Rig\\Component;final class Counter extends Component{    public int $count = 0;    #[Computed(&#8216;count * 2&#8217;)]    public int $double;    #[Action(optimistic: &#8216;count = count + 1&#8217;)]    public function increment(): void    {        $this-&gt;count++;    }}?&gt;&lt;template&gt;  &lt;p&gt;{{ count }} \u00d7 2 = {{ double }}&lt;\/p&gt;  &lt;button @click=&#187;increment&#187;&gt;+&lt;\/button&gt;&lt;\/template&gt;&lt;style&gt;  p { font-size: 24px; }&lt;\/style&gt;\u041d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u0435\u0433\u043e \u0432\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0442 \u0442\u0435\u0433\u043e\u043c:&lt;?php $title = &#8216;\u0421\u0447\u0451\u0442\u0447\u0438\u043a&#8217;; ?&gt;&lt;h1&gt;\u0421\u0447\u0451\u0442\u0447\u0438\u043a&lt;\/h1&gt;&lt;Counter \/&gt;\u0412\u043e\u0442 \u0447\u0442\u043e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442, \u043a\u043e\u0433\u0434\u0430 \u043d\u0430\u0436\u0438\u043c\u0430\u044e\u0442 \u00ab+\u00bb:\u0427\u0438\u0441\u043b\u043e \u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f \u0441\u0440\u0430\u0437\u0443. \u041e\u043f\u0442\u0438\u043c\u0438\u0441\u0442\u0438\u0447\u043d\u043e\u0435 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435 count = count + 1 \u0431\u0440\u0430\u0443\u0437\u0435\u0440 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u0441\u0430\u043c, \u043d\u0435 \u0434\u043e\u0436\u0438\u0434\u0430\u044f\u0441\u044c \u043e\u0442\u0432\u0435\u0442\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0430.\u00d72 \u043f\u0435\u0440\u0435\u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043c\u0433\u043d\u043e\u0432\u0435\u043d\u043d\u043e: #[Computed(&#8216;count * 2&#8217;)] \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0438 \u0432 PHP, \u0438 \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435.\u041d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440 \u0443\u0445\u043e\u0434\u0438\u0442 JSON-\u0437\u0430\u043f\u0440\u043e\u0441: \u00ab\u0443 \u044d\u0442\u043e\u0433\u043e Counter \u0441 \u0442\u0435\u043a\u0443\u0449\u0438\u043c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435\u043c \u0432\u044b\u0437\u043e\u0432\u0438 increment()\u00bb.PHP \u0438\u0441\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u043e\u0431\u044b\u0447\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434 \u043a\u043b\u0430\u0441\u0441\u0430 \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043d\u043e\u0432\u043e\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435.\u0411\u0440\u0430\u0443\u0437\u0435\u0440 \u043c\u0435\u043d\u044f\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u0435 \u0443\u0437\u043b\u044b DOM, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0438\u0437\u043c\u0435\u043d\u0438\u043b\u0438\u0441\u044c.JavaScript \u0432 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0435 \u0438 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 \u043d\u0435\u0442 \u0432\u043e\u043e\u0431\u0449\u0435. \u041e\u043d \u0436\u0438\u0432\u0451\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0432\u043d\u0443\u0442\u0440\u0438 \u0440\u0430\u043d\u0442\u0430\u0439\u043c\u0430 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0430, \u0432\u0435\u0441\u0438\u0442 21 \u041a\u0411 \u0432 gzip, \u0438 \u0437\u0430\u0433\u043b\u044f\u0434\u044b\u0432\u0430\u0442\u044c \u0432 \u043d\u0435\u0433\u043e \u043f\u0440\u0438 \u0440\u0430\u0431\u043e\u0442\u0435 \u043d\u0430\u0434 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435\u043c \u043d\u0435 \u043f\u0440\u0438\u0434\u0451\u0442\u0441\u044f.\u0417\u0430\u0447\u0435\u043c\u0414\u043b\u044f \u0431\u044d\u043a\u0435\u043d\u0434-\u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0436\u0438\u0432\u043e\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0441\u0442\u043e\u0438\u0442 \u0434\u043e\u0440\u043e\u0433\u043e. \u041b\u043e\u0433\u0438\u043a\u0430 \u0440\u0430\u0437\u0431\u0440\u043e\u0441\u0430\u043d\u0430 \u043c\u0435\u0436\u0434\u0443 PHP \u0438 JS, \u0438 \u043a\u0430\u0436\u0434\u044b\u0439 \u0432 \u043a\u043e\u043c\u0430\u043d\u0434\u0435 \u0437\u043d\u0430\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0441\u0432\u043e\u044e \u0447\u0430\u0441\u0442\u044c. \u0412\u043e\u0437\u044c\u043c\u0451\u043c \u043a\u043d\u043e\u043f\u043a\u0443 \u00ab\u0423\u0434\u0430\u043b\u0438\u0442\u044c\u00bb \u0431\u0435\u0437 \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438: \u043d\u0443\u0436\u0435\u043d \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442, \u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f, \u0432\u044b\u0437\u043e\u0432 \u0438\u0437 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430 \u0438 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u043e\u0448\u0438\u0431\u043e\u043a. \u041f\u0440\u0438 \u044d\u0442\u043e\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0438 \u0441\u0435\u0440\u0432\u0435\u0440 \u0432\u0441\u0451 \u0440\u0430\u0432\u043d\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u0432 \u043e\u0434\u043d\u043e\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438. \u0412\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u044e, \u043f\u0440\u0430\u0432\u0430 \u0438 \u0444\u043e\u0440\u043c\u0430\u0442 \u0434\u0430\u0442 \u043f\u0438\u0448\u0435\u0448\u044c \u0434\u0432\u0430\u0436\u0434\u044b. \u0423 \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434\u0430 \u0441\u0432\u043e\u0439 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d \u0438 \u0441\u0432\u043e\u0438 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438, \u0438\u0445 \u0442\u043e\u0436\u0435 \u043d\u0443\u0436\u043d\u043e \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0442\u044c. \u0410 \u0435\u0441\u043b\u0438 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u0442\u0441\u044f \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435, \u0435\u0433\u043e \u0435\u0449\u0451 \u0443\u0447\u0430\u0442 \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u0442\u044c\u0441\u044f \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435, \u0438\u043d\u0430\u0447\u0435 \u043f\u043e\u0438\u0441\u043a\u043e\u0432\u0438\u043a\u0438 \u0443\u0432\u0438\u0434\u044f\u0442 \u043f\u0443\u0441\u0442\u0443\u044e \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443.\u0412 rig \u044d\u0442\u043e \u043e\u0434\u043d\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043d\u0430 \u043e\u0434\u043d\u043e\u043c \u044f\u0437\u044b\u043a\u0435. \u0428\u0430\u0431\u043b\u043e\u043d \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u0442\u0441\u044f \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435, \u0442\u0430\u043a \u0447\u0442\u043e \u043f\u043e\u0438\u0441\u043a\u043e\u0432\u0438\u043a \u0441\u0440\u0430\u0437\u0443 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u0433\u043e\u0442\u043e\u0432\u044b\u0439 HTML. \u0411\u0440\u0430\u0443\u0437\u0435\u0440 \u043f\u043e\u0442\u043e\u043c \u00ab\u043e\u0436\u0438\u0432\u043b\u044f\u0435\u0442\u00bb \u044d\u0442\u0443 \u0440\u0430\u0437\u043c\u0435\u0442\u043a\u0443. \u0412\u0441\u0451, \u0433\u0434\u0435 \u043d\u0443\u0436\u043d\u044b \u0434\u0430\u043d\u043d\u044b\u0435, \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0432 PHP, \u0440\u044f\u0434\u043e\u043c \u0441 \u0431\u0430\u0437\u043e\u0439, \u043f\u0440\u0430\u0432\u0430\u043c\u0438 \u0438 \u0431\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u043e\u0439.\u041a\u0430\u043a \u044d\u0442\u043e \u0443\u0441\u0442\u0440\u043e\u0435\u043d\u043e\u041e\u0434\u0438\u043d \u044f\u0437\u044b\u043a \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0439 \u0438 \u0434\u0432\u0430 \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0442\u043e\u0440\u0430\u0421\u0430\u043c\u043e\u0435 \u043f\u0440\u0438\u044f\u0442\u043d\u043e\u0435 \u0432 rig \u0434\u043b\u044f \u043c\u0435\u043d\u044f \u044d\u0442\u043e \u0448\u0430\u0431\u043b\u043e\u043d\u044b. \u0412\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0432 \u043d\u0438\u0445 \u043f\u0438\u0448\u0443\u0442\u0441\u044f \u043d\u0430 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u043c \u044f\u0437\u044b\u043a\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u043d\u0438\u043c\u0430\u044e\u0442 \u0438 \u0441\u0435\u0440\u0432\u0435\u0440, \u0438 \u0431\u0440\u0430\u0443\u0437\u0435\u0440: {{ count }}, :class=&#187;{active: filter == f}&#187;, r-for=&#187;t in todos&#187;, @click=&#187;remove(t.id)&#187;.\u041f\u0440\u0438 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438 PHP \u0440\u0430\u0437\u0431\u0438\u0440\u0430\u0435\u0442 \u0448\u0430\u0431\u043b\u043e\u043d \u0432 \u0434\u0435\u0440\u0435\u0432\u043e (AST \u0438\u0437 \u043e\u0431\u044b\u0447\u043d\u044b\u0445 \u043c\u0430\u0441\u0441\u0438\u0432\u043e\u0432). \u042d\u0442\u043e \u0434\u0435\u0440\u0435\u0432\u043e \u0438\u0441\u043f\u043e\u043b\u043d\u044f\u044e\u0442 \u0434\u0432\u0430 \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0442\u043e\u0440\u0430: PHP, \u043a\u043e\u0433\u0434\u0430 \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u0442 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443, \u0438 \u0440\u0430\u043d\u0442\u0430\u0439\u043c \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435. \u0421\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0435, \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0442\u0438\u043f\u043e\u0432, \u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043d\u0430 \u043d\u043e\u043b\u044c \u0438 \u0432\u044b\u0432\u043e\u0434 \u0432 \u0441\u0442\u0440\u043e\u043a\u0443 \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u043e, \u0434\u043e \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0433\u043e \u0441\u0438\u043c\u0432\u043e\u043b\u0430. \u0427\u0442\u043e\u0431\u044b \u0442\u0430\u043a \u0438 \u043e\u0441\u0442\u0430\u0432\u0430\u043b\u043e\u0441\u044c, \u0435\u0441\u0442\u044c \u0442\u0435\u0441\u0442\u044b: \u043e\u0434\u043d\u043e \u0438 \u0442\u043e \u0436\u0435 \u0434\u0435\u0440\u0435\u0432\u043e \u043f\u0440\u043e\u0433\u043e\u043d\u044f\u0435\u0442\u0441\u044f \u0447\u0435\u0440\u0435\u0437 \u043e\u0431\u0430 \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0442\u043e\u0440\u0430, \u0438 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u0441\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u044e\u0442\u0441\u044f.\u0427\u0442\u043e \u044d\u0442\u043e \u0434\u0430\u0451\u0442 \u043d\u0430 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0435? \u0412\u0441\u0451, \u0447\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0441\u0447\u0438\u0442\u0430\u0442\u044c \u0431\u0435\u0437 \u0441\u0435\u0440\u0432\u0435\u0440\u0430, \u0431\u0440\u0430\u0443\u0437\u0435\u0440 \u0441\u0447\u0438\u0442\u0430\u0435\u0442 \u0441\u0440\u0430\u0437\u0443. \u0410 \u043a\u043e\u0433\u0434\u0430 \u043d\u0443\u0436\u043d\u044b \u0434\u0430\u043d\u043d\u044b\u0435, \u0441\u0447\u0438\u0442\u0430\u0435\u0442 PHP. HTML \u0441 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442 \u0440\u043e\u0432\u043d\u043e \u0442\u0430\u043a\u0438\u043c, \u043a\u0430\u043a\u0438\u043c \u0435\u0433\u043e \u043d\u0430\u0440\u0438\u0441\u043e\u0432\u0430\u043b \u0431\u044b \u0431\u0440\u0430\u0443\u0437\u0435\u0440, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u0440\u0438 \u0433\u0438\u0434\u0440\u0430\u0446\u0438\u0438 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u043d\u0435 \u043f\u0435\u0440\u0435\u0440\u0438\u0441\u043e\u0432\u044b\u0432\u0430\u0435\u0442\u0441\u044f.\u041e\u0448\u0438\u0431\u043a\u0438 \u043b\u043e\u0432\u0438\u0442 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440\u0428\u0430\u0431\u043b\u043e\u043d\u044b \u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u0437\u0430\u0440\u0430\u043d\u0435\u0435, \u0438 \u043a\u0430\u0436\u0434\u043e\u0435 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0441\u0432\u0435\u0440\u044f\u0435\u0442\u0441\u044f \u0441\u043e \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430\u043c\u0438 \u043a\u043b\u0430\u0441\u0441\u0430. \u041e\u0448\u0438\u0431\u043b\u0438\u0441\u044c, \u0438 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u044f \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f:\u2716 TodoItem  \u041d\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043d\u0430\u044f \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0430\u044f \u00abnmae\u00bb \u2014 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c, \u00abname\u00bb?  app\/components\/TodoItem.php:15\u0412 \u0440\u0435\u0436\u0438\u043c\u0435 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0442\u0430 \u0436\u0435 \u043e\u0448\u0438\u0431\u043a\u0430 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0439 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435\u0439: \u043a\u043e\u0434 \u0432\u043e\u043a\u0440\u0443\u0433 \u0441\u0442\u0440\u043e\u043a\u0438, \u043a\u043d\u043e\u043f\u043a\u0430 \u00ab\u041e\u0442\u043a\u0440\u044b\u0442\u044c \u0432 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0435\u00bb \u0438 \u0433\u043e\u0442\u043e\u0432\u044b\u0439 \u043f\u0440\u043e\u043c\u043f\u0442 \u0434\u043b\u044f \u0418\u0418-\u0430\u0433\u0435\u043d\u0442\u0430. \u0412 \u043f\u0440\u043e\u043c\u043f\u0442\u0435 \u0443\u0436\u0435 \u043b\u0435\u0436\u0430\u0442 \u043e\u0448\u0438\u0431\u043a\u0430, \u043a\u043e\u0434, \u043f\u0443\u0442\u044c \u0432\u044b\u0437\u043e\u0432\u0430 \u0438 \u0437\u0430\u0434\u0430\u0447\u0430 \u043d\u0430\u0439\u0442\u0438 \u043f\u0440\u0438\u0447\u0438\u043d\u0443 \u0438 \u043f\u043e\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0435\u0451 \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u043c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435\u043c.\u0413\u0434\u0435 \u0436\u0438\u0432\u0451\u0442 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435\u0417\u0430 \u044d\u0442\u043e \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0430\u0442\u0440\u0438\u0431\u0443\u0442 \u043d\u0430\u0434 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e\u043c:public array $todos = [];              \/\/ \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435, \u043c\u0435\u0436\u0434\u0443 \u0437\u0430\u043f\u0440\u043e\u0441\u0430\u043c\u0438 \u043b\u0435\u0436\u0438\u0442 \u0432 \u043f\u043e\u0434\u043f\u0438\u0441\u0430\u043d\u043d\u043e\u043c \u0441\u043d\u0438\u043c\u043a\u0435#[Locked]                              \/\/ \u0431\u0440\u0430\u0443\u0437\u0435\u0440 \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0438\u0441\u043b\u0430\u0442\u044c \u043d\u043e\u0432\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435public int $userId;#[Client]                              \/\/ \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435: \u0432\u043a\u043b\u0430\u0434\u043a\u0438, \u043c\u043e\u0434\u0430\u043b\u043a\u0438, \u0444\u0438\u043b\u044c\u0442\u0440\u044b, \u0431\u0435\u0437 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432public string $filter = &#8216;all&#8217;;#[Computed(&#171;where(todos, &#8216;done&#8217;, false) | len&#187;)]public int $left;                      \/\/ \u0441\u0447\u0438\u0442\u0430\u0435\u0442\u0441\u044f \u0438 \u0432 PHP, \u0438 \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435#[Shared(&#8216;cart&#8217;, persist: true)]       \/\/ \u043e\u0434\u043d\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u0441 \u044d\u0442\u0438\u043c \u043a\u043b\u044e\u0447\u043e\u043cpublic array $cart = [];\u0421\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043c\u0435\u0436\u0434\u0443 \u0437\u0430\u043f\u0440\u043e\u0441\u0430\u043c\u0438 \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f \u043f\u0440\u044f\u043c\u043e \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435, \u0432 \u0441\u043d\u0438\u043c\u043a\u0435 \u0441 \u043f\u043e\u0434\u043f\u0438\u0441\u044c\u044e HMAC-SHA256. \u0411\u0435\u0437 \u043a\u043b\u044e\u0447\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0435\u0433\u043e \u043d\u0435 \u043f\u043e\u0434\u0434\u0435\u043b\u0430\u0435\u0448\u044c. \u0417\u0430\u043e\u0434\u043d\u043e \u0441\u0435\u0440\u0432\u0435\u0440\u0443 \u043d\u0435 \u043d\u0443\u0436\u043d\u043e \u043f\u043e\u043c\u043d\u0438\u0442\u044c \u043a\u0430\u0436\u0434\u0443\u044e \u043e\u0442\u043a\u0440\u044b\u0442\u0443\u044e \u0432\u043a\u043b\u0430\u0434\u043a\u0443.\u0412\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b\u041e\u0434\u0438\u043d \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0432\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0432 \u0448\u0430\u0431\u043b\u043e\u043d \u0434\u0440\u0443\u0433\u043e\u0433\u043e \u0442\u0435\u0433\u043e\u043c. \u0420\u043e\u0434\u0438\u0442\u0435\u043b\u044c \u043e\u0442\u0434\u0430\u0451\u0442 \u0435\u043c\u0443 \u0434\u0430\u043d\u043d\u044b\u0435 \u0447\u0435\u0440\u0435\u0437 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b, \u0430 \u0434\u043e\u0447\u0435\u0440\u043d\u0438\u0439 \u0441\u043e\u043e\u0431\u0449\u0430\u0435\u0442 \u0441\u043e\u0431\u044b\u0442\u0438\u044f\u043c\u0438, \u0447\u0442\u043e \u0441\u0434\u0435\u043b\u0430\u043b \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c. \u041a\u0430\u043a \u043d\u0430 \u044d\u0442\u043e \u0440\u0435\u0430\u0433\u0438\u0440\u043e\u0432\u0430\u0442\u044c, \u0440\u0435\u0448\u0430\u0435\u0442 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c.\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0441\u0442\u0440\u043e\u043a\u0430 \u0441\u043f\u0438\u0441\u043a\u0430 \u0437\u0430\u0434\u0430\u0447 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u0437\u0430\u0434\u0430\u0447\u0443 \u0447\u0435\u0440\u0435\u0437 #[Prop] \u0438 \u0441\u043e\u043e\u0431\u0449\u0430\u0435\u0442 \u043e \u043a\u043b\u0438\u043a\u0435 \u0447\u0435\u0440\u0435\u0437 emit():\/\/ \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 TodoItem: app\/components\/TodoItem.phpfinal class TodoItem extends Component{    public const TAG = &#8216;li&#8217;;   \/\/ \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u0442\u0441\u044f \u0432\u043d\u0443\u0442\u0440\u0438 &lt;li&gt;, \u0430 \u043d\u0435 &lt;div&gt;    #[Prop]    public array $todo = [];}?&gt;&lt;template&gt;  &lt;input type=&#187;checkbox&#187; :checked=&#187;todo.done&#187; @change=&#187;emit(&#8216;toggle&#8217;, $event.target.checked)&#187;&gt;  {{ todo.title }}  &lt;button @click=&#187;emit(&#8216;remove&#8217;)&#187;&gt;\u00d7&lt;\/button&gt;&lt;\/template&gt;\u0421\u043f\u0438\u0441\u043e\u043a \u0432\u044b\u0432\u043e\u0434\u0438\u0442 \u043f\u043e \u0441\u0442\u0440\u043e\u043a\u0435 \u043d\u0430 \u043a\u0430\u0436\u0434\u0443\u044e \u0437\u0430\u0434\u0430\u0447\u0443 \u0438 \u043d\u0430 \u0435\u0451 \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442 \u0441\u0432\u043e\u0438 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f. \u0412 $event \u043f\u043e\u043f\u0430\u0434\u0430\u0435\u0442 \u0442\u043e, \u0447\u0442\u043e \u0441\u0442\u0440\u043e\u043a\u0430 \u043f\u0435\u0440\u0435\u0434\u0430\u043b\u0430 \u0432 emit(), \u0432 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0447\u0435\u043a\u0431\u043e\u043a\u0441\u0430:&lt;!&#8212; \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 TodoList: \u0448\u0430\u0431\u043b\u043e\u043d \u0432 app\/components\/TodoList.php &#8212;&gt;&lt;ul&gt;  &lt;TodoItem r-for=&#187;t in todos&#187; :key=&#187;t.id&#187; :todo=&#187;t&#187;            @toggle=&#187;setDone(t.id, $event)&#187;            @remove=&#187;remove(t.id)&#187; \/&gt;&lt;\/ul&gt;\u0418\u043d\u043e\u0433\u0434\u0430 \u0434\u043e\u0447\u0435\u0440\u043d\u0438\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u043c\u0435\u043d\u044f\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u043d\u043e-\u0435\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435. \u0422\u043e\u0433\u0434\u0430 \u0443\u0434\u043e\u0431\u043d\u043e \u043f\u0440\u0438\u0432\u044f\u0437\u0430\u0442\u044c \u0435\u0433\u043e \u043a \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044e \u0447\u0435\u0440\u0435\u0437 r-model, \u043a\u0430\u043a \u043e\u0431\u044b\u0447\u043d\u043e\u0435 \u043f\u043e\u043b\u0435 \u0432\u0432\u043e\u0434\u0430. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043f\u043e\u043c\u0435\u0447\u0430\u0435\u043c \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u043e\u043c #[Model]:\/\/ \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 Rating: app\/components\/Rating.phpfinal class Rating extends Component{    #[Prop, Model]    public int $value = 0;}?&gt;&lt;template&gt;  &lt;button r-for=&#187;n in [1, 2, 3, 4, 5]&#187; :key=&#187;n&#187; :class=&#187;{on: n &lt;= value}&#187; @click=&#187;value = n&#187;&gt;\u2605&lt;\/button&gt;&lt;\/template&gt;&lt;Rating r-model=&#187;score&#187; \/&gt;   &lt;!&#8212; \u043a\u043b\u0438\u043a \u043f\u043e \u0437\u0432\u0435\u0437\u0434\u0435 \u043c\u0435\u043d\u044f\u0435\u0442 score \u0443 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044f &#8212;&gt;\u0420\u0430\u0437\u043c\u0435\u0442\u043a\u0443 \u0432\u043d\u0443\u0442\u0440\u044c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u043f\u0435\u0440\u0435\u0434\u0430\u044e\u0442 \u0441\u043b\u043e\u0442\u0430\u043c\u0438. \u0412 \u0448\u0430\u0431\u043b\u043e\u043d\u0435 \u043a\u0430\u0440\u0442\u043e\u0447\u043a\u0438 \u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u044b \u043c\u0435\u0441\u0442\u0430 &lt;slot&gt; \u0438 &lt;slot name=&#187;footer&#187;&gt;. \u0421\u043d\u0430\u0440\u0443\u0436\u0438 \u044d\u0442\u043e \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0442\u0430\u043a:&lt;Card title=&#187;\u0417\u0430\u0434\u0430\u0447\u0438&#187;&gt;  &lt;TodoList \/&gt;  &lt;template #footer&gt;\u0414\u0432\u043e\u0439\u043d\u043e\u0439 \u0449\u0435\u043b\u0447\u043e\u043a \u043f\u043e \u0437\u0430\u0434\u0430\u0447\u0435 \u043f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u043e\u0432\u044b\u0432\u0430\u0435\u0442 \u0435\u0451&lt;\/template&gt;&lt;\/Card&gt;\u041f\u043e\u0447\u0435\u043c\u0443 \u0443 TodoList \u043d\u0435\u0442 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u043e\u0432? \u041f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043e\u043d \u0441\u0430\u043c \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0442 \u0437\u0430\u0434\u0430\u0447\u0438 \u0432 mount() \u0438 \u0441\u0430\u043c \u043c\u0435\u043d\u044f\u0435\u0442 \u0438\u0445 \u0447\u0435\u0440\u0435\u0437 setDone() \u0438 remove(). \u0415\u0441\u043b\u0438 \u0431\u044b \u0441\u043f\u0438\u0441\u043e\u043a \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u043b \u0438\u0437\u0432\u043d\u0435 \u0447\u0435\u0440\u0435\u0437 #[Prop], \u043c\u0435\u043d\u044f\u0442\u044c \u0435\u0433\u043e \u0432\u043d\u0443\u0442\u0440\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u0431\u044b\u043b\u043e \u0431\u044b \u043d\u0435\u043b\u044c\u0437\u044f, \u0438 \u0432\u0441\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u0431\u044b \u043f\u0435\u0440\u0435\u043d\u043e\u0441\u0438\u0442\u044c \u0432 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044f. \u0414\u043b\u044f \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u0441\u0434\u0435\u043b\u0430\u043d\u043e \u0432\u043d\u0443\u0442\u0440\u0438 \u043a\u043e\u043c\u043f\u0430\u043d\u0435\u043d\u0442\u0430.\u041f\u0435\u0440\u0435\u0445\u043e\u0434\u044b, \u043a\u0435\u0448 \u0438 \u043b\u0435\u043d\u0438\u0432\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435\u0421\u0441\u044b\u043b\u043a\u0438 \u0432\u043d\u0443\u0442\u0440\u0438 \u0441\u0430\u0439\u0442\u0430 \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u0431\u0435\u0437 \u043f\u043e\u043b\u043d\u043e\u0439 \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438. \u0421\u0435\u0440\u0432\u0435\u0440 \u043e\u0442\u0434\u0430\u0451\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u043d\u0443\u0436\u043d\u043e\u0439 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b, \u0430 layout \u0438 \u0435\u0433\u043e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u043e\u0441\u0442\u0430\u044e\u0442\u0441\u044f \u043d\u0430 \u043c\u0435\u0441\u0442\u0435 \u0441\u043e \u0441\u0432\u043e\u0438\u043c \u0442\u0435\u043a\u0443\u0449\u0438\u043c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435\u043c.\u0421\u0442\u0440\u0430\u043d\u0438\u0446\u0430, \u0441 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0443\u0448\u043b\u0438, \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u0442\u0441\u044f \u0432 rig \u0432\u043c\u0435\u0441\u0442\u0435 \u0441 \u0436\u0438\u0432\u044b\u043c\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430\u043c\u0438. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043a\u043d\u043e\u043f\u043a\u0430 \u00ab\u041d\u0430\u0437\u0430\u0434\u00bb \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u0435\u0451 \u043c\u0433\u043d\u043e\u0432\u0435\u043d\u043d\u043e, \u0431\u0435\u0437 \u043d\u043e\u0432\u043e\u0433\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0430, \u0441 \u0442\u0435\u043c\u0438 \u0436\u0435 \u0444\u0438\u043b\u044c\u0442\u0440\u0430\u043c\u0438, \u043f\u043e\u0434\u0433\u0440\u0443\u0436\u0435\u043d\u043d\u044b\u043c\u0438 \u0442\u043e\u0432\u0430\u0440\u0430\u043c\u0438, \u0432\u0432\u0435\u0434\u0451\u043d\u043d\u044b\u043c \u0442\u0435\u043a\u0441\u0442\u043e\u043c \u0438 \u0442\u0435\u043a\u0443\u0449\u0435\u0439 \u043f\u0440\u043e\u043a\u0440\u0443\u0442\u043a\u043e\u0439. \u0415\u0441\u043b\u0438 \u0437\u0430 \u044d\u0442\u043e \u0432\u0440\u0435\u043c\u044f \u0434\u0430\u043d\u043d\u044b\u0435 \u0438\u0437\u043c\u0435\u043d\u0438\u043b\u0438\u0441\u044c, \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u0442\u0438\u0445\u043e \u043e\u0431\u043d\u043e\u0432\u044f\u0442\u0441\u044f \u0432 \u0444\u043e\u043d\u0435.\u041f\u043e\u043a\u0430 \u043a\u0443\u0440\u0441\u043e\u0440 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u043d\u0430\u0434 \u0441\u0441\u044b\u043b\u043a\u043e\u0439, rig \u0443\u0436\u0435 \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u0442 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443, \u0438 \u043a \u043c\u043e\u043c\u0435\u043d\u0442\u0443 \u043a\u043b\u0438\u043a\u0430 \u043e\u0442\u0432\u0435\u0442 \u0433\u043e\u0442\u043e\u0432.\u041c\u0435\u0434\u043b\u0435\u043d\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u043d\u0435 \u0436\u0434\u0451\u0442. \u041a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0441 #[Lazy] \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442 \u0441\u0440\u0430\u0437\u0443 \u0432 \u0432\u0438\u0434\u0435 \u0441\u043a\u0435\u043b\u0435\u0442\u043e\u043d\u0430, \u0430 \u0442\u044f\u0436\u0451\u043b\u0430\u044f \u0432\u044b\u0431\u043e\u0440\u043a\u0430 \u0434\u0435\u043b\u0430\u0435\u0442\u0441\u044f \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u043c \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u043c, \u043a\u043e\u0433\u0434\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u0443\u0436\u0435 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0430. \u0415\u0441\u043b\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0437\u0430 \u044d\u0442\u043e \u0432\u0440\u0435\u043c\u044f \u0443\u0448\u0451\u043b \u0434\u0430\u043b\u044c\u0448\u0435, \u043f\u0435\u0440\u0435\u0445\u043e\u0434 \u0442\u043e\u0436\u0435 \u043d\u0435 \u0436\u0434\u0451\u0442 \u044d\u0442\u0443 \u0432\u044b\u0431\u043e\u0440\u043a\u0443.#[Lazy]final class ProductList extends Component{    #[Locked] public array $items = [];    #[Locked] public int $page = 0;    #[Locked] public bool $hasMore = false;    public function mount(): void    {        $this-&gt;more();   \/\/ \u043f\u0435\u0440\u0432\u0430\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430: \u043c\u0435\u0434\u043b\u0435\u043d\u043d\u0430\u044f \u0432\u044b\u0431\u043e\u0440\u043a\u0430    }    #[Action]    public function more(): void    {        $p = Product::orderBy(&#8216;id&#8217;)-&gt;paginate(9, $this-&gt;page + 1);        $this-&gt;items = [&#8230;$this-&gt;items, &#8230;$p[&#8216;items&#8217;]];        $this-&gt;page = $p[&#8216;page&#8217;];        $this-&gt;hasMore = $p[&#8216;page&#8217;] &lt; $p[&#8216;pages&#8217;];    }}?&gt;&lt;template&gt;  &lt;ul class=&#187;grid&#187;&gt;    &lt;li r-for=&#187;p in items&#187; :key=&#187;p.id&#187;&gt;{{ p.name }}, {{ p.price }} \u20bd&lt;\/li&gt;    &lt;!&#8212; \u043f\u043e\u043a\u0430 \u0433\u0440\u0443\u0437\u0438\u0442\u0441\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0430\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430, \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u0442\u0440\u0438 \u0441\u043a\u0435\u043b\u0435\u0442\u043e\u043d\u0430 &#8212;&gt;    &lt;li r-for=&#187;i in ($pending.more ? [1, 2, 3] : [])&#187; :key=&#187;&#8216;sk&#8217; + i&#187; aria-hidden=&#187;true&#187;&gt;      &lt;div class=&#187;r-sk r-sk-block&#187;&gt;&lt;\/div&gt;    &lt;\/li&gt;  &lt;\/ul&gt;  &lt;button r-if=&#187;hasMore&#187; @click=&#187;more&#187; :disabled=&#187;$busy&#187;&gt;    {{ $pending.more ? &#8216;\u0417\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c\u2026&#8217; : &#8216;\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0435\u0449\u0451&#8217; }}  &lt;\/button&gt;&lt;\/template&gt;&lt;!&#8212; \u0441\u043a\u0435\u043b\u0435\u0442\u043e\u043d, \u0432\u0438\u0434\u0438\u043c\u044b\u0439 \u043f\u043e\u043a\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f mount() &#8212;&gt;&lt;skeleton&gt;  &lt;ul class=&#187;grid&#187; aria-hidden=&#187;true&#187;&gt;    &lt;li r-for=&#187;i in [1, 2, 3, 4, 5, 6]&#187; :key=&#187;i&#187;&gt;      &lt;div class=&#187;r-sk r-sk-block&#187;&gt;&lt;\/div&gt;      &lt;div class=&#187;r-sk r-sk-line&#187; style=&#187;width: 60%&#187;&gt;&lt;\/div&gt;    &lt;\/li&gt;  &lt;\/ul&gt;&lt;\/skeleton&gt;\u0421\u043a\u0435\u043b\u0435\u0442\u043e\u043d \u043f\u0438\u0448\u0435\u0442\u0441\u044f \u0442\u0435\u043c \u0436\u0435 \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441\u043e\u043c, \u0447\u0442\u043e \u0438 \u0448\u0430\u0431\u043b\u043e\u043d, \u0438 \u0441\u0442\u0438\u043b\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u043a \u043d\u0435\u043c\u0443 \u0442\u043e\u0436\u0435 \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u044e\u0442\u0441\u044f. \u0414\u043b\u044f \u043f\u043b\u0430\u0448\u0435\u043a \u0435\u0441\u0442\u044c \u0433\u043e\u0442\u043e\u0432\u044b\u0435 \u043a\u043b\u0430\u0441\u0441\u044b r-sk, r-sk-line \u0438 r-sk-block. \u041e\u043d\u0438 \u043c\u0435\u0440\u0446\u0430\u044e\u0442, \u0443\u0447\u0438\u0442\u044b\u0432\u0430\u044e\u0442 \u0442\u0451\u043c\u043d\u0443\u044e \u0442\u0435\u043c\u0443 \u0438 prefers-reduced-motion.\u0421\u043e\u0431\u044b\u0442\u0438\u044f \u0441 \u0441\u0435\u0440\u0432\u0435\u0440\u0430$this-&gt;broadcast(&#8216;todos-changed&#8217;);     \/\/ \u0434\u0440\u0443\u0433\u0438\u043c \u0432\u043a\u043b\u0430\u0434\u043a\u0430\u043c \u0438 \u0434\u0440\u0443\u0433\u0438\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u043c#[On(&#8216;todos-changed&#8217;)]public function reload(): void{    $this-&gt;todos = Todo::all();}\u0414\u043e\u0441\u0442\u0430\u0432\u043a\u043e\u0439 \u0437\u0430\u043d\u0438\u043c\u0430\u0435\u0442\u0441\u044f \u0445\u0430\u0431. \u0423 \u0432\u043a\u043b\u0430\u0434\u043a\u0438 \u043e\u0434\u043d\u043e SSE-\u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435, \u0438 \u043f\u043e &#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-499410","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/499410","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=499410"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/499410\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=499410"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=499410"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=499410"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}