<?xml version="1.0" encoding="utf-8" ?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:tt="http://teletype.in/" xmlns:opensearch="http://a9.com/-/spec/opensearch/1.1/"><title>GromIT</title><author><name>GromIT</name></author><id>https://teletype.in/atom/gromit</id><link rel="self" type="application/atom+xml" href="https://teletype.in/atom/gromit?offset=0"></link><link rel="alternate" type="text/html" href="https://blog.grom-it.ru/?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=gromit"></link><link rel="next" type="application/rss+xml" href="https://teletype.in/atom/gromit?offset=10"></link><link rel="search" type="application/opensearchdescription+xml" title="Teletype" href="https://teletype.in/opensearch.xml"></link><updated>2026-04-20T00:56:17.260Z</updated><entry><id>gromit:Uzs4ynPVlar</id><link rel="alternate" type="text/html" href="https://blog.grom-it.ru/Uzs4ynPVlar?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=gromit"></link><title>Поддержка внутренней документации к REST API в OctoberCMS</title><published>2021-05-28T12:59:52.428Z</published><updated>2021-05-28T12:59:52.428Z</updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://teletype.in/files/8d/80/8d804592-164b-47f8-851d-e66cf908270e.jpeg"></media:thumbnail><category term="october-cms" label="OctoberCMS"></category><summary type="html">&lt;img src=&quot;https://teletype.in/files/89/fb/89fbc8fb-0dd9-4bd2-9570-7e74bf570d83.jpeg&quot;&gt;Так получилось, что некоторые из последних проектов в нашей компании были выполнены как REST-like API на OctoberCMS + фронтенд на Nuxt.js.</summary><content type="html">
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://teletype.in/files/89/fb/89fbc8fb-0dd9-4bd2-9570-7e74bf570d83.jpeg&quot; width=&quot;1200&quot; /&gt;
  &lt;/figure&gt;
  &lt;h2&gt;Рождение идеи.&lt;/h2&gt;
  &lt;p&gt;Так получилось, что некоторые из последних проектов в нашей компании были выполнены как REST-like API на OctoberCMS + фронтенд на Nuxt.js.&lt;/p&gt;
  &lt;p&gt;Я разрабатывал первую часть и мне надо было как-то рассказывать frontend-разработчику какие роуты есть у нас в API. Для этого я поддерживал коллекцию роутов в Postman. Всё шло не плохо, пока мне, наконец, это не надоело. Тогда меня посетила мысль: &amp;quot;зачем мне поддерживать коллекцию в постмане, если у меня в коде уже всё есть?&amp;quot;. &lt;/p&gt;
  &lt;p&gt;Так родилась идея создания &lt;a href=&quot;https://github.com/gromitsoft/oc-routesbrowser-plugin&quot; target=&quot;_blank&quot;&gt;плагина для OctoberCMS&lt;/a&gt;, про который я расскажу в этой статье.&lt;/p&gt;
  &lt;h2&gt;Плагин GromIT.RoutesBrowser&lt;/h2&gt;
  &lt;p&gt;Итак &lt;strong&gt;GromIT.RoutesBrowser&lt;/strong&gt; - это плагин, который отображает в админке на отдельной странице все роуты вашего приложения (за исключением системных, и роутов темы) с документацией, собираемой из кода и докблоков с помощью Reflection API.&lt;/p&gt;
  &lt;p&gt;Самый простой способ понять, как с этим работать - это создать плагин с файлом &lt;code&gt;routes.php&lt;/code&gt; и добавить какой-нибудь роут. &lt;/p&gt;
  &lt;p&gt;Например, что-то такое:&lt;/p&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;iframe src=&quot;https://carbon.now.sh/embed?bg=rgba%28171%2C+184%2C+195%2C+1%29&amp;t=monokai&amp;wt=none&amp;l=text%2Fx-php&amp;ds=true&amp;dsyoff=20px&amp;dsblur=68px&amp;wc=true&amp;wa=false&amp;pv=56px&amp;ph=56px&amp;ln=false&amp;fl=1&amp;fm=Hack&amp;fs=14px&amp;lh=133%25&amp;si=false&amp;es=2x&amp;wm=false&amp;code=%253C%253Fphp%250A%250ARoute%253A%253Aget%28%27%252Fhello%252F%257Bname%257D%27%252C%2520%255BGreetController%253A%253Aclass%252C%2520%27greet%27%255D%29%253B%250A%250Aclass%2520GreetController%2520extends%2520%255CIlluminate%255CRouting%255CController%250A%257B%250A%2520%2520%2520%2520%252F**%250A%2520%2520%2520%2520%2520*%2520Returns%2520greeting%250A%2520%2520%2520%2520%2520*%250A%2520%2520%2520%2520%2520*%2520%2540param%2520string%2520%2524name%2520Person%2520name%250A%2520%2520%2520%2520%2520*%252F%250A%2520%2520%2520%2520public%2520function%2520greet%28GreetRequest%2520%2524request%252C%2520string%2520%2524name%29%250A%2520%2520%2520%2520%257B%250A%2520%2520%2520%2520%2520%2520%2520%2520%2524greeting%2520%253D%2520%28%2524request-%253Egreeting%2520%253F%253A%2520%27Hello%27%29%2520.%2520%27%252C%2520%27%2520.%2520%2524name%253B%250A%250A%2520%2520%2520%2520%2520%2520%2520%2520if%2520%28%2524request-%253Efriend%29%2520%257B%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2524greeting%2520.%253D%2520%27%2520and%2520%27%2520.%2520%2524request-%253Efriend%253B%250A%2520%2520%2520%2520%2520%2520%2520%2520%257D%250A%250A%2520%2520%2520%2520%2520%2520%2520%2520return%2520response%28%29-%253Ejson%28%255B%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%27greeting%27%2520%253D%253E%2520%2524greeting%250A%2520%2520%2520%2520%2520%2520%2520%2520%255D%29%253B%250A%2520%2520%2520%2520%257D%250A%257D%250A%250A%252F**%250A%2520*%2520%2540property-read%2520string%257Cnull%2520%2524greeting%2520Greeting.%2520Default%2520-%2520%2522Hello%2522%250A%2520*%2520%2540property-read%2520string%257Cnull%2520%2524friend%2520%2520%2520Friend%2520name%250A%2520*%252F%250Aclass%2520GreetRequest%2520extends%2520%255CIlluminate%255CFoundation%255CHttp%255CFormRequest%250A%257B%250A%2520%2520%2520%2520public%2520function%2520rules%28%29%250A%2520%2520%2520%2520%257B%250A%2520%2520%2520%2520%2520%2520%2520%2520return%2520%255B%255D%253B%250A%2520%2520%2520%2520%257D%250A%257D&quot;&gt;&lt;/iframe&gt;
  &lt;/figure&gt;
  &lt;p&gt;Далее, открываем страницу плагина в админке сайта и видим следующую картину:&lt;/p&gt;
  &lt;figure class=&quot;m_retina&quot;&gt;
    &lt;img src=&quot;https://teletype.in/files/6a/5b/6a5b0d42-f7f3-4074-a98e-e333f7c2a96a.png&quot; width=&quot;1080&quot; /&gt;
  &lt;/figure&gt;
  &lt;p&gt;Как видно из скриншота, информация о роуте заполнилась следующим образом:&lt;/p&gt;
  &lt;ul&gt;
    &lt;li&gt;HTTP-метод и URI роута - из самого описания роута в файле &lt;code&gt;route.php&lt;/code&gt;&lt;/li&gt;
    &lt;li&gt;комментарий - из докблока к обработчику роута&lt;/li&gt;
    &lt;li&gt;тип и комментарий к параметру &lt;code&gt;name&lt;/code&gt; из него же&lt;/li&gt;
    &lt;li&gt;параметры запроса с описанием типов и комментариями - из докблока к классу запроса&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p&gt;Также, здесь можно ввести значения параметров, добавить заголовки и выполнить тестовые запросы (пока без файлов и массивов, возможно, они будут добавлены в будущем).&lt;/p&gt;
  &lt;p&gt;Вот, собственно, и всё.&lt;/p&gt;
  &lt;h2&gt;Вместо заключения&lt;/h2&gt;
  &lt;p&gt;Данный плагин - не замена Postman или Swagger и он точно не предназначен для публичных API. Это скорее аналог &lt;code&gt;php artisan route:list&lt;/code&gt; для тех, кому лень идти в терминал.&lt;/p&gt;
  &lt;p&gt;&lt;/p&gt;
  &lt;p&gt;Скачать плагин:&lt;/p&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;a href=&quot;https://github.com/gromitsoft/oc-routesbrowser-plugin&quot; target=&quot;_blank&quot;&gt;GitHub&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;https://packagist.org/packages/gromit/oc-routesbrowser-plugin&quot; target=&quot;_blank&quot;&gt;Packagist&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;

</content></entry><entry><id>gromit:HSzRHt7fq6g</id><link rel="alternate" type="text/html" href="https://blog.grom-it.ru/HSzRHt7fq6g?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=gromit"></link><title>DadataWidgets plugin for OctoberCMS v.2</title><published>2021-05-13T17:37:06.676Z</published><updated>2021-05-13T17:37:06.676Z</updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://teletype.in/files/af/21/af219ac1-6579-44bc-aaa9-ceb734c044aa.jpeg"></media:thumbnail><category term="october-cms" label="OctoberCMS"></category><tt:hashtag>octobercms</tt:hashtag><tt:hashtag>dadata</tt:hashtag><tt:hashtag>widgets</tt:hashtag><summary type="html">&lt;img src=&quot;https://teletype.in/files/a6/76/a676802a-a1a1-4663-8b5c-82f3aa2c9d12.jpeg&quot;&gt;Плагин интеграции подсказок сервиса Dadata в OctoberCMS v.2</summary><content type="html">
  &lt;figure class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://teletype.in/files/a6/76/a676802a-a1a1-4663-8b5c-82f3aa2c9d12.jpeg&quot; width=&quot;1200&quot; /&gt;
  &lt;/figure&gt;
  &lt;p&gt;Плагин интеграции подсказок сервиса Dadata в OctoberCMS v.2&lt;/p&gt;
  &lt;h2&gt;Установка&lt;/h2&gt;
  &lt;pre&gt;composer require gromit/oc-dadatawidgets-plugin&lt;/pre&gt;
  &lt;h2&gt;Настройка&lt;/h2&gt;
  &lt;p&gt;Для использования плагина, необходимо получить токен сервиса Dadata. Получить токен можно бесплатно - необходимо зарегистрироваться на сайте &lt;a href=&quot;https://dadata.ru/&quot; target=&quot;_blank&quot;&gt;https://dadata.ru/&lt;/a&gt; и скопировать его в профиле.&lt;/p&gt;
  &lt;p&gt;Полученный токен (он же АПИ КЛЮЧ) вставляем в настройки плагина через &lt;strong&gt;Настройки -&amp;gt; Dadata Widgets&lt;/strong&gt;&lt;/p&gt;
  &lt;h2&gt;Использование&lt;/h2&gt;
  &lt;p&gt;В конфиге формы указываем тип поля &lt;strong&gt;dadataSuggestions&lt;/strong&gt;, тип подсказки &lt;strong&gt;suggestion&lt;/strong&gt; и привязку данных к полям формы.&lt;/p&gt;
  &lt;p&gt;&lt;strong&gt;Пример конфига поля:&lt;/strong&gt;&lt;/p&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;iframe src=&quot;https://carbon.now.sh/embed?bg=rgba%28171%2C+184%2C+195%2C+1%29&amp;t=monokai&amp;wt=none&amp;l=yaml&amp;ds=true&amp;dsyoff=20px&amp;dsblur=68px&amp;wc=true&amp;wa=true&amp;pv=56px&amp;ph=56px&amp;ln=false&amp;fl=1&amp;fm=Hack&amp;fs=14px&amp;lh=133%25&amp;si=false&amp;es=2x&amp;wm=false&amp;code=name%253A%250A%2520%2520%2520%2520label%253A%2520%25D0%259D%25D0%25B0%25D0%25B7%25D0%25B2%25D0%25B0%25D0%25BD%25D0%25B8%25D0%25B5%2520%25D0%25BA%25D0%25BE%25D0%25BC%25D0%25BF%25D0%25B0%25D0%25BD%25D0%25B8%25D0%25B8%250A%2520%2520%2520%2520type%253A%2520dadataSuggestions%250A%2520%2520%2520%2520suggestion%253A%2520company&quot;&gt;&lt;/iframe&gt;
  &lt;/figure&gt;
  &lt;h2&gt;Маппер&lt;/h2&gt;
  &lt;p&gt;В конфиге поля можно указать соответствие данных, получаемых из сервиса Dadata, и полей формы, куда эти данные вставить.&lt;/p&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;iframe src=&quot;https://carbon.now.sh/embed?bg=rgba%28171%2C+184%2C+195%2C+1%29&amp;t=monokai&amp;wt=none&amp;l=yaml&amp;ds=true&amp;dsyoff=20px&amp;dsblur=68px&amp;wc=true&amp;wa=false&amp;pv=56px&amp;ph=56px&amp;ln=false&amp;fl=1&amp;fm=Hack&amp;fs=14px&amp;lh=133%25&amp;si=false&amp;es=2x&amp;wm=false&amp;code=map%253A%250A%2520%2520%2520%2520%25D0%25B8%25D0%25BC%25D1%258F%2520%25D0%25BF%25D0%25BE%25D0%25BB%25D1%258F1%253A%2520%25D0%25B7%25D0%25BD%25D0%25B0%25D1%2587%25D0%25B5%25D0%25BD%25D0%25B8%25D0%25B5%2520%25D0%25B8%25D0%25B7%2520%25D0%25BE%25D1%2582%25D0%25B2%25D0%25B5%25D1%2582%25D0%25B0%2520Dadata%250A%2520%2520%2520%2520%25D0%25B8%25D0%25BC%25D1%258F%2520%25D0%25BF%25D0%25BE%25D0%25BB%25D1%258F2%253A%2520%25D0%25B7%25D0%25BD%25D0%25B0%25D1%2587%25D0%25B5%25D0%25BD%25D0%25B8%25D0%25B5%2520%25D0%25B8%25D0%25B7%2520%25D0%25BE%25D1%2582%25D0%25B2%25D0%25B5%25D1%2582%25D0%25B0%2520Dadata%250A%2520%2520%2520%2520...%250A%2520%2520%2520%2520%25D0%25B8%25D0%25BC%25D1%258F%2520%25D0%25BF%25D0%25BE%25D0%25BB%25D1%258FN%253A%2520%25D0%25B7%25D0%25BD%25D0%25B0%25D1%2587%25D0%25B5%25D0%25BD%25D0%25B8%25D0%25B5%2520%25D0%25B8%25D0%25B7%2520%25D0%25BE%25D1%2582%25D0%25B2%25D0%25B5%25D1%2582%25D0%25B0%2520Dadata&quot;&gt;&lt;/iframe&gt;
  &lt;/figure&gt;
  &lt;p&gt;Структура возвращаемых данных сервиса Dadata зависит от типа подсказки:&lt;/p&gt;
  &lt;p&gt;suggestion: &lt;strong&gt;company -&amp;gt; &lt;/strong&gt;&lt;a href=&quot;https://dadata.ru/api/suggest/party/#response&quot; target=&quot;_blank&quot;&gt;https://dadata.ru/api/suggest/party/#response&lt;/a&gt;&lt;/p&gt;
  &lt;p&gt;suggestion: &lt;strong&gt;bank -&amp;gt; &lt;/strong&gt;&lt;a href=&quot;https://dadata.ru/api/suggest/bank/#response&quot; target=&quot;_blank&quot;&gt;https://dadata.ru/api/suggest/bank/#response&lt;/a&gt;&lt;/p&gt;
  &lt;p&gt;suggestion: &lt;strong&gt;address -&amp;gt; &lt;/strong&gt;&lt;a href=&quot;https://dadata.ru/api/suggest/address/#response&quot; target=&quot;_blank&quot;&gt;https://dadata.ru/api/suggest/address/#response&lt;/a&gt;&lt;/p&gt;
  &lt;p&gt;suggestion: &lt;strong&gt;email -&amp;gt; &lt;/strong&gt;&lt;a href=&quot;https://dadata.ru/api/suggest/email/#response&quot; target=&quot;_blank&quot;&gt;https://dadata.ru/api/suggest/email/#response&lt;/a&gt;&lt;/p&gt;
  &lt;p&gt;suggestion: &lt;strong&gt;fio -&amp;gt; &lt;/strong&gt;&lt;a href=&quot;https://dadata.ru/api/suggest/name/#response&quot; target=&quot;_blank&quot;&gt;https://dadata.ru/api/suggest/name/#response&lt;/a&gt;&lt;/p&gt;
  &lt;p&gt;Соответственно в маппере используем описанные выше структуры данных.&lt;/p&gt;
  &lt;h2&gt;Примеры&lt;/h2&gt;
  &lt;p&gt;Небольшие примеры использования виджета для разных ситуаций&lt;/p&gt;
  &lt;h3&gt;Поиск контрагента и заполнение нужных полей&lt;/h3&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;iframe src=&quot;https://carbon.now.sh/embed?bg=rgba%28171%2C+184%2C+195%2C+1%29&amp;t=monokai&amp;wt=none&amp;l=yaml&amp;ds=true&amp;dsyoff=20px&amp;dsblur=68px&amp;wc=true&amp;wa=false&amp;pv=56px&amp;ph=56px&amp;ln=false&amp;fl=1&amp;fm=Hack&amp;fs=14px&amp;lh=133%25&amp;si=false&amp;es=2x&amp;wm=false&amp;code=fields%253A%250A%2520%2520%2520%2520name%253A%250A%2520%2520%2520%2520%2520%2520%2520%2520label%253A%2520%25D0%259D%25D0%25B0%25D0%25B7%25D0%25B2%25D0%25B0%25D0%25BD%25D0%25B8%25D0%25B5%2520%25D0%25BA%25D0%25BE%25D0%25BC%25D0%25BF%25D0%25B0%25D0%25BD%25D0%25B8%25D0%25B8%250A%2520%2520%2520%2520%2520%2520%2520%2520type%253A%2520dadataSuggestions%250A%2520%2520%2520%2520%2520%2520%2520%2520suggestion%253A%2520company%250A%2520%2520%2520%2520%2520%2520%2520%2520map%253A%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520name%253A%2520value%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520inn%253A%2520data.inn%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520kpp%253A%2520data.kpp%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520ogrn%253A%2520data.ogrn%250A%2520%2520%2520%2520inn%253A%250A%2520%2520%2520%2520%2520%2520%2520%2520label%253A%2520%25D0%2598%25D0%259D%25D0%259D%250A%2520%2520%2520%2520kpp%253A%250A%2520%2520%2520%2520%2520%2520%2520%2520label%253A%2520%25D0%259A%25D0%259F%25D0%259F%250A%2520%2520%2520%2520ogrn%253A%250A%2520%2520%2520%2520%2520%2520%2520%2520label%253A%2520%25D0%259E%25D0%2593%25D0%25A0%25D0%259D&quot;&gt;&lt;/iframe&gt;
  &lt;/figure&gt;
  &lt;h3&gt;Поиск банка&lt;/h3&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;iframe src=&quot;https://carbon.now.sh/embed?bg=rgba%28171%2C+184%2C+195%2C+1%29&amp;t=monokai&amp;wt=none&amp;l=yaml&amp;ds=true&amp;dsyoff=20px&amp;dsblur=68px&amp;wc=true&amp;wa=false&amp;pv=56px&amp;ph=56px&amp;ln=false&amp;fl=1&amp;fm=Hack&amp;fs=14px&amp;lh=133%25&amp;si=false&amp;es=2x&amp;wm=false&amp;code=fields%253A%250A%2520%2520%2520%2520bank%253A%250A%2520%2520%2520%2520%2520%2520%2520%2520label%253A%2520%25D0%2591%25D0%25B0%25D0%25BD%25D0%25BA%250A%2520%2520%2520%2520%2520%2520%2520%2520type%253A%2520dadataSuggestions%250A%2520%2520%2520%2520%2520%2520%2520%2520suggestion%253A%2520bank%250A%2520%2520%2520%2520%2520%2520%2520%2520map%253A%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520bank%253A%2520value%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520bic%253A%2520data.bic%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520cs%253A%2520data.correspondent_account%250A%2520%2520%2520%2520bic%253A%250A%2520%2520%2520%2520%2520%2520%2520%2520label%253A%2520%25D0%2591%25D0%2598%25D0%259A%250A%2520%2520%2520%2520cs%253A%250A%2520%2520%2520%2520%2520%2520%2520%2520label%253A%2520%25D0%259A%252F%25D0%25A1&quot;&gt;&lt;/iframe&gt;
  &lt;/figure&gt;
  &lt;h3&gt;Ввод адреса и его последующий разбор&lt;/h3&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;iframe src=&quot;https://carbon.now.sh/embed?bg=rgba%28171%2C+184%2C+195%2C+1%29&amp;t=monokai&amp;wt=none&amp;l=yaml&amp;ds=true&amp;dsyoff=20px&amp;dsblur=68px&amp;wc=true&amp;wa=false&amp;pv=56px&amp;ph=56px&amp;ln=false&amp;fl=1&amp;fm=Hack&amp;fs=14px&amp;lh=133%25&amp;si=false&amp;es=2x&amp;wm=false&amp;code=fields%253A%250A%2520%2520%2520%2520address%253A%250A%2520%2520%2520%2520%2520%2520%2520%2520label%253A%2520%25D0%2590%25D0%25B4%25D1%2580%25D0%25B5%25D1%2581%250A%2520%2520%2520%2520%2520%2520%2520%2520type%253A%2520dadataSuggestions%250A%2520%2520%2520%2520%2520%2520%2520%2520suggestion%253A%2520address%250A%2520%2520%2520%2520%2520%2520%2520%2520map%253A%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520address%253A%2520value%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520country%253A%2520data.country%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520city%253A%2520data.city%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520lat%253A%2520data.geo_lat%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520lon%253A%2520data.geo_lon%250A%250A%2520%2520%2520%2520country%253A%250A%2520%2520%2520%2520%2520%2520%2520%2520label%253A%2520%25D0%25A1%25D1%2582%25D1%2580%25D0%25B0%25D0%25BD%25D0%25B0%250A%2520%2520%2520%2520city%253A%250A%2520%2520%2520%2520%2520%2520%2520%2520label%253A%2520%25D0%2593%25D0%25BE%25D1%2580%25D0%25BE%25D0%25B4%250A%2520%2520%2520%2520lat%253A%250A%2520%2520%2520%2520%2520%2520%2520%2520label%253A%2520%25D0%259A%25D0%25BE%25D0%25BE%25D1%2580%25D0%25B4%25D0%25B8%25D0%25BD%25D0%25B0%25D1%2582%25D1%258B%2520%28%25D1%2588%25D0%25B8%25D1%2580%25D0%25BE%25D1%2582%25D0%25B0%29%250A%2520%2520%2520%2520lon%253A%250A%2520%2520%2520%2520%2520%2520%2520%2520label%253A%2520%25D0%259A%25D0%25BE%25D0%25BE%25D1%2580%25D0%25B4%25D0%25B8%25D0%25BD%25D0%25B0%25D1%2582%25D1%258B%2520%28%25D0%25B4%25D0%25BE%25D0%25BB%25D0%25B3%25D0%25BE%25D1%2582%25D0%25B0%29&quot;&gt;&lt;/iframe&gt;
  &lt;/figure&gt;
  &lt;h3&gt;Помощь при вводе email-адреса и его разбор&lt;/h3&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;iframe src=&quot;https://carbon.now.sh/embed?bg=rgba%28171%2C+184%2C+195%2C+1%29&amp;t=monokai&amp;wt=none&amp;l=yaml&amp;ds=true&amp;dsyoff=20px&amp;dsblur=68px&amp;wc=true&amp;wa=false&amp;pv=56px&amp;ph=56px&amp;ln=false&amp;fl=1&amp;fm=Hack&amp;fs=14px&amp;lh=133%25&amp;si=false&amp;es=2x&amp;wm=false&amp;code=fields%253A%250A%2520%2520%2520%2520email%253A%250A%2520%2520%2520%2520%2520%2520%2520%2520label%253A%2520Email%250A%2520%2520%2520%2520%2520%2520%2520%2520type%253A%2520dadataSuggestions%250A%2520%2520%2520%2520%2520%2520%2520%2520suggestion%253A%2520email%250A%2520%2520%2520%2520%2520%2520%2520%2520map%253A%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520email%253A%2520value%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520local%253A%2520data.local%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520domain%253A%2520data.domain%250A%2520%2520%2520%2520local%253A%250A%2520%2520%2520%2520%2520%2520%2520%2520label%253A%2520%25D0%259B%25D0%25BE%25D0%25BA%25D0%25B0%25D0%25BB%25D1%258C%25D0%25BD%25D0%25BE%25D0%25B5%2520%28%25D0%25B4%25D0%25BE%2520%25D1%2581%25D0%25BE%25D0%25B1%25D0%25B0%25D1%2587%25D0%25BA%25D0%25B8%29%250A%2520%2520%2520%2520domain%253A%250A%2520%2520%2520%2520%2520%2520%2520%2520label%253A%2520%25D0%2594%25D0%25BE%25D0%25BC%25D0%25B5%25D0%25BD&quot;&gt;&lt;/iframe&gt;
  &lt;/figure&gt;
  &lt;h3&gt;Помощь при вводе ФИО и разбор&lt;/h3&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;iframe src=&quot;https://carbon.now.sh/embed?bg=rgba%28171%2C+184%2C+195%2C+1%29&amp;t=monokai&amp;wt=none&amp;l=yaml&amp;ds=true&amp;dsyoff=20px&amp;dsblur=68px&amp;wc=true&amp;wa=false&amp;pv=56px&amp;ph=56px&amp;ln=false&amp;fl=1&amp;fm=Hack&amp;fs=14px&amp;lh=133%25&amp;si=false&amp;es=2x&amp;wm=false&amp;code=fields%253A%250A%2520%2520%2520%2520fio%253A%250A%2520%2520%2520%2520%2520%2520%2520%2520label%253A%2520%25D0%25A4%25D0%2598%25D0%259E%250A%2520%2520%2520%2520%2520%2520%2520%2520type%253A%2520dadataSuggestions%250A%2520%2520%2520%2520%2520%2520%2520%2520suggestion%253A%2520fio%250A%2520%2520%2520%2520%2520%2520%2520%2520map%253A%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520fio%253A%2520value%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520surname%253A%2520data.surname%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520name%253A%2520data.name%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520patronymic%253A%2520data.patronymic%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520gender%253A%2520data.gender%250A%2520%2520%2520%2520surname%253A%250A%2520%2520%2520%2520%2520%2520%2520%2520label%253A%2520%25D0%25A4%25D0%25B0%25D0%25BC%25D0%25B8%25D0%25BB%25D0%25B8%25D1%258F%250A%2520%2520%2520%2520name%253A%250A%2520%2520%2520%2520%2520%2520%2520%2520label%253A%2520%25D0%2598%25D0%25BC%25D1%258F%250A%2520%2520%2520%2520patronymic%253A%250A%2520%2520%2520%2520%2520%2520%2520%2520label%253A%2520%25D0%259E%25D1%2582%25D1%2587%25D0%25B5%25D1%2582%25D1%2581%25D1%2582%25D0%25B2%25D0%25BE%250A%2520%2520%2520%2520gender%253A%250A%2520%2520%2520%2520%2520%2520%2520%2520label%253A%2520%25D0%259F%25D0%25BE%25D0%25BB&quot;&gt;&lt;/iframe&gt;
  &lt;/figure&gt;
  &lt;tt-tags&gt;
    &lt;tt-tag name=&quot;octobercms&quot;&gt;#octobercms&lt;/tt-tag&gt;
    &lt;tt-tag name=&quot;dadata&quot;&gt;#dadata&lt;/tt-tag&gt;
    &lt;tt-tag name=&quot;widgets&quot;&gt;#widgets&lt;/tt-tag&gt;
  &lt;/tt-tags&gt;

</content></entry><entry><id>gromit:eBj_dft11WY</id><link rel="alternate" type="text/html" href="https://blog.grom-it.ru/eBj_dft11WY?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=gromit"></link><title>Разработка простейшего виджета формы с использованием Vue.js для OctoberCMS v.2</title><published>2021-05-11T18:20:12.716Z</published><updated>2021-05-12T06:34:25.362Z</updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://teletype.in/files/59/db/59db1f28-0a86-4fe9-a275-9b889b7b2150.jpeg"></media:thumbnail><tt:hashtag>octobercms</tt:hashtag><tt:hashtag>vuejs</tt:hashtag><tt:hashtag>formwidgets</tt:hashtag><summary type="html">&lt;img src=&quot;https://teletype.in/files/c3/f3/c3f37965-ee1f-471b-8e50-ba4a71ecdc97.jpeg&quot;&gt;С появлением поддержки Vue.js в новом October, открылись новые возможности по созданию виджетов и прочих интересных вещей в админке нашей любимой CMS.</summary><content type="html">
  &lt;figure class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://teletype.in/files/c3/f3/c3f37965-ee1f-471b-8e50-ba4a71ecdc97.jpeg&quot; width=&quot;1200&quot; /&gt;
  &lt;/figure&gt;
  &lt;p&gt;С появлением поддержки Vue.js в новом October, открылись новые возможности по созданию виджетов и прочих интересных вещей в админке нашей любимой CMS.&lt;/p&gt;
  &lt;p&gt;Так как документации по поводу использования Vue.js в настоящий момент еще нет и автор не претендует на звание Кунг-Vue мастера, то публикуем этот гайд исходя из опыта, полученного в процессе изучения исходников новой системы.&lt;/p&gt;
  &lt;h3&gt;Задача&lt;/h3&gt;
  &lt;p&gt;Задача простая, бесполезная, но сгодится для примера - это создание formWidget&amp;#x27;а для получения адреса, с использованием Яндекс.Карт&lt;/p&gt;
  &lt;h3&gt;Подготовка&lt;/h3&gt;
  &lt;p&gt;Перед тем как начать - создадим тестовый плагин, назовем его Address.&lt;br /&gt;Данный материал предполагает, что читатель знаком с базовыми командами по созданию плагинов, моделей и пр. в OctoberCMS.&lt;/p&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;iframe src=&quot;https://carbon.now.sh/embed?bg=rgba%28171%2C+184%2C+195%2C+1%29&amp;t=monokai&amp;wt=none&amp;l=text%2Fx-php&amp;ds=true&amp;dsyoff=20px&amp;dsblur=68px&amp;wc=true&amp;wa=true&amp;pv=56px&amp;ph=56px&amp;ln=false&amp;fl=1&amp;fm=Hack&amp;fs=14px&amp;lh=133%25&amp;si=false&amp;es=2x&amp;wm=false&amp;code=%252F%252F%2520%25D0%25A1%25D0%25BE%25D0%25B7%25D0%25B4%25D0%25B0%25D0%25B4%25D0%25B8%25D0%25BC%2520%25D0%25BF%25D0%25BB%25D0%25B0%25D0%25B3%25D0%25B8%25D0%25BD%2520%25D0%25B4%25D0%25BB%25D1%258F%2520%25D1%258D%25D0%25BA%25D1%2581%25D0%25BF%25D0%25B5%25D1%2580%25D0%25B8%25D0%25BC%25D0%25B5%25D0%25BD%25D1%2582%25D0%25BE%25D0%25B2%252C%2520%25D0%25BD%25D0%25B0%25D0%25B7%25D0%25BE%25D0%25B2%25D0%25B5%25D0%25BC%2520%25D0%25B5%25D0%25B3%25D0%25BE%2520Sandbox%250A%250Aphp%2520artisan%2520create%253Aplugin%2520sandbox.address%250A%2520%2520%250A%252F%252F%2520%25D0%25A1%25D0%25BE%25D0%25B7%25D0%25B4%25D0%25B0%25D0%25B4%25D0%25B8%25D0%25BC%2520%25D0%25BC%25D0%25BE%25D0%25B4%25D0%25B5%25D0%25BB%25D1%258C%2520%25D0%25B8%2520%25D0%25BA%25D0%25BE%25D0%25BD%25D1%2582%25D1%2580%25D0%25BE%25D0%25BB%25D0%25BB%25D0%25B5%25D1%2580%2520%25D0%25B4%25D0%25BB%25D1%258F%2520%25D0%25BF%25D0%25BB%25D0%25B0%25D0%25B3%25D0%25B8%25D0%25BD%25D0%25B0%250Aphp%2520artisan%2520create%253Amodel%2520sandbox.address%2520address%250Aphp%2520artisan%2520create%253Acontroller%2520sandbox.address%2520addresses%250A&quot;&gt;&lt;/iframe&gt;
  &lt;/figure&gt;
  &lt;p&gt;Далее ускоренный прогон - миграция, модель, контроллер.&lt;/p&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;iframe src=&quot;https://carbon.now.sh/embed?bg=rgba%28171%2C+184%2C+195%2C+1%29&amp;t=monokai&amp;wt=none&amp;l=text%2Fx-php&amp;ds=true&amp;dsyoff=20px&amp;dsblur=68px&amp;wc=true&amp;wa=false&amp;pv=56px&amp;ph=56px&amp;ln=false&amp;fl=1&amp;fm=Hack&amp;fs=14px&amp;lh=133%25&amp;si=false&amp;es=2x&amp;wm=false&amp;code=%252F%252F%2520%25D0%259C%25D0%25B8%25D0%25B3%25D1%2580%25D0%25B0%25D1%2586%25D0%25B8%25D1%258F%2520create_addresses_table.php%250A%250A%253C%253Fphp%2520namespace%2520Sandbox%255CAddress%255CUpdates%253B%250A%250Ause%2520Schema%253B%250Ause%2520October%255CRain%255CDatabase%255CSchema%255CBlueprint%253B%250Ause%2520October%255CRain%255CDatabase%255CUpdates%255CMigration%253B%250A%250Aclass%2520CreateAddressesTable%2520extends%2520Migration%250A%257B%250A%2520%2520%2520%2520public%2520function%2520up%28%29%250A%2520%2520%2520%2520%257B%250A%2520%2520%2520%2520%2520%2520%2520%2520Schema%253A%253Acreate%28%27sandbox_address_addresses%27%252C%2520function%2520%28Blueprint%2520%2524table%29%2520%257B%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2524table-%253Eengine%2520%253D%2520%27InnoDB%27%253B%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2524table-%253Eincrements%28%27id%27%29%253B%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2524table-%253Estring%28%27address%27%29%253B%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2524table-%253Etimestamps%28%29%253B%250A%2520%2520%2520%2520%2520%2520%2520%2520%257D%29%253B%250A%2520%2520%2520%2520%257D%250A%250A%2520%2520%2520%2520public%2520function%2520down%28%29%250A%2520%2520%2520%2520%257B%250A%2520%2520%2520%2520%2520%2520%2520%2520Schema%253A%253AdropIfExists%28%27sandbox_address_addresses%27%29%253B%250A%2520%2520%2520%2520%257D%250A%257D%250A%250A%252F%252F%2520%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%250A%252F%252F%2520%25D0%259C%25D0%25BE%25D0%25B4%25D0%25B5%25D0%25BB%25D1%258C%2520Address%250A%250A%253C%253Fphp%2520namespace%2520Sandbox%255CAddress%255CModels%253B%250A%250Ause%2520Model%253B%250A%250A%252F**%250A%2520*%2520Address%2520Model%250A%2520*%252F%250Aclass%2520Address%2520extends%2520Model%250A%257B%250A%2520%2520%2520%2520%252F**%250A%2520%2520%2520%2520%2520*%2520%2540var%2520string%2520table%2520associated%2520with%2520the%2520model%250A%2520%2520%2520%2520%2520*%252F%250A%2520%2520%2520%2520public%2520%2524table%2520%253D%2520%27sandbox_address_addresses%27%253B%250A%257D%250A%250A%252F%252F%2520%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%250A%252F%252F%2520%25D0%259A%25D0%25BE%25D0%25BD%25D1%2582%25D1%2580%25D0%25BE%25D0%25BB%25D0%25BB%25D0%25B5%25D1%2580%2520Addresses%250A%250A%253C%253Fphp%2520namespace%2520Sandbox%255CAddress%255CControllers%253B%250A%250Ause%2520BackendMenu%253B%250Ause%2520Backend%255CBehaviors%255CFormController%253B%250Ause%2520Backend%255CBehaviors%255CListController%253B%250Ause%2520Backend%255CClasses%255CController%253B%250A%250A%252F**%250A%2520*%2520Addresses%2520Back-end%2520Controller%250A%2520*%252F%250Aclass%2520Addresses%2520extends%2520Controller%250A%257B%250A%2520%2520%2520%2520public%2520%2524implement%2520%253D%2520%255B%250A%2520%2520%2520%2520%2520%2520%2520%2520FormController%253A%253Aclass%252C%250A%2520%2520%2520%2520%2520%2520%2520%2520ListController%253A%253Aclass%250A%2520%2520%2520%2520%255D%253B%250A%250A%2520%2520%2520%2520public%2520%2524formConfig%2520%253D%2520%27config_form.yaml%27%253B%250A%2520%2520%2520%2520public%2520%2524listConfig%2520%253D%2520%27config_list.yaml%27%253B%250A%250A%2520%2520%2520%2520public%2520function%2520__construct%28%29%250A%2520%2520%2520%2520%257B%250A%2520%2520%2520%2520%2520%2520%2520%2520parent%253A%253A__construct%28%29%253B%250A%250A%2520%2520%2520%2520%2520%2520%2520%2520BackendMenu%253A%253AsetContext%28%27Sandbox.Address%27%252C%2520%27address%27%252C%2520%27addresses%27%29%253B%250A%2520%2520%2520%2520%257D%250A%257D&quot;&gt;&lt;/iframe&gt;
  &lt;/figure&gt;
  &lt;p&gt;Не забываем обновить файл &lt;code&gt;updates/version.yaml&lt;/code&gt; &lt;/p&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;iframe src=&quot;https://carbon.now.sh/embed?bg=rgba%28171%2C+184%2C+195%2C+1%29&amp;t=monokai&amp;wt=none&amp;l=yaml&amp;ds=true&amp;dsyoff=20px&amp;dsblur=68px&amp;wc=true&amp;wa=false&amp;pv=56px&amp;ph=56px&amp;ln=false&amp;fl=1&amp;fm=Hack&amp;fs=14px&amp;lh=133%25&amp;si=false&amp;es=2x&amp;wm=false&amp;code=1.0.1%253A%2520%250A%2520%2520%2520%2520-%2520First%2520version%2520of%2520address%250A%2520%2520%2520%2520-%2520create_addresses_table.php&quot;&gt;&lt;/iframe&gt;
  &lt;/figure&gt;
  &lt;p&gt;и выполнить:&lt;/p&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;iframe src=&quot;https://carbon.now.sh/embed?bg=rgba%28171%2C+184%2C+195%2C+1%29&amp;t=monokai&amp;wt=none&amp;l=application%2Fx-sh&amp;ds=true&amp;dsyoff=20px&amp;dsblur=68px&amp;wc=true&amp;wa=false&amp;pv=56px&amp;ph=56px&amp;ln=false&amp;fl=1&amp;fm=Hack&amp;fs=14px&amp;lh=133%25&amp;si=false&amp;es=2x&amp;wm=false&amp;code=php%2520artisan%2520plugin%253Arefresh%2520sandbox.address&quot;&gt;&lt;/iframe&gt;
  &lt;/figure&gt;
  &lt;p&gt;Не стану описывать, что и как - мы только что создали простой скелет, для того, чтобы было куда &amp;quot;прицепить&amp;quot; наш formWidget.&lt;/p&gt;
  &lt;h2&gt;Создание виджета&lt;/h2&gt;
  &lt;p&gt;Пробежимся по созданию виджета - следуя документации. Назовем наш виджет &lt;code&gt;MapPicker&lt;/code&gt;&lt;/p&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;iframe src=&quot;https://carbon.now.sh/embed?bg=rgba%28171%2C+184%2C+195%2C+1%29&amp;t=monokai&amp;wt=none&amp;l=application%2Fx-sh&amp;ds=true&amp;dsyoff=20px&amp;dsblur=68px&amp;wc=true&amp;wa=false&amp;pv=56px&amp;ph=56px&amp;ln=false&amp;fl=1&amp;fm=Hack&amp;fs=14px&amp;lh=133%25&amp;si=false&amp;es=2x&amp;wm=false&amp;code=php%2520artisan%2520create%253Aformwidget%2520sandbox.address%2520MapPicker&quot;&gt;&lt;/iframe&gt;
  &lt;/figure&gt;
  &lt;p&gt;В итоге у нас будет создан шаблон нашего виджета, с ним и будем работать.&lt;/p&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://teletype.in/files/f3/6b/f36b77e8-2f25-4f4d-9ea6-c17752eed7fc.png&quot; width=&quot;372&quot; /&gt;
  &lt;/figure&gt;
  &lt;p&gt;Сразу зарегистрируем виджет (согласно документации) в файле Plugin.php нашего плагина SandBox:&lt;/p&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;iframe src=&quot;https://carbon.now.sh/embed?bg=rgba%28171%2C+184%2C+195%2C+1%29&amp;t=monokai&amp;wt=none&amp;l=text%2Fx-php&amp;ds=true&amp;dsyoff=20px&amp;dsblur=68px&amp;wc=true&amp;wa=false&amp;pv=56px&amp;ph=56px&amp;ln=false&amp;fl=1&amp;fm=Hack&amp;fs=14px&amp;lh=133%25&amp;si=false&amp;es=2x&amp;wm=false&amp;code=%250Apublic%2520function%2520registerFormWidgets%28%29%250A%257B%250A%2520%2520%2520%2520return%2520%255B%250A%2520%2520%2520%2520%2520%2520%2520%2520Sandbox%255CAddress%255CFormWidgets%255CMapPicker%253A%253Aclass%2520%253D%253E%2520%27mapPicker%27%252C%250A%2520%2520%2520%2520%255D%253B%250A%257D%250A&quot;&gt;&lt;/iframe&gt;
  &lt;/figure&gt;
  &lt;p&gt;И добавим поле address с типом mapPicker в yaml-файл &lt;code&gt;sandbox/address/models/address/fields.yaml&lt;/code&gt;&lt;/p&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;iframe src=&quot;https://carbon.now.sh/embed?bg=rgba%28171%2C+184%2C+195%2C+1%29&amp;t=monokai&amp;wt=none&amp;l=yaml&amp;ds=true&amp;dsyoff=20px&amp;dsblur=68px&amp;wc=true&amp;wa=false&amp;pv=56px&amp;ph=56px&amp;ln=false&amp;fl=1&amp;fm=Hack&amp;fs=14px&amp;lh=133%25&amp;si=false&amp;es=2x&amp;wm=false&amp;code=%2523%2520%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%250A%2523%2520%2520Form%2520Field%2520Definitions%250A%2523%2520%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%253D%250A%250Afields%253A%250A%2520%2520%2520%2520id%253A%250A%2520%2520%2520%2520%2520%2520%2520%2520label%253A%2520ID%250A%2520%2520%2520%2520%2520%2520%2520%2520disabled%253A%2520true%250A%2520%2520%2520%2520address%253A%250A%2520%2520%2520%2520%2520%2520%2520%2520label%253A%2520MapPicker%250A%2520%2520%2520%2520%2520%2520%2520%2520type%253A%2520mapPicker%250A&quot;&gt;&lt;/iframe&gt;
  &lt;/figure&gt;
  &lt;p&gt;Теперь в браузере перейдем на страницу /backend/sandbox/address/addresses/create и увидим стандартный сгенерированный шаблон виджета. С ним и будем работать.&lt;/p&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://teletype.in/files/bc/6b/bc6ba12a-1210-43a4-99f8-3b78263a5c83.png&quot; width=&quot;1776&quot; /&gt;
  &lt;/figure&gt;
  &lt;p&gt;Итак, что мы хотим здесь видеть:&lt;/p&gt;
  &lt;ol&gt;
    &lt;li&gt;Поле ввода адреса&lt;/li&gt;
    &lt;li&gt;Кнопку, которая откроет в модальном окне карту&lt;/li&gt;
    &lt;li&gt;Собственно карту, при клике по которой, мы получим адрес и вставим его в поле ввода&lt;/li&gt;
  &lt;/ol&gt;
  &lt;h3&gt;Поле и кнопка&lt;/h3&gt;
  &lt;p&gt;Поправим стандартный шаблон партиалки, добавив в него кнопку и немного css.&lt;/p&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;iframe src=&quot;https://carbon.now.sh/embed?bg=rgba%28171%2C+184%2C+195%2C+1%29&amp;t=monokai&amp;wt=none&amp;l=text%2Fx-php&amp;ds=true&amp;dsyoff=20px&amp;dsblur=68px&amp;wc=true&amp;wa=false&amp;pv=56px&amp;ph=56px&amp;ln=false&amp;fl=1&amp;fm=Hack&amp;fs=14px&amp;lh=133%25&amp;si=false&amp;es=2x&amp;wm=false&amp;code=%252F%252F%2520sandbox%252Faddress%252Fformwidgets%252Fmappicker%252Fpartials%252F_mappicker.htm%250A%250A%253C%253Fphp%2520if%2520%28%2524this-%253EpreviewMode%29%253A%2520%253F%253E%250A%250A%2520%2520%2520%2520%253Cdiv%2520class%253D%2522form-control%2522%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%253C%253F%253D%2520%2524value%2520%253F%253E%250A%2520%2520%2520%2520%253C%252Fdiv%253E%250A%250A%253C%253Fphp%2520else%253A%2520%253F%253E%250A%250A%2520%2520%2520%2520%253Cdiv%2520id%253D%2522widget-%253C%253F%253D%2520%2524this-%253EgetId%28%27input%27%29%2520%253F%253E%2522%2520class%253D%2522mappicker-widget%2522%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%253Cinput%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520type%253D%2522text%2522%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520id%253D%2522%253C%253F%253D%2520%2524this-%253EgetId%28%27input%27%29%2520%253F%253E%2522%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520name%253D%2522%253C%253F%253D%2520%2524name%2520%253F%253E%2522%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520value%253D%2522%253C%253F%253D%2520%2524value%2520%253F%253E%2522%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520class%253D%2522form-control%2522%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520autocomplete%253D%2522off%2522%252F%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%253Cbutton%2520type%253D%2522button%2522%2520class%253D%2522btn%2520btn-primary%2522%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%25D0%259A%25D0%25B0%25D1%2580%25D1%2582%25D0%25B0%250A%2520%2520%2520%2520%2520%2520%2520%2520%253C%252Fbutton%253E%250A%2520%2520%2520%2520%253C%252Fdiv%253E%250A%250A%253C%253Fphp%2520endif%2520%253F%253E%250A&quot;&gt;&lt;/iframe&gt;
  &lt;/figure&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;iframe src=&quot;https://carbon.now.sh/embed?bg=rgba%28171%2C+184%2C+195%2C+1%29&amp;t=monokai&amp;wt=none&amp;l=css&amp;ds=true&amp;dsyoff=20px&amp;dsblur=68px&amp;wc=true&amp;wa=false&amp;pv=56px&amp;ph=56px&amp;ln=false&amp;fl=1&amp;fm=Hack&amp;fs=14px&amp;lh=133%25&amp;si=false&amp;es=2x&amp;wm=false&amp;code=%252F*%250A%2520*%2520sandbox%252Faddress%252Fformwidgets%252Fmappicker%252Fassets%252Fcss%252Fmappicker.css%250A%2520*%252F%250A%250A.mappicker-widget%257B%250A%2520%2520%2520%2520display%253A%2520flex%253B%250A%2520%2520%2520%2520gap%253A%252015px%253B%250A%257D%250A&quot;&gt;&lt;/iframe&gt;
  &lt;/figure&gt;
  &lt;p&gt;Получили примерно то, что надо =)&lt;/p&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://teletype.in/files/37/bf/37bf6314-6fbd-4bdd-9a4a-bfd25d2143a0.png&quot; width=&quot;1778&quot; /&gt;
  &lt;/figure&gt;
  &lt;p&gt;Далее используем стандартный компонент &amp;lt;backend-component-modal&amp;gt;, немного покопавшись в исходниках модуля editor и подглядев, как его вызывать.&lt;/p&gt;
  &lt;p&gt;Немного модифицируем нашу партиалку:&lt;/p&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;iframe src=&quot;https://carbon.now.sh/embed?bg=rgba%28171%2C+184%2C+195%2C+1%29&amp;t=monokai&amp;wt=none&amp;l=text%2Fx-php&amp;ds=true&amp;dsyoff=20px&amp;dsblur=68px&amp;wc=true&amp;wa=false&amp;pv=56px&amp;ph=56px&amp;ln=false&amp;fl=1&amp;fm=Hack&amp;fs=14px&amp;lh=133%25&amp;si=false&amp;es=2x&amp;wm=false&amp;code=%252F%252F%2520sandbox%252Faddress%252Fformwidgets%252Fmappicker%252Fpartials%252F_mappicker.htm%250A%250A%253C%253Fphp%2520if%2520%28%2524this-%253EpreviewMode%29%253A%2520%253F%253E%250A%250A%2520%2520%2520%2520%253Cdiv%2520class%253D%2522form-control%2522%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%253C%253F%253D%2520%2524value%2520%253F%253E%250A%2520%2520%2520%2520%253C%252Fdiv%253E%250A%250A%253C%253Fphp%2520else%253A%2520%253F%253E%250A%250A%2520%2520%2520%2520%253Cdiv%2520id%253D%2522widget-%253C%253F%253D%2520%2524this-%253EgetId%28%27input%27%29%2520%253F%253E%2522%2520class%253D%2522mappicker-widget%2522%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%253Cinput%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520type%253D%2522text%2522%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520id%253D%2522%253C%253F%253D%2520%2524this-%253EgetId%28%27input%27%29%2520%253F%253E%2522%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520name%253D%2522%253C%253F%253D%2520%2524name%2520%253F%253E%2522%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520value%253D%2522%253C%253F%253D%2520%2524value%2520%253F%253E%2522%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520class%253D%2522form-control%2522%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520autocomplete%253D%2522off%2522%252F%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%253Cbutton%2520type%253D%2522button%2522%2520class%253D%2522btn%2520btn-primary%2522%2520%2540click%253D%2522%2524refs.modal.show%28%29%2522%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%25D0%259A%25D0%25B0%25D1%2580%25D1%2582%25D0%25B0%250A%2520%2520%2520%2520%2520%2520%2520%2520%253C%252Fbutton%253E%250A%250A%2520%2520%2520%2520%2520%2520%2520%2520%253Cbackend-component-modal%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520ref%253D%2522modal%2522%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%253Aaria-labeled-by%253D%2522modalTitleId%2522%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%253Aunique-key%253D%2522uniqueKey%2522%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520size%253D%2522large%2522%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%253Adraggable%253D%2522false%2522%250A%2520%2520%2520%2520%2520%2520%2520%2520%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%253Ctemplate%2520v-slot%253Acontent%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%253Cdiv%2520class%253D%2522modal-header%2522%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%253Ch4%2520class%253D%2522modal-title%2522%253E%25D0%2597%25D0%25B0%25D0%25B3%25D0%25BE%25D0%25BB%25D0%25BE%25D0%25B2%25D0%25BE%25D0%25BA%253C%252Fh4%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%253C%252Fdiv%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%253Cdiv%2520class%253D%2522modal-body%2522%253E%25D0%25A2%25D0%25B5%25D0%25BA%25D1%2581%25D1%2582%253C%252Fdiv%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%253C%252Ftemplate%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%253C%252Fbackend-component-modal%253E%250A%2520%2520%2520%2520%253C%252Fdiv%253E%250A%250A%2520%2520%2520%2520%253Cscript%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520document.addEventListener%28%27DOMContentLoaded%27%252C%2520function%2520%28%29%2520%257B%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520new%2520Vue%28%257B%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520el%253A%2520%27%2523widget-%253C%253F%253D%2520%2524this-%253EgetId%28%27input%27%29%2520%253F%253E%27%252C%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520data%253A%2520function%2520%28%29%2520%257B%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520return%2520%257B%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520uniqueKey%253A%2520%2524.oc.domIdManager.generate%28%27modal-mappicker%27%29%252C%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520modalTitleId%253A%2520%2524.oc.domIdManager.generate%28%27modal-mappicker-title%27%29%252C%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%257D%253B%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%257D%252C%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%257D%29%253B%250A%2520%2520%2520%2520%2520%2520%2520%2520%257D%29%253B%250A%2520%2520%2520%2520%253C%252Fscript%253E%250A%250A%253C%253Fphp%2520endif%2520%253F%253E%250A%250A&quot;&gt;&lt;/iframe&gt;
  &lt;/figure&gt;
  &lt;p&gt;Проверяем:&lt;/p&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://teletype.in/files/ae/41/ae41d9f3-ca94-4673-9342-52bfba9532f4.png&quot; width=&quot;1756&quot; /&gt;
  &lt;/figure&gt;
  &lt;p&gt;Ура, получилось! Дело за малым, наполнить модалку картой и функционалом.&lt;/p&gt;
  &lt;h3&gt;Яндекс.Карты&lt;/h3&gt;
  &lt;p&gt;Достаточно просто и красиво всё описано тут - &lt;a href=&quot;https://vue-yandex-maps.github.io/&quot; target=&quot;_blank&quot;&gt;https://vue-yandex-maps.github.io/&lt;/a&gt;&lt;/p&gt;
  &lt;p&gt;Немного модифицируем файл виджета, добавив в метод загрузки ассетов одну строку&lt;/p&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;iframe src=&quot;https://carbon.now.sh/embed?bg=rgba%28171%2C+184%2C+195%2C+1%29&amp;t=monokai&amp;wt=none&amp;l=text%2Fx-php&amp;ds=true&amp;dsyoff=20px&amp;dsblur=68px&amp;wc=true&amp;wa=false&amp;pv=56px&amp;ph=56px&amp;ln=false&amp;fl=1&amp;fm=Hack&amp;fs=14px&amp;lh=133%25&amp;si=false&amp;es=2x&amp;wm=false&amp;code=%252F%252F%2520sandbox%252Faddress%252Fformwidgets%252FMapPicker.php%250A%250A%250Apublic%2520function%2520loadAssets%28%29%250A%257B%250A%2520%2520%2520%2520%2524this-%253EaddCss%28%27css%252Fmappicker.css%27%252C%2520%27sandbox.address%27%29%253B%250A%2520%2520%2520%2520%2524this-%253EaddJs%28%27js%252Fmappicker.js%27%252C%2520%27sandbox.address%27%29%253B%250A%2520%2520%2520%2520%2524this-%253EaddJs%28%27https%253A%252F%252Funpkg.com%252Fvue-yandex-maps%27%252C%2520%27sandbox.address%27%29%253B%250A%257D%250A%250A%250A&quot;&gt;&lt;/iframe&gt;
  &lt;/figure&gt;
  &lt;p&gt;Ну вот и всё - согласно документации, мы подключили плагин карт напрямую, и теперь дело техники, подпилить нашу партиалку для работы с ним.&lt;/p&gt;
  &lt;p&gt;Долго описывать не будем - покажем результат модифицированной партиалки&lt;/p&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://teletype.in/files/47/8d/478dd092-cece-4090-96c7-4cb16902db5c.png&quot; width=&quot;1818&quot; /&gt;
  &lt;/figure&gt;
  &lt;p&gt;И немного докинем стилей в css&lt;/p&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;iframe src=&quot;https://carbon.now.sh/embed?bg=rgba%28171%2C+184%2C+195%2C+1%29&amp;t=monokai&amp;wt=none&amp;l=text%2Fx-php&amp;ds=true&amp;dsyoff=20px&amp;dsblur=68px&amp;wc=true&amp;wa=false&amp;pv=56px&amp;ph=56px&amp;ln=false&amp;fl=1&amp;fm=Hack&amp;fs=14px&amp;lh=133%25&amp;si=false&amp;es=2x&amp;wm=false&amp;code=%252F%252F%2520sandbox%252Faddress%252Fformwidgets%252Fmappicker%252Fassets%252Fcss%252Fmappicker.css%250A%250A%252F*%250A%2520*%2520This%2520is%2520a%2520sample%2520StyleSheet%2520file%2520used%2520by%2520MapPicker%250A%2520*%250A%2520*%2520You%2520can%2520delete%2520this%2520file%2520if%2520you%2520want%250A%2520*%252F%250A.mappicker-widget%2520%257B%250A%2520%2520%2520%2520display%253A%2520flex%253B%250A%2520%2520%2520%2520gap%253A%252015px%253B%250A%257D%250A%250A%2523yandex-map%2520%257B%250A%2520%2520%2520%2520height%253A%2520400px%253B%250A%2520%2520%2520%2520margin-bottom%253A%252020px%253B%250A%257D%250A%250A.ymap-container%2520%257B%250A%2520%2520%2520%2520height%253A%2520100%2525%253B%250A%257D%250A%250A%250A&quot;&gt;&lt;/iframe&gt;
  &lt;/figure&gt;
  &lt;h3&gt;Результат&lt;/h3&gt;
  &lt;p&gt;Собственно, чтобы не придумывать велосипед - небольшое видео-демонстрация&lt;/p&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;iframe src=&quot;https://www.youtube.com/embed/Q7og6lPstnc?autoplay=0&amp;loop=0&amp;mute=0&quot;&gt;&lt;/iframe&gt;
  &lt;/figure&gt;
  &lt;p&gt;Исходники виджета можно скачать тут &lt;a href=&quot;https://github.com/gromitsoft/sandbox-formwidget&quot; target=&quot;_blank&quot;&gt;https://github.com/gromitsoft/sandbox-formwidget&lt;/a&gt;&lt;/p&gt;
  &lt;p&gt;&lt;/p&gt;
  &lt;tt-tags&gt;
    &lt;tt-tag name=&quot;octobercms&quot;&gt;#octobercms&lt;/tt-tag&gt;
    &lt;tt-tag name=&quot;vuejs&quot;&gt;#vuejs&lt;/tt-tag&gt;
    &lt;tt-tag name=&quot;formwidgets&quot;&gt;#formwidgets&lt;/tt-tag&gt;
  &lt;/tt-tags&gt;

</content></entry><entry><id>gromit:ZimADT2FeOx</id><link rel="alternate" type="text/html" href="https://blog.grom-it.ru/ZimADT2FeOx?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=gromit"></link><title>Особенности разработки REST API на OctoberCMS</title><published>2021-05-09T14:18:32.235Z</published><updated>2021-05-09T14:18:32.235Z</updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://teletype.in/files/07/84/0784e2a3-9fda-460c-be65-9817e07d99b6.jpeg"></media:thumbnail><category term="october-cms" label="OctoberCMS"></category><tt:hashtag>octobercms</tt:hashtag><tt:hashtag>restapi</tt:hashtag><tt:hashtag>cors</tt:hashtag><summary type="html">&lt;img src=&quot;https://teletype.in/files/46/b5/46b5a675-f67a-43d4-b0b7-95b746f9be91.jpeg&quot;&gt;В данном уроке мы рассмотрим разработку REST API на основе OctoberCMS.</summary><content type="html">
  &lt;figure class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://teletype.in/files/46/b5/46b5a675-f67a-43d4-b0b7-95b746f9be91.jpeg&quot; width=&quot;1200&quot; /&gt;
  &lt;/figure&gt;
  &lt;p&gt;В данном уроке мы рассмотрим разработку REST API на основе OctoberCMS.&lt;/p&gt;
  &lt;p&gt;Для чего это может понадобиться? Например, для создания роутов для последующего обращения к ним через AJAX. &lt;/p&gt;
  &lt;p&gt;Тут читатель может возразить, что в October для этого есть встроенный &lt;br /&gt;AJAX-фреймворк, работающий с компонентами и методами, находящимися прямо в файле страницы и будет прав. Но в некоторых случаях встроенный &lt;br /&gt;AJAX-фреймворк может быть не удобен или совсем не подходить. Особенно, при внедрении сторонних библиотек с динамической подгрузкой данных, таких как Select2.&lt;/p&gt;
  &lt;p&gt;Также, как показала практика, OctoberCMS отлично подходит как основа для headless решений, предоставляющих REST API для SPA или мобильных приложений, с удобной админкой в комплекте.&lt;/p&gt;
  &lt;h3&gt;Приступая к работе&lt;/h3&gt;
  &lt;p&gt;Как известно, OctoberCMS основан на Laravel. Из этого следует, что разработка REST API на OctoberCMS будет очень похожа на разработку REST API на Laravel.&lt;/p&gt;
  &lt;p&gt;Данный урок подразумевает, что Вы уже умеете создавать плагины для OctoberCMS. Также нам понадобится развернутый проект и немного свободного времени.&lt;/p&gt;
  &lt;h3&gt;Начало&lt;/h3&gt;
  &lt;p&gt;Для начала необходимо создать плагин. Для этого, как обычно, пойдем в консоль и попросим &lt;code&gt;artisan&lt;/code&gt; создать нам пустой плагин.&lt;/p&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;iframe src=&quot;https://carbon.now.sh/embed?bg=rgba%28171%2C+184%2C+195%2C+1%29&amp;t=monokai&amp;wt=none&amp;l=application%2Fx-sh&amp;ds=true&amp;dsyoff=20px&amp;dsblur=68px&amp;wc=true&amp;wa=true&amp;pv=56px&amp;ph=56px&amp;ln=false&amp;fl=1&amp;fm=Hack&amp;fs=14px&amp;lh=133%25&amp;si=false&amp;es=2x&amp;wm=false&amp;code=%2524%2520php%2520artisan%2520create%253Aplugin%2520Sandbox.RestApi&quot;&gt;&lt;/iframe&gt;
  &lt;/figure&gt;
  &lt;p&gt;Или создадим всё вручную (или даже через Builder), кому как больше нравится.&lt;/p&gt;
  &lt;p&gt;Далее, для объявления роутов нашего REST API создадим файл &lt;code&gt;/plugins/sandbox/restapi/routes.php&lt;/code&gt; и объявим в нем наш первый роут.&lt;/p&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;iframe src=&quot;https://carbon.now.sh/embed?bg=rgba%28171%2C+184%2C+195%2C+1%29&amp;t=monokai&amp;wt=none&amp;l=text%2Fx-php&amp;ds=true&amp;dsyoff=20px&amp;dsblur=68px&amp;wc=true&amp;wa=false&amp;pv=56px&amp;ph=56px&amp;ln=false&amp;fl=1&amp;fm=Hack&amp;fs=14px&amp;lh=133%25&amp;si=false&amp;es=2x&amp;wm=false&amp;code=%252F%252F%2520%252Fplugins%252Fsandbox%252Frestapi%252Froutes.php%250A%250A%253C%253Fphp%250A%250Ause%2520Illuminate%255CSupport%255CFacades%255CRoute%253B%250A%250ARoute%253A%253Aprefix%28%27api%27%29-%253Egroup%28function%2520%28%29%2520%257B%250A%2520%2520%2520%2520Route%253A%253Aget%28%27hello%27%252C%2520function%2520%28%29%2520%257B%250A%2520%2520%2520%2520%2520%2520%2520%2520return%2520response%28%27hello%2520rest%2520api%27%29%253B%250A%2520%2520%2520%2520%257D%29%253B%250A%257D%29%253B&quot;&gt;&lt;/iframe&gt;
  &lt;/figure&gt;
  &lt;p&gt;Теперь, если обратиться к этому роуту, то мы увидим ответ - &lt;strong&gt;hello rest api&lt;/strong&gt;. Для этого мы обычно используем &lt;a href=&quot;https://www.postman.com/&quot; target=&quot;_blank&quot;&gt;Postman&lt;/a&gt;.&lt;/p&gt;
  &lt;figure class=&quot;m_retina&quot;&gt;
    &lt;img src=&quot;https://teletype.in/files/ac/a8/aca80026-ed35-4389-8264-135c25cc0ac3.png&quot; width=&quot;1262&quot; /&gt;
  &lt;/figure&gt;
  &lt;p&gt;Далее - все как и в случае с Laravel. Только папку для контроллеров нам придется создать самостоятельно. Создадим наш контроллер, например, в файле &lt;code&gt;/plugins/sandbox/restapi/http/controllers/HelloController.php&lt;/code&gt;, и добавим роут для него:&lt;/p&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;iframe src=&quot;https://carbon.now.sh/embed?bg=rgba%28171%2C+184%2C+195%2C+1%29&amp;t=monokai&amp;wt=none&amp;l=text%2Fx-php&amp;ds=true&amp;dsyoff=20px&amp;dsblur=68px&amp;wc=true&amp;wa=false&amp;pv=56px&amp;ph=56px&amp;ln=false&amp;fl=1&amp;fm=Hack&amp;fs=14px&amp;lh=133%25&amp;si=false&amp;es=2x&amp;wm=false&amp;code=%252F%252F%2520%252Fplugins%252Fsandbox%252Frestapi%252Fhttp%252Fcontrollers%252FHelloController.php%250A%250A%253C%253Fphp%250A%250Anamespace%2520Sandbox%255CRestapi%255CHttp%255CControllers%253B%250A%250Ause%2520Illuminate%255CHttp%255CJsonResponse%253B%250Ause%2520Illuminate%255CRouting%255CController%253B%250A%250Aclass%2520HelloController%2520extends%2520Controller%250A%257B%250A%2520%2520%2520%2520public%2520function%2520greet%28string%2520%2524name%29%253A%2520JsonResponse%250A%2520%2520%2520%2520%257B%250A%2520%2520%2520%2520%2520%2520%2520%2520return%2520response%28%29-%253Ejson%28%255B%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%27greet%27%2520%253D%253E%2520%2522Hello%2520%2524name%2522%252C%250A%2520%2520%2520%2520%2520%2520%2520%2520%255D%29%253B%250A%2520%2520%2520%2520%257D%250A%257D&quot;&gt;&lt;/iframe&gt;
  &lt;/figure&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;iframe src=&quot;https://carbon.now.sh/embed?bg=rgba%28171%2C+184%2C+195%2C+1%29&amp;t=monokai&amp;wt=none&amp;l=text%2Fx-php&amp;ds=true&amp;dsyoff=20px&amp;dsblur=68px&amp;wc=true&amp;wa=false&amp;pv=56px&amp;ph=56px&amp;ln=false&amp;fl=1&amp;fm=Hack&amp;fs=14px&amp;lh=133%25&amp;si=false&amp;es=2x&amp;wm=false&amp;code=%252F%252F%2520%252Fplugins%252Fsandbox%252Frestapi%252Froutes.php%250A%250A%253C%253Fphp%250A%250Ause%2520Illuminate%255CSupport%255CFacades%255CResponse%253B%250Ause%2520Illuminate%255CSupport%255CFacades%255CRoute%253B%250Ause%2520Sandbox%255CRestApi%255CHttp%255CControllers%255CHelloController%253B%250A%250ARoute%253A%253Aprefix%28%27api%27%29-%253Egroup%28function%2520%28%29%2520%257B%250A%2520%2520%2520%2520Route%253A%253Aget%28%27hello%252F%257Bname%257D%27%252C%2520%255BHelloController%253A%253Aclass%252C%2520%27greet%27%255D%29%253B%250A%257D%29%253B&quot;&gt;&lt;/iframe&gt;
  &lt;/figure&gt;
  &lt;p&gt;Теперь обратимся к роуту &lt;code&gt;/api/hello/John%20Doe&lt;/code&gt; и увидим, что наш API отвечает соответствующим образом.&lt;/p&gt;
  &lt;figure class=&quot;m_retina&quot;&gt;
    &lt;img src=&quot;https://teletype.in/files/7d/e4/7de430a7-7372-4716-9dc0-6cc5bae62c1a.png&quot; width=&quot;1262&quot; /&gt;
  &lt;/figure&gt;
  &lt;p&gt;Главное здесь - наследовать контроллеры от &lt;code&gt;Illuminate\Routing\Controller&lt;/code&gt;, то есть от базового контроллера Laravel. А не от &lt;code&gt;Backend\Classes\Controller&lt;/code&gt;, так как последний предназначен для создания страниц в админ-панели OctoberCMS и плохо подходит для нашей задачи.&lt;/p&gt;
  &lt;h3&gt;Особенности&lt;/h3&gt;
  &lt;p&gt;OctoberCMS - это, в первую очередь, система предназначенная для разработки сайтов с классическим роутингом и генерацией HTML-страниц на сервере, а не REST API, поэтому некоторые вещи для разработки REST API подготовлены не очень хорошо.&lt;/p&gt;
  &lt;p&gt;Основные вопросы - обработка исключений и CORS.&lt;/p&gt;
  &lt;h3&gt;Обработка исключений&lt;/h3&gt;
  &lt;p&gt;В Laravel, если мы запросим роут страницы через браузер и в процессе обработки запроса будет выброшено исключение - мы увидим красивую страницу с кучей полезной информации. В случае же с XHR запросом - получим json с текстом ошибки, кодом и стеком вызовов. И происходит это автоматически, то есть стандартный обработчик ошибок в Laravel сам понимает, какой ответ нам нужен. В случае с OctoberCMS это не так.&lt;/p&gt;
  &lt;p&gt;Чтобы в этом убедиться, создадим роут, который, просто выбросит ошибку валидации, а затем обратимся к этому роуту.&lt;/p&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;iframe src=&quot;https://carbon.now.sh/embed?bg=rgba%28171%2C+184%2C+195%2C+1%29&amp;t=monokai&amp;wt=none&amp;l=text%2Fx-php&amp;ds=true&amp;dsyoff=20px&amp;dsblur=68px&amp;wc=true&amp;wa=false&amp;pv=56px&amp;ph=56px&amp;ln=false&amp;fl=1&amp;fm=Hack&amp;fs=14px&amp;lh=133%25&amp;si=false&amp;es=2x&amp;wm=false&amp;code=%252F%252F%2520%252Fplugins%252Fsandbox%252Frestapi%252Froutes.php%250A%250A%253C%253Fphp%250A%250Ause%2520October%255CRain%255CException%255CValidationException%253B%250A%250ARoute%253A%253Aget%28%27%252Fexception%27%252C%2520function%2520%28%29%2520%257B%250A%2520%2520%2520%2520throw%2520new%2520ValidationException%28%255B%250A%2520%2520%2520%2520%2520%2520%2520%2520%27something%27%2520%253D%253E%2520%27wrong%27%252C%250A%2520%2520%2520%2520%2520%2520%2520%2520%27mode%27%2520%2520%2520%2520%2520%2520%253D%253E%2520%27error%27%252C%250A%2520%2520%2520%2520%255D%29%253B%250A%257D%29%253B&quot;&gt;&lt;/iframe&gt;
  &lt;/figure&gt;
  &lt;p&gt;Откроем Postman и запросим наш роут, не забывая при этом добавить заголовок &lt;code&gt;X-Requested-With&lt;/code&gt; со значением &lt;code&gt;XMLHttpRequest&lt;/code&gt;, чтобы приложение понимало, что у нас тут AJAX-запрос и отправлять отрендеренную страницу не нужно.&lt;/p&gt;
  &lt;figure class=&quot;m_retina&quot;&gt;
    &lt;img src=&quot;https://teletype.in/files/b7/ff/b7ff374e-7f09-415b-9304-8e8fe604616c.png&quot; width=&quot;1345&quot; /&gt;
  &lt;/figure&gt;
  &lt;p&gt;Не густо! Что ж, значит нам придется сделать обработку исключений самим.&lt;/p&gt;
  &lt;p&gt;Согласно документации, для этого надо в методе &lt;code&gt;boot&lt;/code&gt; класса &lt;code&gt;Plugin&lt;/code&gt; нашего плагина добавить конструкцию вида:&lt;/p&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;iframe src=&quot;https://carbon.now.sh/embed?bg=rgba%28171%2C+184%2C+195%2C+1%29&amp;t=monokai&amp;wt=none&amp;l=text%2Fx-php&amp;ds=true&amp;dsyoff=20px&amp;dsblur=68px&amp;wc=true&amp;wa=false&amp;pv=56px&amp;ph=56px&amp;ln=false&amp;fl=1&amp;fm=Hack&amp;fs=14px&amp;lh=133%25&amp;si=false&amp;es=2x&amp;wm=false&amp;code=%252F%252F%2520%252Fplugins%252Fsandbox%252Frestapi%252FPlugin.php%250A%250A%253C%253Fphp%250A%250Anamespace%2520Sandbox%255CRestApi%253B%250A%250Ause%2520Config%253B%250Ause%2520Fruitcake%255CCors%255CHandleCors%253B%250Ause%2520Illuminate%255CContracts%255CHttp%255CKernel%253B%250A%250Aclass%2520Plugin%2520%257B%250A%250A%2520%2520%2520%2520%252F%252F%2520...%250A%250A%2520%2520%2520%2520public%2520function%2520boot%28%29%253A%2520void%250A%2520%2520%2520%2520%257B%250A%2520%2520%2520%2520%2520%2520%2520%2520App%253A%253Aerror%28function%2520%28ValidationException%2520%2524exception%29%2520%257B%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520return%2520response%28%29-%253Ejson%28%255B%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%27message%27%2520%253D%253E%2520%27validation%2520exception%27%252C%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%27errors%27%2520%2520%253D%253E%2520%2524exception-%253EgetErrors%28%29%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%255D%252C%2520422%29%253B%250A%2520%2520%2520%2520%2520%2520%2520%2520%257D%29%253B%250A%2520%2520%2520%2520%257D%250A%250A%2520%2520%2520%2520%252F%252F%2520...%250A%250A%257D&quot;&gt;&lt;/iframe&gt;
  &lt;/figure&gt;
  &lt;p&gt;Теперь попробуем обратиться к роуту еще раз.&lt;/p&gt;
  &lt;figure class=&quot;m_retina&quot;&gt;
    &lt;img src=&quot;https://teletype.in/files/7c/54/7c54a01a-8804-4b04-b30c-a85a70679d0f.png&quot; width=&quot;1345&quot; /&gt;
  &lt;/figure&gt;
  &lt;p&gt;Уже лучше. Но теперь появилась другая проблема: так как мы переопределили обработку для ошибок валидации, то у нас теперь не будет работать стандартная валидация в админке и на фронте.&lt;/p&gt;
  &lt;p&gt;Для проверки этого утверждения, создадим пустой контроллер для админки, добавим в него метод &lt;code&gt;index&lt;/code&gt; и бросим ошибку валидации.&lt;/p&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;iframe src=&quot;https://carbon.now.sh/embed?bg=rgba%28171%2C+184%2C+195%2C+1%29&amp;t=monokai&amp;wt=none&amp;l=text%2Fx-php&amp;ds=true&amp;dsyoff=20px&amp;dsblur=68px&amp;wc=true&amp;wa=false&amp;pv=56px&amp;ph=56px&amp;ln=false&amp;fl=1&amp;fm=Hack&amp;fs=14px&amp;lh=133%25&amp;si=false&amp;es=2x&amp;wm=false&amp;code=%252F%252F%2520%252Fplugins%252Fsandbox%252Frestapi%252Fcontrollers%252FHello.php%250A%250A%253C%253Fphp%250A%250Anamespace%2520Sandbox%255CRestapi%255CControllers%253B%250A%250Ause%2520Backend%255CClasses%255CController%253B%250Ause%2520October%255CRain%255CException%255CValidationException%253B%250A%250Aclass%2520Hello%2520extends%2520Controller%250A%257B%250A%2520%2520%2520%2520public%2520function%2520index%28%29%250A%2520%2520%2520%2520%257B%250A%2520%2520%2520%2520%2520%2520%2520%2520throw%2520new%2520ValidationException%28%255B%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%27something%27%2520%253D%253E%2520%27wrong%27%252C%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%27mode%27%2520%2520%2520%2520%2520%2520%253D%253E%2520%27error%27%252C%250A%2520%2520%2520%2520%2520%2520%2520%2520%255D%29%253B%250A%2520%2520%2520%2520%257D%250A%257D&quot;&gt;&lt;/iframe&gt;
  &lt;/figure&gt;
  &lt;p&gt;Теперь откроем эту страницу в браузере.&lt;/p&gt;
  &lt;figure class=&quot;m_retina&quot;&gt;
    &lt;img src=&quot;https://teletype.in/files/c3/6a/c36ac442-3414-4cd6-9210-921d08d4d7e9.png&quot; width=&quot;1326&quot; /&gt;
  &lt;/figure&gt;
  &lt;p&gt;Да - это не то, что мы привыкли видеть в браузере, в случае ошибки.&lt;/p&gt;
  &lt;p&gt;Для решения этой проблемы мы перенесем регистрацию хэндлера ошибок валидации в новый &lt;code&gt;middleware&lt;/code&gt;.&lt;/p&gt;
  &lt;p&gt;Создадим класс &lt;code&gt;ExceptionsMiddleware&lt;/code&gt;, разместим его в &lt;code&gt;/plugins/sandbox/restapi/http/middleware/ExceptionsMiddleware.php&lt;/code&gt; и добавим следующий код:&lt;/p&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;iframe src=&quot;https://carbon.now.sh/embed?bg=rgba%28171%2C+184%2C+195%2C+1%29&amp;t=monokai&amp;wt=none&amp;l=text%2Fx-php&amp;ds=true&amp;dsyoff=20px&amp;dsblur=68px&amp;wc=true&amp;wa=false&amp;pv=56px&amp;ph=56px&amp;ln=false&amp;fl=1&amp;fm=Hack&amp;fs=14px&amp;lh=133%25&amp;si=false&amp;es=2x&amp;wm=false&amp;code=%252F%252F%2520%252Fplugins%252Fsandbox%252Frestapi%252Fhttp%252Fmiddleware%252FExceptionsMiddleware.php%250A%250A%253C%253Fphp%250A%250Anamespace%2520Sandbox%255CRestapi%255CHttp%255CMiddleware%253B%250A%250Ause%2520App%253B%250Ause%2520Closure%253B%250Ause%2520Illuminate%255CHttp%255CRequest%253B%250Ause%2520October%255CRain%255CException%255CValidationException%253B%250A%250Aclass%2520ExceptionsMiddleware%250A%257B%250A%2520%2520%2520%2520public%2520function%2520handle%28Request%2520%2524request%252C%2520Closure%2520%2524next%29%250A%2520%2520%2520%2520%257B%250A%2520%2520%2520%2520%2520%2520%2520%2520%2524this-%253EregisterExceptionHandlers%28%29%253B%250A%250A%2520%2520%2520%2520%2520%2520%2520%2520return%2520%2524next%28%2524request%29%253B%250A%2520%2520%2520%2520%257D%250A%250A%2520%2520%2520%2520private%2520function%2520registerExceptionHandlers%28%29%253A%2520void%250A%2520%2520%2520%2520%257B%250A%2520%2520%2520%2520%2520%2520%2520%2520App%253A%253Aerror%28function%2520%28ValidationException%2520%2524exception%29%2520%257B%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520return%2520response%28%29-%253Ejson%28%255B%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%27message%27%2520%253D%253E%2520%27validation%2520exception%27%252C%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%27errors%27%2520%2520%253D%253E%2520%2524exception-%253EgetErrors%28%29%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%255D%252C%2520422%29%253B%250A%2520%2520%2520%2520%2520%2520%2520%2520%257D%29%253B%250A%2520%2520%2520%2520%257D%250A%257D&quot;&gt;&lt;/iframe&gt;
  &lt;/figure&gt;
  &lt;p&gt;Добавим наш новый &lt;code&gt;middleware&lt;/code&gt; в файл &lt;code&gt;routes.php&lt;/code&gt;&lt;/p&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;iframe src=&quot;https://carbon.now.sh/embed?bg=rgba%28171%2C+184%2C+195%2C+1%29&amp;t=monokai&amp;wt=none&amp;l=text%2Fx-php&amp;ds=true&amp;dsyoff=20px&amp;dsblur=68px&amp;wc=true&amp;wa=false&amp;pv=56px&amp;ph=56px&amp;ln=false&amp;fl=1&amp;fm=Hack&amp;fs=14px&amp;lh=133%25&amp;si=false&amp;es=2x&amp;wm=false&amp;code=%252F%252F%2520%252Fplugins%252Fsandbox%252Frestapi%252Froutes.php%250A%250A%253C%253Fphp%250A%250Ause%2520Sandbox%255CRestapi%255CHttp%255CMiddleware%255CExceptionsMiddleware%253B%250A%250ARoute%253A%253Agroup%28%255B%250A%2520%2520%2520%2520%27prefix%27%2520%2520%2520%2520%2520%253D%253E%2520%27api%27%252C%250A%2520%2520%2520%2520%27middleware%27%2520%253D%253E%2520%255B%250A%2520%2520%2520%2520%2520%2520%2520%2520ExceptionsMiddleware%253A%253Aclass%250A%2520%2520%2520%2520%255D%250A%255D%252C%2520function%2520%28%29%2520%257B%250A%2520%2520%2520%2520%252F%252F%2520%25D0%25BD%25D0%25B0%25D1%2588%25D0%25B8%2520%25D1%2580%25D0%25BE%25D1%2583%25D1%2582%25D1%258B%250A%257D%29%253B&quot;&gt;&lt;/iframe&gt;
  &lt;/figure&gt;
  &lt;p&gt;Если же мы откроем страницу теперь, то увидим, привычную нам картину - роут с ошибкой будет отдавать все, что нам нужно.&lt;/p&gt;
  &lt;figure class=&quot;m_retina&quot;&gt;
    &lt;img src=&quot;https://teletype.in/files/fa/f2/faf2633a-2c38-4160-a48b-f3e2663f02bd.png&quot; width=&quot;1345&quot; /&gt;
  &lt;/figure&gt;
  &lt;h3&gt;CORS&lt;/h3&gt;
  &lt;p&gt;Следующий интересный вопрос - CORS.&lt;/p&gt;
  &lt;p&gt;Если Вы не знаете, что такое CORS, то CORS (Cross-Origin Resource Sharing) - это механизм, позволяющий с помощью дополнительных заголовков запросов и ответов получать доступ к ресурсам других доменов. Подробнее можно почитать &lt;a href=&quot;https://developer.mozilla.org/ru/docs/Web/HTTP/CORS&quot; target=&quot;_blank&quot;&gt;здесь&lt;/a&gt;.&lt;/p&gt;
  &lt;p&gt;В Laravel, начиная с 7-ой версии, есть встроенный middleware для работы с CORS. В OctoberCMS же его нет. А это значит, что этот вопрос нам придется решить самим.&lt;/p&gt;
  &lt;p&gt;В Laravel встроенный middleware работает на основе пакета &lt;strong&gt;fruitcake/laravel-cors&lt;/strong&gt;. Не будем изобретать велосипед и поступим так же.&lt;/p&gt;
  &lt;p&gt;Про особенности работы с composer в OctoberCMS рекомендую ознакомиться с документацией. В нашем случае, будем считать, что разрабатываемый плагин предназначен исключительно для текущего проекта, а значит все зависимости будем добавлять в корневой composer.json.&lt;/p&gt;
  &lt;p&gt;Идем в консоль и просим composer установить нам этот пакет.&lt;/p&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;iframe src=&quot;https://carbon.now.sh/embed?bg=rgba%28171%2C+184%2C+195%2C+1%29&amp;t=monokai&amp;wt=none&amp;l=application%2Fx-sh&amp;ds=true&amp;dsyoff=20px&amp;dsblur=68px&amp;wc=true&amp;wa=false&amp;pv=56px&amp;ph=56px&amp;ln=false&amp;fl=1&amp;fm=Hack&amp;fs=14px&amp;lh=133%25&amp;si=false&amp;es=2x&amp;wm=false&amp;code=composer%2520req%2520fruitcake%252Flaravel-cors&quot;&gt;&lt;/iframe&gt;
  &lt;/figure&gt;
  &lt;p&gt;Данный пакет требует конфига. Следуя рекомендациям из документации OctoberCMS создем конфиг не в общей папке проекта, а в папке плагина &lt;code&gt;/plugins/sandbox/restapi/config/cors.php&lt;/code&gt;&lt;/p&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;iframe src=&quot;https://carbon.now.sh/embed?bg=rgba%28171%2C+184%2C+195%2C+1%29&amp;t=monokai&amp;wt=none&amp;l=text%2Fx-php&amp;ds=true&amp;dsyoff=20px&amp;dsblur=68px&amp;wc=true&amp;wa=false&amp;pv=56px&amp;ph=56px&amp;ln=false&amp;fl=1&amp;fm=Hack&amp;fs=14px&amp;lh=133%25&amp;si=false&amp;es=2x&amp;wm=false&amp;code=%252F%252F%2520%252Fplugins%252Fsandbox%252Frestapi%252Fconfig%252Fcors.php%250A%250A%253C%253Fphp%250A%250Areturn%2520%255B%250A%250A%2520%2520%2520%2520%27paths%27%2520%253D%253E%2520%255B%27api%252F*%27%255D%252C%250A%250A%2520%2520%2520%2520%27allowed_methods%27%2520%253D%253E%2520%255B%27*%27%255D%252C%250A%250A%2520%2520%2520%2520%27allowed_origins%27%2520%253D%253E%2520%255B%27*%27%255D%252C%250A%250A%2520%2520%2520%2520%27allowed_origins_patterns%27%2520%253D%253E%2520%255B%255D%252C%250A%250A%2520%2520%2520%2520%27allowed_headers%27%2520%253D%253E%2520%255B%27*%27%255D%252C%250A%250A%2520%2520%2520%2520%27exposed_headers%27%2520%253D%253E%2520%255B%255D%252C%250A%250A%2520%2520%2520%2520%27max_age%27%2520%253D%253E%25200%252C%250A%250A%2520%2520%2520%2520%27supports_credentials%27%2520%253D%253E%2520true%252C%250A%250A%255D%253B&quot;&gt;&lt;/iframe&gt;
    &lt;figcaption&gt;&lt;em&gt;Для чего нужен каждый параметр можно посмотреть &lt;a href=&quot;https://github.com/fruitcake/laravel-cors#options&quot; target=&quot;_blank&quot;&gt;здесь&lt;/a&gt;.&lt;/em&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;p&gt;А затем регистрируем конфиг в методе &lt;code&gt;boot&lt;/code&gt; класса &lt;code&gt;Plugin&lt;/code&gt; нашего плагина, а также зарегистрируем &lt;code&gt;ServiceProvider&lt;/code&gt; пакета и добавим глобальный &lt;code&gt;middleware&lt;/code&gt;.&lt;/p&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;iframe src=&quot;https://carbon.now.sh/embed?bg=rgba%28171%2C+184%2C+195%2C+1%29&amp;t=monokai&amp;wt=none&amp;l=text%2Fx-php&amp;ds=true&amp;dsyoff=20px&amp;dsblur=68px&amp;wc=true&amp;wa=false&amp;pv=56px&amp;ph=56px&amp;ln=false&amp;fl=1&amp;fm=Hack&amp;fs=14px&amp;lh=133%25&amp;si=false&amp;es=2x&amp;wm=false&amp;code=%253C%253Fphp%250A%250Anamespace%2520Sandbox%255CRestApi%253B%250A%250Ause%2520Config%253B%250Ause%2520Fruitcake%255CCors%255CHandleCors%253B%250Ause%2520Illuminate%255CContracts%255CHttp%255CKernel%253B%250A%250Aclass%2520Plugin%2520%257B%250A%250A%2520%2520%2520%2520%252F%252F%2520...%250A%250A%2520%2520%2520%2520public%2520function%2520boot%28%29%253A%2520void%250A%2520%2520%2520%2520%257B%250A%2520%2520%2520%2520%2520%2520%2520%2520Config%253A%253Aset%28%27cors%27%252C%2520Config%253A%253Aget%28%27sandbox.restapi%253A%253Acors%27%29%29%253B%250A%250A%2520%2520%2520%2520%2520%2520%2520%2520%2524this-%253Eapp-%253Eregister%28CorsServiceProvider%253A%253Aclass%29%253B%250A%250A%2520%2520%2520%2520%2520%2520%2520%2520%2524this-%253Eapp%255BKernel%253A%253Aclass%255D-%253EpushMiddleware%28HandleCors%253A%253Aclass%29%253B%250A%2520%2520%2520%2520%257D%250A%250A%2520%2520%2520%2520%252F%252F%2520...%250A%250A%257D&quot;&gt;&lt;/iframe&gt;
  &lt;/figure&gt;
  &lt;h3&gt;Заключение&lt;/h3&gt;
  &lt;p&gt;Вещи описанные в статье, на самом деле, не обязательные, и разрабатывать REST API на OctoberCMS можно и без них, однако обработка исключений не плохо упрощает жизнь, а CORS - необходимая вещь, если вы разрабатываете API обращение к которому будет происходить с домена отличного от того, на котором это API находится.&lt;/p&gt;
  &lt;p&gt;Код из статьи можно найти в &lt;a href=&quot;https://github.com/gromitsoft/sandbox-restapi-plugin&quot; target=&quot;_blank&quot;&gt;репозитории&lt;/a&gt;&lt;/p&gt;
  &lt;tt-tags&gt;
    &lt;tt-tag name=&quot;octobercms&quot;&gt;#octobercms&lt;/tt-tag&gt;
    &lt;tt-tag name=&quot;restapi&quot;&gt;#restapi&lt;/tt-tag&gt;
    &lt;tt-tag name=&quot;cors&quot;&gt;#cors&lt;/tt-tag&gt;
  &lt;/tt-tags&gt;

</content></entry><entry><id>gromit:phbAYZqkAUt</id><link rel="alternate" type="text/html" href="https://blog.grom-it.ru/phbAYZqkAUt?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=gromit"></link><title>Изменение пользовательского меню в OctoberCMS</title><published>2021-05-06T14:29:03.745Z</published><updated>2021-05-06T14:29:42.604Z</updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://teletype.in/files/d4/34/d434d1a0-8370-42f7-820d-44d3416819fe.jpeg"></media:thumbnail><category term="october-cms" label="OctoberCMS"></category><tt:hashtag>octobercms</tt:hashtag><tt:hashtag>tips</tt:hashtag><tt:hashtag>tricks</tt:hashtag><summary type="html">&lt;img src=&quot;https://teletype.in/files/fb/4c/fb4c9a0d-61d7-4d6f-adec-83faaf5792ca.jpeg&quot;&gt;При работе с OctoberCMS иногда возникает желание добавить свой пункт в выпадающее меню, которое появляется в верхнем правом углу при клике на иконку пользователя:</summary><content type="html">
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://teletype.in/files/fb/4c/fb4c9a0d-61d7-4d6f-adec-83faaf5792ca.jpeg&quot; width=&quot;1200&quot; /&gt;
  &lt;/figure&gt;
  &lt;p&gt;При работе с OctoberCMS иногда возникает желание добавить свой пункт в выпадающее меню, которое появляется в верхнем правом углу при клике на иконку пользователя:&lt;/p&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://teletype.in/files/86/1d/861d4f88-29ad-40fd-8836-869de3d7ad24.png&quot; width=&quot;873&quot; /&gt;
  &lt;/figure&gt;
  &lt;p&gt;Решение очень простое, для этого необходимо добавить пункты, которые вы хотите видеть в этом меню в метод &lt;code&gt;registerSettings()&lt;/code&gt; вашего плагина.&lt;/p&gt;
  &lt;p&gt;Пример добавления своего пункта:&lt;/p&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;iframe src=&quot;https://carbon.now.sh/embed?bg=rgba%28171%2C+184%2C+195%2C+1%29&amp;t=monokai&amp;wt=none&amp;l=text%2Fx-php&amp;ds=true&amp;dsyoff=20px&amp;dsblur=68px&amp;wc=true&amp;wa=false&amp;pv=56px&amp;ph=56px&amp;ln=false&amp;fl=1&amp;fm=Hack&amp;fs=14px&amp;lh=133%25&amp;si=false&amp;es=2x&amp;wm=false&amp;code=%2520%2520%2520%2520public%2520function%2520registerSettings%28%29%250A%2520%2520%2520%2520%257B%250A%2520%2520%2520%2520%2520%2520%2520%2520return%2520%255B%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%27settings%27%2520%253D%253E%2520%255B%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%27label%27%2520%2520%2520%2520%2520%2520%2520%253D%253E%2520%27%25D0%2592%25D0%25B0%25D1%2588%25D0%25B0%2520%25D1%2581%25D1%2581%25D1%258B%25D0%25BB%25D0%25BA%25D0%25B0%27%252C%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%27description%27%2520%253D%253E%2520%27%25D0%2592%25D0%25B0%25D1%2588%2520%25D0%25B4%25D0%25B5%25D1%2581%25D0%25BA%25D1%2580%25D0%25B8%25D0%25BF%25D1%2588%25D0%25B5%25D0%25BD%27%252C%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%27icon%27%2520%2520%2520%2520%2520%2520%2520%2520%253D%253E%2520%27octo-icon-text-image%27%252C%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%27url%27%2520%2520%2520%2520%2520%2520%2520%2520%2520%253D%253E%2520%27https%253A%252F%252Fblog.grom-it.ru%27%252C%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%27context%27%2520%2520%2520%2520%2520%253D%253E%2520%27mysettings%27%252C%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2509%27order%27%2509%2509%2520%2520%253D%253E%2520500%252C%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%255D%250A%2520%2520%2520%2520%2520%2520%2520%2520%255D%253B%250A%2520%2520%2520%2520%257D%250A&quot;&gt;&lt;/iframe&gt;
  &lt;/figure&gt;
  &lt;p&gt;То есть, необходимо всего лишь указать контекст для вашего пункта, и, чтобы он отобразился в выпадающем меню, значение контекста должно быть равно &lt;code&gt;mysettings&lt;/code&gt;.&lt;/p&gt;
  &lt;p&gt;Результат будет таким:&lt;/p&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://teletype.in/files/02/40/0240d646-d2d2-4ae2-b15a-ea5680c9694b.png&quot; width=&quot;879&quot; /&gt;
  &lt;/figure&gt;
  &lt;tt-tags&gt;
    &lt;tt-tag name=&quot;octobercms&quot;&gt;#octobercms&lt;/tt-tag&gt;
    &lt;tt-tag name=&quot;tips&quot;&gt;#tips&lt;/tt-tag&gt;
    &lt;tt-tag name=&quot;tricks&quot;&gt;#tricks&lt;/tt-tag&gt;
  &lt;/tt-tags&gt;

</content></entry><entry><id>gromit:Xoyd0Fy3y</id><link rel="alternate" type="text/html" href="https://blog.grom-it.ru/Xoyd0Fy3y?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=gromit"></link><title>Иконки в OctoberCMS 2.0</title><published>2021-04-16T13:03:52.206Z</published><updated>2021-04-16T13:03:52.206Z</updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://teletype.in/files/bd/44/bd44d4ac-0380-49be-9aee-7dc8ac161e63.png"></media:thumbnail><category term="october-cms" label="OctoberCMS"></category><tt:hashtag>octobercms</tt:hashtag><tt:hashtag>icons</tt:hashtag><summary type="html">&lt;img src=&quot;https://teletype.in/files/06/91/069184d3-7c21-4919-be70-3540cb0a8196.png&quot;&gt;Свершилось, дождались =)</summary><content type="html">
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://teletype.in/files/06/91/069184d3-7c21-4919-be70-3540cb0a8196.png&quot; width=&quot;660&quot; /&gt;
  &lt;/figure&gt;
  &lt;p&gt;Свершилось, дождались =)&lt;/p&gt;
  &lt;p&gt;Помимо косметики в бэке разработчики добавили, но пока не задокументировали новый набор иконок.&lt;/p&gt;
  &lt;p&gt;Иконки вытащили и собрали в pdf, собирать в страницу лень =)&lt;/p&gt;
  &lt;p&gt;Скачать можно тут - &lt;a href=&quot;https://github.com/gromitsoft/sandbox/blob/master/new-icons.pdf&quot; target=&quot;_blank&quot;&gt;https://github.com/gromitsoft/sandbox/blob/master/new-icons.pdf&lt;/a&gt;&lt;/p&gt;
  &lt;tt-tags&gt;
    &lt;tt-tag name=&quot;octobercms&quot;&gt;#octobercms&lt;/tt-tag&gt;
    &lt;tt-tag name=&quot;icons&quot;&gt;#icons&lt;/tt-tag&gt;
  &lt;/tt-tags&gt;

</content></entry><entry><id>gromit:B6gJn5cMH</id><link rel="alternate" type="text/html" href="https://blog.grom-it.ru/B6gJn5cMH?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=gromit"></link><title>Строки в PHP и кавычки</title><published>2021-04-03T08:28:02.226Z</published><updated>2021-04-03T08:28:02.226Z</updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://teletype.in/files/8b/66/8b668073-e311-4a2b-9130-252e1b048559.png"></media:thumbnail><category term="php" label="php"></category><tt:hashtag>php</tt:hashtag><summary type="html">&lt;img src=&quot;https://teletype.in/files/45/5e/455efccf-769f-43a1-9f5f-09d334b4ca5c.png&quot;&gt;При изучении PHP многие обращают внимание на то, что строки можно обрамлять как одинарными, так и двойными кавычками. </summary><content type="html">
  &lt;p&gt;При изучении PHP многие обращают внимание на то, что строки можно обрамлять как одинарными, так и двойными кавычками. &lt;/p&gt;
  &lt;p&gt;Давайте разберемся - в чем разница.&lt;/p&gt;
  &lt;h3&gt;Двойные кавычки VS Одинарные кавычки&lt;/h3&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://teletype.in/files/45/5e/455efccf-769f-43a1-9f5f-09d334b4ca5c.png&quot; width=&quot;724&quot; /&gt;
  &lt;/figure&gt;
  &lt;p&gt;Двойные кавычки позволяют вставлять переменные и специальные символы, а одинарные нет - вот и вся концептуальная разница.&lt;/p&gt;
  &lt;tt-tags&gt;
    &lt;tt-tag name=&quot;php&quot;&gt;#php&lt;/tt-tag&gt;
  &lt;/tt-tags&gt;

</content></entry><entry><id>gromit:g-hbK5rkQ</id><link rel="alternate" type="text/html" href="https://blog.grom-it.ru/g-hbK5rkQ?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=gromit"></link><title>Именованные аргументы функций в PHP 8</title><published>2021-04-03T08:22:46.274Z</published><updated>2021-04-03T09:47:45.799Z</updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://teletype.in/files/07/df/07df6105-1058-412a-9b71-ae874c2d8ef2.png"></media:thumbnail><category term="php" label="php"></category><tt:hashtag>php</tt:hashtag><tt:hashtag>php8</tt:hashtag><tt:hashtag>spatie</tt:hashtag><summary type="html">&lt;img src=&quot;https://teletype.in/files/34/35/3435249b-1111-4ec4-ac89-a0a4ec3394f2.png&quot;&gt;В PHP 8 появилась возможность передавать аргументы в функции по именам.</summary><content type="html">
  &lt;p&gt;В PHP 8 появилась возможность передавать аргументы в функции по именам.&lt;/p&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://teletype.in/files/34/35/3435249b-1111-4ec4-ac89-a0a4ec3394f2.png&quot; width=&quot;1076&quot; /&gt;
  &lt;/figure&gt;
  &lt;p&gt;&lt;strong&gt;Какие преимущества?&lt;/strong&gt;&lt;/p&gt;
  &lt;p&gt;Это позволяет передавать аргументы в функцию по имени в произвольном порядке, что будет особенно полезно, если функция принимает несколько не обязательных аргументов.&lt;/p&gt;
  &lt;p&gt;Для тех, кто не в теме - ребята из &lt;a href=&quot;http://spatie.be&quot; target=&quot;_blank&quot;&gt;spatie.be&lt;/a&gt; сделали отличный видеокурс по новинкам в PHP 8.&lt;/p&gt;
  &lt;p&gt;Ссылка на видеокурс - &lt;a href=&quot;https://spatie.be/videos/front-line-php&quot; target=&quot;_blank&quot;&gt;https://spatie.be/videos/front-line-php&lt;/a&gt;&lt;/p&gt;
  &lt;tt-tags&gt;
    &lt;tt-tag name=&quot;php&quot;&gt;#php&lt;/tt-tag&gt;
    &lt;tt-tag name=&quot;php8&quot;&gt;#php8&lt;/tt-tag&gt;
    &lt;tt-tag name=&quot;spatie&quot;&gt;#spatie&lt;/tt-tag&gt;
  &lt;/tt-tags&gt;

</content></entry><entry><id>gromit:faqt6Mu6q</id><link rel="alternate" type="text/html" href="https://blog.grom-it.ru/faqt6Mu6q?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=gromit"></link><title>Разработка простейшего лендинга на OctoberCMS. Часть 2.</title><published>2021-04-02T15:42:56.047Z</published><updated>2021-04-02T15:42:56.047Z</updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://teletype.in/files/26/f4/26f4a37b-1b2e-4758-81a8-fcfdf13e5b05.jpeg"></media:thumbnail><category term="october-cms" label="OctoberCMS"></category><tt:hashtag>octobercms</tt:hashtag><tt:hashtag>landing</tt:hashtag><summary type="html">&lt;img src=&quot;https://teletype.in/files/90/d5/90d51ae9-c9df-47f6-80c9-d0d03019f283.jpeg&quot;&gt;На чем мы остановились в предыдущей части? Мы создали следующее:</summary><content type="html">
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://teletype.in/files/90/d5/90d51ae9-c9df-47f6-80c9-d0d03019f283.jpeg&quot; width=&quot;1200&quot; /&gt;
  &lt;/figure&gt;
  &lt;p&gt;На чем мы остановились в предыдущей части? Мы создали следующее:&lt;/p&gt;
  &lt;ul&gt;
    &lt;li&gt;плагин landing и миграцию&lt;/li&gt;
    &lt;li&gt;проработали модель Page&lt;/li&gt;
    &lt;li&gt;настроили поля формы и колонки для списка&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p&gt;В итоге на финальном этапе первого урока у нас была следующая картина:&lt;/p&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://teletype.in/files/43/14/4314c6b7-938c-4296-9fba-5685e3993f38.png&quot; width=&quot;1026&quot; /&gt;
  &lt;/figure&gt;
  &lt;p&gt;Мы сделали один вариант страницы лендинга и заполнили его тестовым содержимым.&lt;/p&gt;
  &lt;h2&gt;Компонент&lt;/h2&gt;
  &lt;blockquote&gt;Компоненты, в рамкам OctoberCms это настраиваемые элементы, которые могут быть прикреплены к любой странице или шаблону. Мы можем создавать любое количество компонентов для любых задач, которые могут быть использованы на фронте.&lt;/blockquote&gt;
  &lt;p&gt;Тут снова без выкрутасов - всё очень подробно расписано в документации OctoberCms - &lt;a href=&quot;https://octobercms.com/docs/plugin/components&quot; target=&quot;_blank&quot;&gt;https://octobercms.com/docs/plugin/components&lt;/a&gt;&lt;/p&gt;
  &lt;p&gt;Для нашей задачи нам предстоит создать всего один компонент. Назовем его &lt;strong&gt;Page.&lt;/strong&gt;&lt;/p&gt;
  &lt;p&gt;Для создания компонента воспользуемся следующей командой:&lt;/p&gt;
  &lt;pre&gt;php artisan create:component sandbox.landing page&lt;/pre&gt;
  &lt;p&gt;В результате выполнения команды в директории нашего плагина будет создан компонент Page с подобной структурой&lt;/p&gt;
  &lt;figure class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://teletype.in/files/7e/25/7e25e472-694f-4711-a29d-8284b1c60cce.png&quot; width=&quot;239&quot; /&gt;
  &lt;/figure&gt;
  &lt;p&gt;Поправим файл Page.php под наши нужды&lt;/p&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;iframe src=&quot;https://carbon.now.sh/embed?bg=rgba%28171%2C+184%2C+195%2C+1%29&amp;t=monokai&amp;wt=none&amp;l=text%2Fx-php&amp;ds=true&amp;dsyoff=20px&amp;dsblur=68px&amp;wc=true&amp;wa=false&amp;pv=56px&amp;ph=56px&amp;ln=false&amp;fl=1&amp;fm=Hack&amp;fs=14px&amp;lh=133%25&amp;si=false&amp;es=2x&amp;wm=false&amp;code=%253C%253Fphp%2520namespace%2520Sandbox%255CLanding%255CComponents%253B%250A%250Ause%2520Cms%255CClasses%255CComponentBase%253B%250A%250Aclass%2520Page%2520extends%2520ComponentBase%250A%257B%250A%2520%2520%2520%2520public%2520function%2520componentDetails%28%29%253A%2520array%250A%2520%2520%2520%2520%257B%250A%2520%2520%2520%2520%2520%2520%2520%2520return%2520%255B%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%27name%27%2520%253D%253E%2520%27Landing%2520page%2520Component%27%252C%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%27description%27%2520%253D%253E%2520%27Simple%2520landing%2520page%2520component%27%250A%2520%2520%2520%2520%2520%2520%2520%2520%255D%253B%250A%2520%2520%2520%2520%257D%250A%250A%2520%2520%2520%2520public%2520function%2520defineProperties%28%29%253A%2520array%250A%2520%2520%2520%2520%257B%250A%2520%2520%2520%2520%2520%2520%2520%2520return%2520%255B%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%27page%27%2520%253D%253E%2520%255B%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%27title%27%2520%253D%253E%2520%27Page%27%252C%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%27description%27%2520%253D%253E%2520%27Select%2520the%2520page%2520to%2520be%2520displayed%27%252C%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%27type%27%2520%253D%253E%2520%27dropdown%27%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%255D%250A%2520%2520%2520%2520%2520%2520%2520%2520%255D%253B%250A%2520%2520%2520%2520%257D%250A%250A%250A%2520%2520%2520%2520%252F**%250A%2520%2520%2520%2520%2520*%2520%25D0%259F%25D0%25BE%25D0%25BB%25D1%2583%25D1%2587%25D0%25B8%25D0%25BC%2520%25D1%2581%25D0%25BF%25D0%25B8%25D1%2581%25D0%25BE%25D0%25BA%2520%25D1%2581%25D1%2582%25D1%2580%25D0%25B0%25D0%25BD%25D0%25B8%25D1%2586%2520%25D0%25B4%25D0%25BB%25D1%258F%2520%25D0%25B2%25D1%258B%25D0%25B1%25D0%25BE%25D1%2580%25D0%25B0%250A%2520%2520%2520%2520%2520*%2520%25D0%25B2%2520%25D0%25B2%25D1%258B%25D0%25BF%25D0%25B0%25D0%25B4%25D0%25B0%25D1%258E%25D1%2589%25D0%25B5%25D0%25BC%2520%25D1%2581%25D0%25BF%25D0%25B8%25D1%2581%25D0%25BA%25D0%25B5%2520%25D0%25B2%2520%25D0%25BD%25D0%25B0%25D1%2581%25D1%2582%25D1%2580%25D0%25BE%25D0%25B9%25D0%25BA%25D0%25B0%25D1%2585%2520%25D0%25BA%25D0%25BE%25D0%25BC%25D0%25BF%25D0%25BE%25D0%25BD%25D0%25B5%25D0%25BD%25D1%2582%25D0%25B0%2520%25D0%25BD%25D0%25B0%2520%25D1%2581%25D1%2582%25D1%2580%25D0%25B0%25D0%25BD%25D0%25B8%25D1%2586%25D0%25B5%250A%2520%2520%2520%2520%2520*%2520%2540return%2520array%250A%2520%2520%2520%2520%2520*%252F%250A%2520%2520%2520%2520public%2520function%2520getPageOptions%28%29%253A%2520array%250A%2520%2520%2520%2520%257B%250A%2520%2520%2520%2520%2520%2520%2520%2520return%2520%255CSandbox%255CLanding%255CModels%255CPage%253A%253Alists%28%27title%27%252C%2520%27id%27%29%253B%250A%2520%2520%2520%2520%257D%250A%250A%2520%2520%2520%2520%252F**%250A%2520%2520%2520%2520%2520*%2520%25D0%259F%25D0%25BE%25D0%25BB%25D1%2583%25D1%2587%25D0%25B8%25D0%25BC%2520%25D1%2581%25D0%25BE%25D0%25B4%25D0%25B5%25D1%2580%25D0%25B6%25D0%25B8%25D0%25BC%25D0%25BE%25D0%25B5%2520%25D0%25B2%25D1%258B%25D0%25B1%25D1%2580%25D0%25B0%25D0%25BD%25D0%25BD%25D0%25BE%25D0%25B9%2520%25D1%2581%25D1%2582%25D1%2580%25D0%25B0%25D0%25BD%25D0%25B8%25D1%2586%25D1%258B%250A%2520%2520%2520%2520%2520*%2520%25D0%25B8%2520%25D0%25B4%25D0%25BE%25D0%25B1%25D0%25B0%25D0%25B2%25D0%25B8%25D0%25BC%2520%25D0%25B5%25D0%25B5%2520%25D0%25B2%2520%25D0%25BF%25D0%25B5%25D1%2580%25D0%25B5%25D0%25BC%25D0%25B5%25D0%25BD%25D0%25BD%25D1%2583%25D1%258E%2520landing%250A%2520%2520%2520%2520%2520*%2520%2540return%2520void%250A%2520%2520%2520%2520%2520*%252F%250A%2520%2520%2520%2520public%2520function%2520onRun%28%29%253A%2520void%250A%2520%2520%2520%2520%257B%250A%2520%2520%2520%2520%2520%2520%2520%2520%2524this-%253Epage%255B%27landing%27%255D%2520%253D%2520%255CSandbox%255CLanding%255CModels%255CPage%253A%253Afind%28%2524this-%253Eproperty%28%27page%27%29%29%253B%250A%2520%2520%2520%2520%257D%250A%257D&quot;&gt;&lt;/iframe&gt;
  &lt;/figure&gt;
  &lt;p&gt;И самое главное - не забыть зарегистрировать компонент в нашем плагине, для этого откроем Plugin.php и добавим следующее:&lt;/p&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;iframe src=&quot;https://carbon.now.sh/embed?bg=rgba%28171%2C+184%2C+195%2C+1%29&amp;t=monokai&amp;wt=none&amp;l=text%2Fx-php&amp;ds=true&amp;dsyoff=20px&amp;dsblur=68px&amp;wc=true&amp;wa=false&amp;pv=56px&amp;ph=56px&amp;ln=false&amp;fl=1&amp;fm=Hack&amp;fs=14px&amp;lh=133%25&amp;si=false&amp;es=2x&amp;wm=false&amp;code=%252F**%250A%2520*%2520Registers%2520any%2520front-end%2520components%2520implemented%2520in%2520this%2520plugin.%250A%2520*%250A%2520*%2520%2540return%2520array%250A%2520*%252F%250Apublic%2520function%2520registerComponents%28%29%250A%257B%250A%2520%2520%2520%2520return%2520%255B%250A%2520%2520%2520%2520%2520%2520%2520%2520%27Sandbox%255CLanding%255CComponents%255CPage%27%2520%253D%253E%2520%27Page%27%250A%2520%2520%2520%2520%255D%253B%250A%257D&quot;&gt;&lt;/iframe&gt;
  &lt;/figure&gt;
  &lt;p&gt;Итак, мы создали простейший компонент, который берет из настроек идентификатор страницы и отдает ее в переменную landing.&lt;/p&gt;
  &lt;p&gt;На самом деле, даже этот вариант можно улучшать и улучшать, но цель уроков - ознакомление с возможностями.&lt;/p&gt;
  &lt;h2&gt;&lt;strong&gt;Тема для лендинга.&lt;/strong&gt;&lt;/h2&gt;
  &lt;p&gt;Для нашей лендинговой темы, мы не будем изобретать велосипед и возьмем, уже полюбившуюся всем, стартовую тему demo - просто скопируем ее в папку landing.&lt;/p&gt;
  &lt;figure class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://teletype.in/files/10/38/1038d8c0-aed3-40c9-b9ec-da656e425bf3.png&quot; width=&quot;189&quot; /&gt;
  &lt;/figure&gt;
  &lt;p&gt;Поправим файл &lt;code&gt;themes/landing/theme.yaml&lt;/code&gt;&lt;/p&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;iframe src=&quot;https://carbon.now.sh/embed?bg=rgba%28171%2C+184%2C+195%2C+1%29&amp;t=monokai&amp;wt=none&amp;l=yaml&amp;ds=true&amp;dsyoff=20px&amp;dsblur=68px&amp;wc=true&amp;wa=false&amp;pv=56px&amp;ph=56px&amp;ln=false&amp;fl=1&amp;fm=Hack&amp;fs=14px&amp;lh=133%25&amp;si=false&amp;es=2x&amp;wm=false&amp;code=name%253A%2520Landing%2520theme%250Adescription%253A%2520%27Landing%2520demo%2520theme%27%250Aauthor%253A%2520OctoberCMS%250Ahomepage%253A%2520%27http%253A%252F%252Foctobercms.com%27%250Acode%253A%2520%27landing-theme%27&quot;&gt;&lt;/iframe&gt;
  &lt;/figure&gt;
  &lt;p&gt;Далее подправим файл шаблона &lt;code&gt;themes/landing/pages/home.htm&lt;/code&gt;, подготовив его для дальнейшей работы.&lt;/p&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;iframe src=&quot;https://carbon.now.sh/embed?bg=rgba%28171%2C+184%2C+195%2C+1%29&amp;t=monokai&amp;wt=none&amp;l=htmlmixed&amp;ds=true&amp;dsyoff=20px&amp;dsblur=68px&amp;wc=true&amp;wa=false&amp;pv=56px&amp;ph=56px&amp;ln=false&amp;fl=1&amp;fm=Hack&amp;fs=14px&amp;lh=133%25&amp;si=false&amp;es=2x&amp;wm=false&amp;code=title%2520%253D%2520%2522Demonstration%2522%250Aurl%2520%253D%2520%2522%252F%2522%250Alayout%2520%253D%2520%2522default%2522%250A%253D%253D%250A%250A%253Cdiv%2520class%253D%2522container%2522%253E%250A%2509Our%2520landing%2520content%250A%253C%252Fdiv%253E&quot;&gt;&lt;/iframe&gt;
  &lt;/figure&gt;
  &lt;p&gt;Готово. Теперь наш сайт выглядит примерно так:&lt;/p&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://teletype.in/files/ae/32/ae32d5c1-711c-49cc-9f5d-dabfede14d51.png&quot; width=&quot;1169&quot; /&gt;
  &lt;/figure&gt;
  &lt;p&gt;Не очень круто =)&lt;/p&gt;
  &lt;h2&gt;Подключение компонента и еще немного правок шаблона.&lt;/h2&gt;
  &lt;p&gt;В панели управления переходим в раздел CMS, открываем шаблон нашей темы и бросаем туда компонент Landing.&lt;/p&gt;
  &lt;p&gt;В настройках компонента выбираем страницу, содержимое которой хотим отображать.&lt;/p&gt;
  &lt;blockquote&gt;Страницу South Park: The Fractured but Whole мы создали и наполнили контентом в &lt;a href=&quot;https://blog.grom-it.ru/N9epRWxGX&quot; target=&quot;_blank&quot;&gt;первой части&lt;/a&gt; этого повествования.&lt;/blockquote&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://teletype.in/files/9f/cd/9fcd12c0-09d2-443c-b861-93333e164363.png&quot; width=&quot;1171&quot; /&gt;
  &lt;/figure&gt;
  &lt;p&gt;Компонент подключен к шаблону, соответственно свойства и методы его теперь доступны на всех страницах, которые используют этот шаблон.&lt;/p&gt;
  &lt;p&gt;Далее отредактируем файл &lt;code&gt;themes/landing/partials/site/header.htm&lt;/code&gt;&lt;/p&gt;
  &lt;p&gt;Удалим всё - добавим такое содержимое:&lt;/p&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;iframe src=&quot;https://carbon.now.sh/embed?bg=rgba%28171%2C+184%2C+195%2C+1%29&amp;t=monokai&amp;wt=none&amp;l=htmlmixed&amp;ds=true&amp;dsyoff=20px&amp;dsblur=68px&amp;wc=true&amp;wa=false&amp;pv=56px&amp;ph=56px&amp;ln=false&amp;fl=1&amp;fm=Hack&amp;fs=14px&amp;lh=133%25&amp;si=false&amp;es=2x&amp;wm=false&amp;code=%253D%253D%250Afunction%2520onStart%28%29%250A%257B%250A%2520%2520%2520%2520%2524this%255B%27backendUrl%27%255D%2520%253D%2520Backend%253A%253Aurl%28%27%252F%27%29%253B%250A%257D%250A%253D%253D%250A%253C%21--%2520Nav%2520--%253E%250A%253Cnav%2520id%253D%2522layout-nav%2522%2520class%253D%2522navbar%2520navbar-inverse%2520navbar-fixed-top%2520navbar-autohide%2522%2520role%253D%2522navigation%2522%253E%250A%2520%2520%2520%2520%253Cdiv%2520class%253D%2522container%2522%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%253Cdiv%2520class%253D%2522navbar-header%2522%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%253Ca%2520class%253D%2522navbar-brand%2522%2520href%253D%2522%257B%257B%2520%27home%27%257Cpage%2520%257D%257D%2522%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%257B%257B%2520landing.title%2520%257D%257D%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%253C%252Fa%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%253C%252Fdiv%253E%250A%2520%2520%2520%2520%253C%252Fdiv%253E%250A%253C%252Fnav%253E&quot;&gt;&lt;/iframe&gt;
  &lt;/figure&gt;
  &lt;p&gt;{{ landing.title }} - это название нашей страницы&lt;/p&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://teletype.in/files/8b/91/8b915462-d401-4af6-ae83-dea3d9b2e9a3.png&quot; width=&quot;808&quot; /&gt;
  &lt;/figure&gt;
  &lt;p&gt;После чего, наш сайт стал выглядеть так:&lt;/p&gt;
  &lt;p&gt; &lt;/p&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://teletype.in/files/3e/46/3e46b62d-3bca-4482-9de5-0d5075b0d784.png&quot; width=&quot;1195&quot; /&gt;
  &lt;/figure&gt;
  &lt;p&gt;Уже лучше!&lt;/p&gt;
  &lt;h2&gt;Группы контента&lt;/h2&gt;
  &lt;p&gt;Приступим к самому интересному - будем оживлять динамические блоки с содержимым, которые мы уже давным давно создали и даже заполнили контентом.&lt;/p&gt;
  &lt;p&gt;Группы мы определили при создании модели и формы - это:&lt;/p&gt;
  &lt;ul&gt;
    &lt;li&gt;text&lt;/li&gt;
    &lt;li&gt;image&lt;/li&gt;
    &lt;li&gt;features&lt;/li&gt;
    &lt;li&gt;slider&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p&gt;Чтобы убедиться - вернемся к файлу &lt;code&gt;plugins/sandbox/landing/models/page/groups.yaml&lt;/code&gt;&lt;/p&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;iframe src=&quot;https://carbon.now.sh/embed?bg=rgba%28171%2C+184%2C+195%2C+1%29&amp;t=monokai&amp;wt=none&amp;l=yaml&amp;ds=true&amp;dsyoff=20px&amp;dsblur=68px&amp;wc=true&amp;wa=false&amp;pv=56px&amp;ph=56px&amp;ln=false&amp;fl=1&amp;fm=Hack&amp;fs=14px&amp;lh=133%25&amp;si=false&amp;es=2x&amp;wm=false&amp;code=text%253A%250A%2520%2520%2520%2520name%253A%2520Text%2520block%250A%2520%2520%2520%2520description%253A%2520Text%2520block%2520with%2520richeditor%250A%2520%2520%2520%2520icon%253A%2520icon-file-text-o%250A%2520%2520%2520%2520fields%253A%250A%2520%2520%2520%2520%2520%2520%2520%2520text%253A%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520label%253A%2520Text%2520block%2520content%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520type%253A%2520richeditor%250A%250Aimage%253A%250A%2520%2520%2520%2520name%253A%2520Single%2520image%250A%2520%2520%2520%2520description%253A%2520Block%2520with%2520single%2520image%250A%2520%2520%2520%2520icon%253A%2520icon-image%250A%2520%2520%2520%2520fields%253A%250A%2520%2520%2520%2520%2520%2520%2520%2520image%253A%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520label%253A%2520Image%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520type%253A%2520mediafinder%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520mode%253A%2520image%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520imageHeight%253A%2520150%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520imageWidth%253A%2520150%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520thumbOptions%253A%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520mode%253A%2520crop%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520extension%253A%2520auto%250A%250Afeatures%253A%250A%2520%2520%2520%2520name%253A%2520Features%250A%2520%2520%2520%2520description%253A%2520Features%2520simple%2520block%250A%2520%2520%2520%2520icon%253A%2520icon-star%250A%2520%2520%2520%2520fields%253A%250A%2520%2520%2520%2520%2520%2520%2520%2520title%253A%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520label%253A%2520Feature%2520title%250A%2520%2520%2520%2520%2520%2520%2520%2520features_items%253A%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520type%253A%2520repeater%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520form%253A%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520fields%253A%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520feature_title%253A%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520label%253A%2520Feature%2520title%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520span%253A%2520left%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520feature_description%253A%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520label%253A%2520Feature%2520description%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520span%253A%2520right%250A%250Aslider%253A%250A%2520%2520%2520%2520name%253A%2520Slider%250A%2520%2520%2520%2520description%253A%2520Block%2520with%2520slider%2520images%250A%2520%2520%2520%2520icon%253A%2520icon-play-circle-o%250A%2520%2520%2520%2520fields%253A%250A%2520%2520%2520%2520%2520%2520%2520%2520images%253A%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520label%253A%2520Slides%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520type%253A%2520repeater%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520form%253A%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520fields%253A%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520image%253A%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520label%253A%2520Slide%2520Image%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520type%253A%2520mediafinder%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520mode%253A%2520image%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520imageHeight%253A%2520150%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520imageWidth%253A%2520150%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520thumbOptions%253A%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520mode%253A%2520crop%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520extension%253A%2520auto&quot;&gt;&lt;/iframe&gt;
  &lt;/figure&gt;
  &lt;p&gt;В нашей теме в разделе в &lt;code&gt;themes/landing/partials&lt;/code&gt; создадим папку &lt;code&gt;content&lt;/code&gt;, где сложим шаблоны для каждой группы контента.&lt;/p&gt;
  &lt;p&gt;В папке &lt;code&gt;themes/landing/partials/content&lt;/code&gt;  создадим следующие файлы:&lt;/p&gt;
  &lt;ul&gt;
    &lt;li&gt;text.htm&lt;/li&gt;
    &lt;li&gt;image.htm&lt;/li&gt;
    &lt;li&gt;features.htm&lt;/li&gt;
    &lt;li&gt;slider.htm&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p&gt;Должна получиться такая структура:&lt;/p&gt;
  &lt;figure class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://teletype.in/files/54/35/54350bba-4d47-4d91-b758-7ec4ca0d6580.png&quot; width=&quot;249&quot; /&gt;
  &lt;/figure&gt;
  &lt;p&gt;Далее вернемся в файлу &lt;code&gt;themes/landing/pages/home.htm&lt;/code&gt; и отредактируем его следующим образом.&lt;/p&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;iframe src=&quot;https://carbon.now.sh/embed?bg=rgba%28171%2C+184%2C+195%2C+1%29&amp;t=monokai&amp;wt=none&amp;l=htmlmixed&amp;ds=true&amp;dsyoff=20px&amp;dsblur=68px&amp;wc=true&amp;wa=false&amp;pv=56px&amp;ph=56px&amp;ln=false&amp;fl=1&amp;fm=Hack&amp;fs=14px&amp;lh=133%25&amp;si=false&amp;es=2x&amp;wm=false&amp;code=title%2520%253D%2520%2522Demonstration%2522%250Aurl%2520%253D%2520%2522%252F%2522%250Alayout%2520%253D%2520%2522default%2522%250A%253D%253D%250A%250A%253Cdiv%2520class%253D%2522container%2522%253E%250A%2520%2520%2520%2520%257B%2525%2520for%2520blockKey%252C%2520blockContent%2520in%2520landing.content%2520%2525%257D%250A%2520%2520%2520%2520%257B%2525%2520partial%2520%27content%252F%27%7E%2520blockContent._group%2520blockContent%2520%253D%2520blockContent%2520blockKey%2520%253D%2520blockKey%2520%2525%257D%250A%2520%2520%2520%2520%257B%2525%2520endfor%2520%2525%257D%250A%253C%252Fdiv%253E&quot;&gt;&lt;/iframe&gt;
  &lt;/figure&gt;
  &lt;p&gt;Что означает эта конструкция:&lt;/p&gt;
  &lt;p&gt;В цикле мы перебираем содержимое landing.content, это содержимое состоит из именованных групп и содержимого этих групп.&lt;/p&gt;
  &lt;p&gt;Иными словами зная, что это за группа (из свойства _group), мы можем динамически отправить ключ и содержимое группы в соответствующую партиалку.&lt;/p&gt;
  &lt;h2&gt;Партиалим!&lt;/h2&gt;
  &lt;h3&gt;text.htm&lt;/h3&gt;
  &lt;p&gt;Начнем с файла &lt;code&gt;themes/landing/partials/content/text.htm&lt;/code&gt;&lt;/p&gt;
  &lt;p&gt;Приведем его к следующему виду:&lt;/p&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;iframe src=&quot;https://carbon.now.sh/embed?bg=rgba%28171%2C+184%2C+195%2C+1%29&amp;t=monokai&amp;wt=none&amp;l=htmlmixed&amp;ds=true&amp;dsyoff=20px&amp;dsblur=68px&amp;wc=true&amp;wa=false&amp;pv=56px&amp;ph=56px&amp;ln=false&amp;fl=1&amp;fm=Hack&amp;fs=14px&amp;lh=133%25&amp;si=false&amp;es=2x&amp;wm=false&amp;code=%253Cdiv%2520id%253D%2522text-%257B%257B%2520blockKey%2520%257D%257D%2522%2520class%253D%2522content-block%2520text-block%2522%253E%250A%2520%2520%2520%2520%257B%257B%2520blockContent.text%257Craw%2520%257D%257D%250A%253C%252Fdiv%253E&quot;&gt;&lt;/iframe&gt;
  &lt;/figure&gt;
  &lt;h3&gt;image.htm&lt;/h3&gt;
  &lt;p&gt;Партиалку для отображения картинки &lt;code&gt;themes/landing/partials/content/image.htm&lt;/code&gt;  приведем к следующему виду:&lt;/p&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;iframe src=&quot;https://carbon.now.sh/embed?bg=rgba%28171%2C+184%2C+195%2C+1%29&amp;t=monokai&amp;wt=none&amp;l=htmlmixed&amp;ds=true&amp;dsyoff=20px&amp;dsblur=68px&amp;wc=true&amp;wa=false&amp;pv=56px&amp;ph=56px&amp;ln=false&amp;fl=1&amp;fm=Hack&amp;fs=14px&amp;lh=133%25&amp;si=false&amp;es=2x&amp;wm=false&amp;code=%253Cdiv%2520id%253D%2522image-%257B%257B%2520blockKey%2520%257D%257D%2522%2520class%253D%2522content-block%2520image-block%2522%253E%250A%2520%2520%2520%2520%253Cdiv%2520class%253D%2522image-block__image%2522%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%253Cimg%2520src%253D%2522%257B%257B%2520blockContent.image%257Cmedia%2520%257D%257D%2522%253E%250A%2520%2520%2520%2520%253C%252Fdiv%253E%250A%253C%252Fdiv%253E&quot;&gt;&lt;/iframe&gt;
  &lt;/figure&gt;
  &lt;h3&gt;features.htm&lt;/h3&gt;
  &lt;p&gt;Партиалку для отображения преимуществ &lt;code&gt;themes/landing/partials/content/features.htm&lt;/code&gt; тоже модифицируем:&lt;/p&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;iframe src=&quot;https://carbon.now.sh/embed?bg=rgba%28171%2C+184%2C+195%2C+1%29&amp;t=monokai&amp;wt=none&amp;l=htmlmixed&amp;ds=true&amp;dsyoff=20px&amp;dsblur=68px&amp;wc=true&amp;wa=false&amp;pv=56px&amp;ph=56px&amp;ln=false&amp;fl=1&amp;fm=Hack&amp;fs=14px&amp;lh=133%25&amp;si=false&amp;es=2x&amp;wm=false&amp;code=%253Cdiv%2520id%253D%2522features-%257B%257B%2520blockKey%2520%257D%257D%2522%2520class%253D%2522content-block%2520features-block%2522%253E%250A%2520%2520%2520%2520%253Ch2%253E%257B%257B%2520blockContent.title%2520%257D%257D%253C%252Fh2%253E%250A%2520%2520%2520%2520%253Cdiv%2520class%253D%2522features-block__features%2522%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%257B%2525%2520for%2520feature%2520in%2520blockContent.features_items%2520%2525%257D%250A%2520%2520%2520%2520%2520%2520%2520%2520%253Cdiv%2520class%253D%2522features-block__feature%2522%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%253Cdiv%2520class%253D%2522features-block__feature-title%2522%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%257B%257B%2520feature.feature_title%2520%257D%257D%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%253C%252Fdiv%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%253Cdiv%2520class%253D%2522features-block__feature-description%2522%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%257B%257B%2520feature.feature_description%2520%257D%257D%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%253C%252Fdiv%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%253C%252Fdiv%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%257B%2525%2520endfor%2520%2525%257D%250A%2520%2520%2520%2520%253C%252Fdiv%253E%250A%253C%252Fdiv%253E&quot;&gt;&lt;/iframe&gt;
  &lt;/figure&gt;
  &lt;h3&gt;slider.htm&lt;/h3&gt;
  &lt;p&gt;И наконец слайдер &lt;code&gt;themes/landing/partials/content/slider.htm&lt;/code&gt; мы поправим в два этапа.&lt;/p&gt;
  &lt;p&gt;Для примера слайдера используем библиотеку &lt;a href=&quot;https://github.com/kenwheeler/slick&quot; target=&quot;_blank&quot;&gt;https://github.com/kenwheeler/slick&lt;/a&gt;&lt;/p&gt;
  &lt;p&gt;Как и написано в документации, подключим стили в файл шаблона &lt;code&gt;themes/landing/layouts/default.htm&lt;/code&gt; в раздел &lt;code&gt;head&lt;/code&gt;&lt;/p&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;iframe src=&quot;https://carbon.now.sh/embed?bg=rgba%28171%2C+184%2C+195%2C+1%29&amp;t=monokai&amp;wt=none&amp;l=htmlmixed&amp;ds=true&amp;dsyoff=20px&amp;dsblur=68px&amp;wc=true&amp;wa=false&amp;pv=56px&amp;ph=56px&amp;ln=false&amp;fl=1&amp;fm=Hack&amp;fs=14px&amp;lh=133%25&amp;si=false&amp;es=2x&amp;wm=false&amp;code=%253Chead%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%253Cmeta%2520charset%253D%2522utf-8%2522%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%253Ctitle%253EOctober%2520CMS%2520-%2520%257B%257B%2520this.page.title%2520%257D%257D%253C%252Ftitle%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%253Cmeta%2520name%253D%2522description%2522%2520content%253D%2522%257B%257B%2520this.page.meta_description%2520%257D%257D%2522%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%253Cmeta%2520name%253D%2522title%2522%2520content%253D%2522%257B%257B%2520this.page.meta_title%2520%257D%257D%2522%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%253Cmeta%2520name%253D%2522author%2522%2520content%253D%2522OctoberCMS%2522%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%253Cmeta%2520name%253D%2522viewport%2522%2520content%253D%2522width%253Ddevice-width%252C%2520initial-scale%253D1.0%2522%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%253Cmeta%2520name%253D%2522generator%2522%2520content%253D%2522OctoberCMS%2522%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%253Clink%2520rel%253D%2522icon%2522%2520type%253D%2522image%252Fpng%2522%2520href%253D%2522%257B%257B%2520%27assets%252Fimages%252Foctober.png%27%257Ctheme%2520%257D%257D%2522%253E%250A%250A%2520%2520%2520%2520%2520%2520%2520%2520%253C%21--%2520slick%2520--%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%253Clink%2520rel%253D%2522stylesheet%2522%2520type%253D%2522text%252Fcss%2522%2520href%253D%2522%252F%252Fcdn.jsdelivr.net%252Fnpm%252Fslick-carousel%25401.8.1%252Fslick%252Fslick.css%2522%252F%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%253Clink%2520rel%253D%2522stylesheet%2522%2520type%253D%2522text%252Fcss%2522%2520href%253D%2522%252F%252Fcdn.jsdelivr.net%252Fnpm%252Fslick-carousel%25401.8.1%252Fslick%252Fslick-theme.css%2522%252F%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%253C%21--%2520slick%2520--%253E%250A%250A%2520%2520%2520%2520%2520%2520%2520%2520%253Clink%2520href%253D%2522%257B%257B%2520%27assets%252Fcss%252Fvendor.css%27%257Ctheme%2520%257D%257D%2522%2520rel%253D%2522stylesheet%2522%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%253Clink%2520href%253D%2522%257B%257B%2520%27assets%252Fcss%252Ftheme.css%27%257Ctheme%2520%257D%257D%2522%2520rel%253D%2522stylesheet%2522%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%257B%2525%2520styles%2520%2525%257D%250A%253C%252Fhead%253E&quot;&gt;&lt;/iframe&gt;
  &lt;/figure&gt;
  &lt;p&gt;и в конец шаблона добавим js-библиотеку:&lt;/p&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;iframe src=&quot;https://carbon.now.sh/embed?bg=rgba%28171%2C+184%2C+195%2C+1%29&amp;t=monokai&amp;wt=none&amp;l=htmlmixed&amp;ds=true&amp;dsyoff=20px&amp;dsblur=68px&amp;wc=true&amp;wa=false&amp;pv=56px&amp;ph=56px&amp;ln=false&amp;fl=1&amp;fm=Hack&amp;fs=14px&amp;lh=133%25&amp;si=false&amp;es=2x&amp;wm=false&amp;code=%2520%253C%21--%2520Scripts%2520--%253E%250A%2520%2520%2520%2520%253Cscript%2520src%253D%2522%257B%257B%2520%27assets%252Fvendor%252Fjquery.js%27%257Ctheme%2520%257D%257D%2522%253E%253C%252Fscript%253E%250A%2520%2520%2520%2520%253Cscript%2520src%253D%2522%257B%257B%2520%27assets%252Fvendor%252Fbootstrap.js%27%257Ctheme%2520%257D%257D%2522%253E%253C%252Fscript%253E%250A%2520%2520%2520%2520%253C%21--%2520slick%2520--%253E%250A%2520%2520%2520%2520%253Cscript%2520type%253D%2522text%252Fjavascript%2522%2520src%253D%2522%252F%252Fcdn.jsdelivr.net%252Fnpm%252Fslick-carousel%25401.8.1%252Fslick%252Fslick.min.js%2522%253E%253C%252Fscript%253E%250A%2520%2520%2520%2520%253C%21--%2520slick%2520--%253E%250A%2520%2520%2520%2520%253Cscript%2520src%253D%2522%257B%257B%2520%27assets%252Fjavascript%252Fapp.js%27%257Ctheme%2520%257D%257D%2522%253E%253C%252Fscript%253E%250A%2520%2520%2520%2520%257B%2525%2520framework%2520extras%2520%2525%257D%250A%2520%2520%2520%2520%257B%2525%2520scripts%2520%2525%257D&quot;&gt;&lt;/iframe&gt;
  &lt;/figure&gt;
  &lt;p&gt;Далее отредактируем файл &lt;code&gt;themes/landing/partials/content/slider.htm&lt;/code&gt; и приведем его к следующему виду:&lt;/p&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;iframe src=&quot;https://carbon.now.sh/embed?bg=rgba%28171%2C+184%2C+195%2C+1%29&amp;t=monokai&amp;wt=none&amp;l=htmlmixed&amp;ds=true&amp;dsyoff=20px&amp;dsblur=68px&amp;wc=true&amp;wa=false&amp;pv=56px&amp;ph=56px&amp;ln=false&amp;fl=1&amp;fm=Hack&amp;fs=14px&amp;lh=133%25&amp;si=false&amp;es=2x&amp;wm=false&amp;code=%253Cdiv%2520id%253D%2522slider-%257B%257B%2520blockKey%2520%257D%257D%2522%2520class%253D%2522content-block%2520slider-block%2522%253E%250A%2520%2520%2520%2520%253Ch2%253E%257B%257BblockContent.hint%257D%257D%253C%252Fh2%253E%250A%2520%2520%2520%2520%253Cdiv%2520class%253D%2522slider-block__slider%2522%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%257B%2525%2520for%2520image%2520in%2520blockContent.images%2520%2525%257D%250A%2520%2520%2520%2520%2520%2520%2520%2520%253Cdiv%2520class%253D%2522slider-block__slide%2522%2520style%253D%2522background-image%253A%2520url%28%27%257B%257B%2520image.image%257Cmedia%2520%257D%257D%27%29%253B%2522%253E%253C%252Fdiv%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%257B%2525%2520endfor%2520%2525%257D%250A%2520%2520%2520%2520%253C%252Fdiv%253E%250A%253C%252Fdiv%253E%250A%250A%257B%2525%2520put%2520scripts%2520%2525%257D%250A%253Cscript%253E%250A%2520%2520%2520%2520%2524%28%27%2523slider-%257B%257B%2520blockKey%2520%257D%257D%2520.slider-block__slider%27%29.slick%28%257B%250A%2520%2520%2520%2520%2520%2520%2520%2520dots%253A%2520true%252C%250A%2520%2520%2520%2520%2520%2520%2520%2520infinite%253A%2520true%252C%250A%2520%2520%2520%2520%2520%2520%2520%2520speed%253A%2520300%252C%250A%2520%2520%2520%2520%2520%2520%2520%2520slidesToShow%253A%25201%252C%250A%2520%2520%2520%2520%257D%29%253B%250A%253C%252Fscript%253E%250A%257B%2525%2520endput%2520%2525%257D&quot;&gt;&lt;/iframe&gt;
  &lt;/figure&gt;
  &lt;h3&gt;Немного CSS&lt;/h3&gt;
  &lt;p&gt;Мы не зря добавили css-классы в наши partial-файлы. Приправим наш урок небольшой порцией css.&lt;/p&gt;
  &lt;p&gt;В конец файла &lt;code&gt;themes/landing/assets/css/theme.css&lt;/code&gt; добавим немного своего:&lt;/p&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;iframe src=&quot;https://carbon.now.sh/embed?bg=rgba%28171%2C+184%2C+195%2C+1%29&amp;t=monokai&amp;wt=none&amp;l=css&amp;ds=true&amp;dsyoff=20px&amp;dsblur=68px&amp;wc=true&amp;wa=false&amp;pv=56px&amp;ph=56px&amp;ln=false&amp;fl=1&amp;fm=Hack&amp;fs=14px&amp;lh=133%25&amp;si=false&amp;es=2x&amp;wm=false&amp;code=.content-block%2520%257B%250A%2520%2520%2520%2520margin-bottom%253A%252040px%253B%250A%257D%250A%250A.features-block%2520h2%2520%257B%250A%2520%2520%2520%2520text-align%253A%2520center%253B%250A%257D%250A%250A.features-block__features%2520%257B%250A%2520%2520%2520%2520display%253A%2520flex%253B%250A%2520%2520%2520%2520justify-content%253A%2520center%253B%250A%257D%250A%250A.features-block__feature%2520%257B%250A%2520%2520%2520%2520padding%253A%252030px%253B%250A%2520%2520%2520%2520flex%253A%25201%25201%25200%253B%250A%257D%250A%250A.features-block__feature-title%2520%257B%250A%2520%2520%2520%2520font-size%253A%252018px%253B%250A%2520%2520%2520%2520text-align%253A%2520center%253B%250A%257D%250A%250A.features-block__feature-description%2520%257B%250A%2520%2520%2520%2520font-size%253A%252048px%253B%250A%2520%2520%2520%2520text-align%253A%2520center%253B%250A%257D%250A%250A.image-block%2520%257B%250A%2520%2520%2520%2520display%253A%2520flex%253B%250A%2520%2520%2520%2520justify-content%253A%2520center%253B%250A%257D%250A%250A.image-block__image%2520%257B%250A%2520%2520%2520%2520width%253A%252070%2525%253B%250A%257D%250A%250A.image-block__image%2520img%2520%257B%250A%2520%2520%2520%2520width%253A%2520100%2525%253B%250A%257D%250A%250A.slider-block__slide%2520%257B%250A%2520%2520%2520%2520height%253A%2520500px%253B%250A%2520%2520%2520%2520background-position%253A%2520center%253B%250A%2520%2520%2520%2520background-repeat%253A%2520no-repeat%253B%250A%2520%2520%2520%2520background-size%253A%2520cover%253B%250A%257D&quot;&gt;&lt;/iframe&gt;
  &lt;/figure&gt;
  &lt;h2&gt;Что в итоге?&lt;/h2&gt;
  &lt;p&gt;В итоге у нас должно получиться следующее:&lt;/p&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://teletype.in/files/da/d1/dad127b7-7789-43b1-bb73-1de3b94497de.png&quot; width=&quot;1920&quot; /&gt;
  &lt;/figure&gt;
  &lt;p&gt;Выглядит вполне приемлемо!&lt;/p&gt;
  &lt;h2&gt;Немного универсализации&lt;/h2&gt;
  &lt;p&gt;Что же мы хотим - мы хотим в дальнейшем посадить на один движок OctoberCMS несколько лендингов, чем больше - тем лучше!&lt;/p&gt;
  &lt;p&gt;Можно заморочиться и написать свой плагин для мультисайта, но в рамках урока используем готовые наработки из маркетплейса OctoberCms - плагин &lt;a href=&quot;https://octobercms.com/plugin/briddle-multisite&quot; target=&quot;_blank&quot;&gt;Multiple Websites Manager Lite&lt;/a&gt; - простой, понятный и бесплатный.&lt;/p&gt;
  &lt;h3&gt;Что нужно сделать:&lt;/h3&gt;
  &lt;ul&gt;
    &lt;li&gt;установить плагин &lt;code&gt;Briddle.Multisite&lt;/code&gt;&lt;/li&gt;
    &lt;li&gt;суметь настроить домен третьего уровня (об этом не в этом уроке)&lt;/li&gt;
    &lt;li&gt;отредактировать конфиг плагина &lt;code&gt;/plugins/briddle/multisite/config&lt;/code&gt;&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p&gt;Для примера мы скопируем нашу тему &lt;code&gt;landing&lt;/code&gt; и назовем ее &lt;code&gt;landing2&lt;/code&gt;&lt;/p&gt;
  &lt;p&gt;Не забываем отредактировать файл &lt;code&gt;themes/landing2/theme.yaml&lt;/code&gt;&lt;/p&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;iframe src=&quot;https://carbon.now.sh/embed?bg=rgba%28171%2C+184%2C+195%2C+1%29&amp;t=monokai&amp;wt=none&amp;l=yaml&amp;ds=true&amp;dsyoff=20px&amp;dsblur=68px&amp;wc=true&amp;wa=false&amp;pv=56px&amp;ph=56px&amp;ln=false&amp;fl=1&amp;fm=Hack&amp;fs=14px&amp;lh=133%25&amp;si=false&amp;es=2x&amp;wm=false&amp;code=name%253A%2520Landing%2520theme%25202%250Adescription%253A%2520%27Landing%2520demo%2520theme%25202%27%250Aauthor%253A%2520OctoberCMS%250Ahomepage%253A%2520%27http%253A%252F%252Foctobercms.com%27%250Acode%253A%2520%27landing-theme-2%27&quot;&gt;&lt;/iframe&gt;
  &lt;/figure&gt;
  &lt;p&gt;Далее отредактируем &lt;code&gt;/plugins/briddle/multisite/config&lt;/code&gt;&lt;/p&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;iframe src=&quot;https://carbon.now.sh/embed?bg=rgba%28171%2C+184%2C+195%2C+1%29&amp;t=monokai&amp;wt=none&amp;l=text%2Fx-php&amp;ds=true&amp;dsyoff=20px&amp;dsblur=68px&amp;wc=true&amp;wa=false&amp;pv=56px&amp;ph=56px&amp;ln=false&amp;fl=1&amp;fm=Hack&amp;fs=14px&amp;lh=133%25&amp;si=false&amp;es=2x&amp;wm=false&amp;code=%253C%253Fphp%250A%250Areturn%2520%255B%250A%2520%2520%2520%2520%27sites%27%2520%253D%253E%2520%255B%250A%2520%2520%2520%2520%2520%2520%2520%2520%255B%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%27host%27%2520%253D%253E%2520%27sandbox.test%27%252C%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%27theme%27%2520%253D%253E%2520%27landing%27%250A%2520%2520%2520%2520%2520%2520%2520%2520%255D%252C%250A%2520%2520%2520%2520%2520%2520%2520%2520%255B%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%27host%27%2520%253D%253E%2520%27landing2.sandbox.test%27%252C%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%27theme%27%2520%253D%253E%2520%27landing2%27%250A%2520%2520%2520%2520%2520%2520%2520%2520%255D%250A%2520%2520%2520%2520%255D%250A%255D%253B&quot;&gt;&lt;/iframe&gt;
  &lt;/figure&gt;
  &lt;p&gt;В админке сайта добавляем новый материал:&lt;/p&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://teletype.in/files/41/69/41693313-8220-412a-b6df-b748d7f22ae6.png&quot; width=&quot;730&quot; /&gt;
  &lt;/figure&gt;
  &lt;p&gt;Теперь заходим в админку сайта, но уже по адресу &lt;code&gt;landing2.sandbox.test&lt;/code&gt;&lt;/p&gt;
  &lt;p&gt;Переходим в раздел CMS и отредактируем файл шаблона &lt;code&gt;layouts/default.htm&lt;/code&gt;&lt;/p&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://teletype.in/files/0d/00/0d00be02-f92f-40ba-a3f9-1668fc0bf50a.png&quot; width=&quot;1030&quot; /&gt;
  &lt;/figure&gt;
  &lt;p&gt;Выбираем новую созданную страницу.&lt;/p&gt;
  &lt;h2&gt;Результат&lt;/h2&gt;
  &lt;p&gt;По итогу этого небольшого гайда у нас должно быть в наличии:&lt;/p&gt;
  &lt;ul&gt;
    &lt;li&gt;плагин для создания лендинговых страниц&lt;/li&gt;
    &lt;li&gt;две темы (сайта) , которые работают с одним движком&lt;/li&gt;
    &lt;li&gt;и такой результат:&lt;/li&gt;
  &lt;/ul&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://teletype.in/files/fd/f3/fdf31ec2-9cee-4d83-8829-23702ad00367.jpeg&quot; width=&quot;1600&quot; /&gt;
  &lt;/figure&gt;
  &lt;h2&gt;Ссылки&lt;/h2&gt;
  &lt;p&gt;&lt;a href=&quot;https://github.com/gromitsoft/sandbox&quot; target=&quot;_blank&quot;&gt;https://github.com/gromitsoft/sandbox&lt;/a&gt; - репозиторий с исходным кодом&lt;br /&gt;&lt;a href=&quot;https://blog.grom-it.ru/N9epRWxGX&quot; target=&quot;_blank&quot;&gt;https://blog.grom-it.ru/N9epRWxGX&lt;/a&gt; - первая часть урока&lt;/p&gt;
  &lt;tt-tags&gt;
    &lt;tt-tag name=&quot;octobercms&quot;&gt;#octobercms&lt;/tt-tag&gt;
    &lt;tt-tag name=&quot;landing&quot;&gt;#landing&lt;/tt-tag&gt;
  &lt;/tt-tags&gt;

</content></entry><entry><id>gromit:T7Jo76xx1</id><link rel="alternate" type="text/html" href="https://blog.grom-it.ru/T7Jo76xx1?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=gromit"></link><title>QuickActions в OctoberCMS</title><published>2021-03-30T17:33:12.816Z</published><updated>2021-03-30T18:05:49.966Z</updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://teletype.in/files/c1/ec/c1ecc05e-fd45-48f6-952e-8f632f5b7ffc.jpeg"></media:thumbnail><category term="october-cms" label="OctoberCMS"></category><tt:hashtag>octobercms</tt:hashtag><tt:hashtag>tips</tt:hashtag><tt:hashtag>backend</tt:hashtag><summary type="html">&lt;img src=&quot;https://teletype.in/files/6d/29/6d29d0cf-bcf0-4d96-b8a0-14c671da1020.jpeg&quot;&gt;Заметка из разряда - &quot;Всякие интересности в OctoberCMS&quot;</summary><content type="html">
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://teletype.in/files/6d/29/6d29d0cf-bcf0-4d96-b8a0-14c671da1020.jpeg&quot; width=&quot;1200&quot; /&gt;
  &lt;/figure&gt;
  &lt;p&gt;Заметка из разряда - &amp;quot;Всякие интересности в OctoberCMS&amp;quot;&lt;/p&gt;
  &lt;p&gt;В ноябре 2020 г. был замечен интересный &lt;a href=&quot;https://github.com/octobercms/october/pull/5344&quot; target=&quot;_blank&quot;&gt;pull-request&lt;/a&gt; в репозиторий OctoberCMS.&lt;/p&gt;
  &lt;blockquote&gt;This PR adds support for defining quick actions in the main navigation in the Backend. Quick actions in this case are defined as the single-purpose icon links located to the left of the user menu - the only one currently available in an October CMS install is the link to preview the website.&lt;/blockquote&gt;
  &lt;p&gt;Другими словами этот PR добавляет &amp;quot;быстрые действия&amp;quot; в основной навигации в панели управления, расположенные слева от ссылки для предварительного просмотра сайта.&lt;/p&gt;
  &lt;h2&gt;Небольшой How-To&lt;/h2&gt;
  &lt;p&gt;Для того, чтобы новая фича заработала - нам нужна новая установка OctoberCMS из композера:&lt;/p&gt;
  &lt;pre&gt;composer create-project october/october myoctober&lt;/pre&gt;
  &lt;p&gt;и обновиться до последней версии через тот же composer:&lt;/p&gt;
  &lt;pre&gt;composer update&lt;/pre&gt;
  &lt;h3&gt;Создадим тестовый плагин для эксперимента&lt;/h3&gt;
  &lt;p&gt;Для создания тестового плагина QuickActions выполним в консоли:&lt;/p&gt;
  &lt;pre&gt;php artisan create:plugin sandbox.quickactions&lt;/pre&gt;
  &lt;p&gt;Далее, отредактируем файл Plugin.php, добавим в него следующее:&lt;/p&gt;
  &lt;pre&gt;public function registerQuickActions()
{
    return [
        &amp;#x27;help&amp;#x27; =&amp;gt; [
            &amp;#x27;label&amp;#x27; =&amp;gt; &amp;#x27;Read the documentation &amp;#x27;,
            &amp;#x27;icon&amp;#x27; =&amp;gt; &amp;#x27;icon-question-circle&amp;#x27;,
            &amp;#x27;url&amp;#x27; =&amp;gt; Backend::url(&amp;#x27;read-the-docs&amp;#x27;),
        ],        
    ];
}&lt;/pre&gt;
  &lt;p&gt;Voila, теперь в панели управления мы увидим такое новшество:&lt;/p&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://teletype.in/files/38/8d/388d911c-c2d5-4d33-a197-6f8362eb9736.png&quot; width=&quot;2002&quot; /&gt;
  &lt;/figure&gt;
  &lt;p&gt;Пойдем дальше, добавим кастомную svg-иконку. Очень часто в проектах мы используем ресурс &lt;a href=&quot;https://www.svgrepo.com/&quot; target=&quot;_blank&quot;&gt;https://www.svgrepo.com/&lt;/a&gt; как источник иконок.&lt;/p&gt;
  &lt;p&gt;Добавим быструю ссылку для связи с разработчиками сайта. Для иконки возьмем первую попавшуюся из этого набора &lt;a href=&quot;https://www.svgrepo.com/vectors/mail/multicolor/&quot; target=&quot;_blank&quot;&gt;https://www.svgrepo.com/vectors/mail/multicolor/&lt;/a&gt; и добавим ее в наш плагин в папку:&lt;/p&gt;
  &lt;pre&gt;plugins/sandbox/quickactions/assets/svg&lt;/pre&gt;
  &lt;p&gt;Далее отредактируем метод &lt;code&gt;registerQuickActions()&lt;/code&gt; в файле &lt;code&gt;Plugin.php&lt;/code&gt;&lt;/p&gt;
  &lt;pre&gt;public function registerQuickActions()
{
    return [
        &amp;#x27;help&amp;#x27; =&amp;gt; [
            &amp;#x27;label&amp;#x27; =&amp;gt; &amp;#x27;Read the documentation&amp;#x27;,
            &amp;#x27;icon&amp;#x27; =&amp;gt; &amp;#x27;icon-question-circle&amp;#x27;,
            &amp;#x27;url&amp;#x27; =&amp;gt; Backend::url(&amp;#x27;read-the-docs&amp;#x27;),
        ],
        &amp;#x27;mail&amp;#x27; =&amp;gt; [
            &amp;#x27;label&amp;#x27; =&amp;gt; &amp;#x27;Send email to developers&amp;#x27;,
            &amp;#x27;iconSvg&amp;#x27; =&amp;gt; &amp;#x27;/plugins/sandbox/quickactions/assets/svg/mail.svg&amp;#x27;,
            &amp;#x27;url&amp;#x27; =&amp;gt; Backend::url(&amp;#x27;mail-to-devs&amp;#x27;),
        ],           
    ];
}&lt;/pre&gt;
  &lt;p&gt;Смотрим что получилось:&lt;/p&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://teletype.in/files/da/0a/da0a1e5c-483a-4eb8-a078-5967d6dd07dc.png&quot; width=&quot;1992&quot; /&gt;
  &lt;/figure&gt;
  &lt;p&gt;В своих проектах мы пока не применяли данную возможность, но надеемся, что кому-то это пригодится!&lt;/p&gt;
  &lt;tt-tags&gt;
    &lt;tt-tag name=&quot;octobercms&quot;&gt;#octobercms&lt;/tt-tag&gt;
    &lt;tt-tag name=&quot;tips&quot;&gt;#tips&lt;/tt-tag&gt;
    &lt;tt-tag name=&quot;backend&quot;&gt;#backend&lt;/tt-tag&gt;
  &lt;/tt-tags&gt;

</content></entry></feed>