Евгений Шеронов

Евгений Шеронов

С нами с 20 мая 2015; Место в рейтинге пользователей: #30
Евгений Шеронов
26 мая 2021, 12:10
0
Не особо слежу за ютуб обучениями, но такой подход — это такой же трэш)

Даже если нужно будет фронтенд раскидать между командами — то это точно будет не так.
Варианты:
1) Разные фреймворки — но по разделам, админка например на одном фреймворке, пользовательская на другом.
2) Если прям хочется поделить одну страницу — то всё просто в пределах одного фреймворка, но использованием одного нормального хранилища с модульной структурой, типо Vuex или Redux. ​

Поэтому, что это видео, что то на английском — всё это жуткий bad practice. Остаётся надеяться, что все просмотревшие восприняли это как учебный эксперимент и никогда не подумают повторять.
Евгений Шеронов
25 мая 2021, 18:12
+1
Я бы сказал, что оно очень необычное))
Полностью смотреть не стал (там на канале ещё 2), но подход автора видео по Vue.js мягко говоря странноват.

Сам компонент вот github.com/jaredfhealy/extrabuilder/ и, наверное, он хорошо выполняет свои функции.
Но автор умудрился намешать ExtJs, Vue.js и даже jQuery и всё это подрубается в админку через iframe!
Евгений Шеронов
24 мая 2021, 11:02
+1
Ну там нет конфликта скриптов точно, а вот в стилях всех у меня добавляется css префикс.

Конфликт будет только с простыми названиями классов, это можно и как плюс использовать. Именно для иконок используются стандартные классы. Но все свои классы я пишу добавляя префикс компонента.

Я в админку совсем не захожу, только после сборки раз в неделю что-то проверить)
По идее всё как видишь на отдельной страничке — так и отображается в админке.

Есть смысл локально развернуть как раз для дебага PHP. Xdebug на modhost не поставить же?
Евгений Шеронов
24 мая 2021, 10:13
+2
Как раз на сервере ничего не происходит, там только MODX который генерирует модели по схеме и отвечает на запросы.
Сборка стилей и js в master ветке локально в шторме. Я их и в git кладу.
Можно и на сервере, в заготовке есть пример сборки assets. Но потом опять надо буде выкачать изменения себе)

Так, уточню про процесс по пунктам подробнее)
1) Открываю PhpStorm
2) Жму serve во вкладке npm (читай пишу npm serve в терминале)
3) Происходит небольшая сборка и становится доступна страничка localhost:8080
4) На этой страничке есть только стили и шрифты от MODX и один
5) В него Vue.js уже маунтит приложение.
6) Для ajax запросов я использую axios, в который в зависимости от окружения добавляются псевдокуки в main.js (там где new Vue(...)) и создание конфига.
import axios from "axios";
   let ym2Config = window.ym2Config || (process.env.NODE_ENV !== 'production' ? {
        modAuth: process.env.VUE_APP_MOD_AUTH || '',
        apiUrl: process.env.VUE_APP_API_URL || '',
        xmlLoaded: true,
        lang: {}
    } : {});
 axios.defaults.baseURL = ym2Config.apiUrl || '/assets/components/yandexmarket2/connector.php';
    axios.defaults.headers.common['modAuth'] = ym2Config.modAuth;
    if (process.env.NODE_ENV !== 'production' && process.env.VUE_APP_COOKIE) {
        axios.defaults.headers.common['modCookie'] = process.env.VUE_APP_COOKIE;
    }
//...тут дальше new Vue({...}).$mount('#yandexmarket-app');
7) И при каждой правке обновляется даже не вся локальная страница, а именно тот участок DOM, что обновился. Vue очень умный) Вся страница обновится если что-то сильно общее поменять.

А чтоб это всё работало админке MODX уже Home контроллер отвечает за создание windows.ym2Config и создание разметки:
<?php 
   ...
// тут ничего нового, всё уже описано в вышеупомянутых заметках про vue в админке)
 public function getTemplateFile(): string
    {
        $this->content .= '<div id="yandexmarket-app"></div>';
        return '';
    }

    public function loadCustomCssJs()
    {
        $this->addCss($this->mgrAssetsUrl.'css/chunk-vendors.css');
        $this->addCss($this->mgrAssetsUrl.'css/app.css');

        $this->addHtml("<script type=\"text/javascript\">
        window.ym2Config = {
            apiUrl: \"{$this->connectorUrl}\",
            modAuth: \"{$this->modx->user->getUserToken($this->modx->context->key)}\",
            xmlLoaded: {$this->xmlLoaded}, 
            lang: {}
        }
        </script>");

        $this->addJavascript($this->mgrAssetsUrl.'js/chunk-vendors.js');
        $this->addLastJavascript($this->mgrAssetsUrl.'js/app.js');
    }
Евгений Шеронов
24 мая 2021, 09:55
+2
Спасибо!)

Интересный подход — нужно попробовать.
В комментах чуть поделюсь кодом:
<?php
// в начале файла /assets/components/yandexmarket2/connector.php
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Headers: Authorization, Cookie, Content-Type, Accept, modAuth, modCookie');
header('Access-Control-Allow-Methods: OPTIONS, HEAD, POST, GET, PUT, DELETE');
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
    die; //браузеры уже очень давно перед каждым запросом отправляют OPTIONS для проверки CORS
}
if (isset($_SERVER['HTTP_MODCOOKIE'])) {
    //а тут уже строка в таком формате приходит: "MODSESSID=aaaaa; PHPSESSID=aaaaa"
    $modCookie = array_map('trim', explode(';', $_SERVER['HTTP_MODCOOKIE']));
    foreach ($modCookie as $cookie) {
        list($key, $value) = explode('=', $cookie, 2);
        $_COOKIE[$key] = $value;
    }
}
Этот код у меня только в dev ветке. Людям в продакшн он уже не попадает)

Зачем усложняешь?
Действительно, но в где-то явно может быть иначе. Видел, что вообще по умолчанию PHP 5.4, в /usr/bin/ только один php. А нормальный лежит тут: /opt/php70/bin/php

А для чего такое решение? Чем не устроило то что есть в xPDOSimpleObject например?
Как раз чтобы не привязывать логику к конкретным xPDO объектам. Ну и они не подходят под PSR-4.
Идея была в том, что компонент не должен особо знать, что там подсунуто.
В идеале от этих объектов требовалось имплементация методов save, toArray и get-set для свойств.
Надеюсь, что легко можно будет портировать интерфейс хоть под Laravel, там тоже ActiveRecord модель, которую можно будет смаппить с моделями из компонента)

А еще всегда можно прислать PR
Найду когда-нибудь время и поэкспериментирую с предложенным функционалом, замерю разницу.
Евгений Шеронов
16 мая 2021, 16:22
0
Тут человек AjaxForm путает с AjaxSnippet, поэтому твой совет не поможет (но комментарий привлёк меня, так что косвенно ты тоже помогаешь :))
Там нет никакой формы и вообще ничто никуда не отправится.

При этом сниппет addfavorites ведёт себя как хук для FormIt (хотя вполне себе можно без него, просто оперируя POST данными).

Следовательно вызов в таблице должен быть таким:
(чтобы не мешать синтаксис, ведь люди старались сделать всё изначально на Fenom)
{$_modx->runSnippet('!AjaxForm', [
    'snippet' => 'FormIt',
    'form' => 'tpl.Favorite',
    'hooks' =>  'addfavorite',
    'fi.name' => $service.name,
    'fi.id_service' => $service.id_service,
    'fi.cost' => $service.cost,
    'fi.address' => $service.address
])}
Параметры fi.name и т.д. нужны, чтобы прокинуть данные в форму. См. modx.pro/components/3342

А чанк tpl.Favorite переделать хотя бы так:
<form action="" method="post" class="ajax_form">
    <input type="hidden" name="name" value="[[+fi.name]]">
    <input type="hidden" name="id_service" value="[[+fi.id_service]]">
    <input type="hidden" name="cost" value="[[+fi.cost]]">
    <input type="hidden" name="address" value="[[+fi.address]]">
    <button type="submit" class="center">В избранное</button>
</form>
Это, конечно, не отменяет множество проблем в коде автора.
Например строка $id_user = $modx->user->get('id'); будет работать только для авторизованных пользователей (для админа когда он проверяет). А на пользователях-гостях вполне себе будет падать.

Ну и какой-то странный формат HTML вёрстки с запятой и разными кавычками)
<td class='service' id="cost", value="{$service.price}">Стоимость: {$service.price} ₽</td>

Мне немного страшно и интересно, как же будет выглядеть запрос, который положит данные в базу.
Евгений Шеронов
09 мая 2021, 19:26
0
Почему все так избегают использовать инструменты из коробки?
Есть же хук FormItSaveForm, под который есть даже визуальный интерфейс в админке.
Евгений Шеронов
23 апреля 2021, 14:46
0
Пожалуйста, только тут лучше (float), иначе уже бизнес логика может пострадать))
(int)$_POST['price']
Евгений Шеронов
23 апреля 2021, 13:05
+2
Вроде к каждой статье пишут про безопасность, не?)

$sql = 'SELECT COUNT(id) FROM modxwb_ms2_order_products WHERE product_id = '.$_POST['id'];
Ну это прям призыв, чтобы пришли люди и грохнули сайт без каких-либо сложностей))

$modx->getObject('modResource', $_POST['id']);
И даже так (и вроде когда используется массив) (обсуждали уже где-то здесь) что-угодно можно пропихнуть.

Всегда когда работаем с целыми числами всего лишь нужно добавить (int) перед чем-угодно и спать спокойно.

А это открывает доступ к другим типам инъекций.
<input type="hidden" id="orderid" value="{$.get.msorder}">
Возможно, Fenom что-то там и порежет, но надеяться не стоит.
Евгений Шеронов
23 апреля 2021, 12:54
0
Спасибо!
Теперь по замечаниям.
1) Абсолютный путь в целом там и не нужен, оставлю относительный.
Но ещё более не секьюрно давать кому-то доступ в админку))
Там и без этого никаких проблем получить все системные настройки через Fenom.

2) Поправил, в следующем обновлении уже не должно всплывать.
Евгений Шеронов
13 апреля 2021, 13:35
+1
Авторы могут и не заметить здесь и не знать о запрашиваемых интеграциях)
И в поддержке ни разу про такое никто не спрашивал.

Ну такая интеграция скорее всего потребует дополнительных расходов)

Вообще не помешала бы возможность подключать уведомления об интересующих компонентах, которые всё равно привязываются к топику при их упоминании.
Евгений Шеронов
04 апреля 2021, 13:31
0
А предпросмотр XML работал?
Напишите мне в поддержку с указанием доступов.
По скриншоту тяжело что-то сказать.
Евгений Шеронов
19 марта 2021, 12:28
0
Именно Vuetify 2, иначе бы ещё на несколько месяцев затянул))
Там в целом компоненты очень похожи на Ext JS, разве что гибче. Иконки все используются из MODX стилей.

В первом варианте этой статьи было слишком много технических подробностей, перенёс их в черновик.
Видимо, нужно как нибудь дописать)
Евгений Шеронов
18 марта 2021, 14:02
+4
Я тебе ещё в прошлом году присылал пример встраивания Vue.js в админку))
И вот только сейчас всё это выглядит как полноценный компонент.

Вообще разрабатывать гораздо приятнее и удобнее. Тот же hot-reload, обновляющий на странице только изменившуюся часть DOM, реактивность, роутинг, хранилище, прям хочется ещё что-то сделать)
Но всё равно, полноценный компонент слишком долго делать :(

Если сильно захотеть текущий компонент легко перенести из админки на фронт или вообще заюзать в другой CMS, так как старался абстрагироваться от MODX сущностей (не получилось).
Евгений Шеронов
02 ноября 2020, 15:05
0
Здравствуйте, Вы вроде уже писали мне?

Здесь только через prepareSnippet сможете сделать замену нужных Вам тегов.

Также, если есть какие-то теги или стили у html-тегов, то их нужно подчистить.
Для этого должен быть установлен Jevix.

Вот пример сниппета prepareMarketDescription, который сделает то, что нужно.
Добавьте его и укажите название в настройку ms2ym_prepare_snippet.

<?php
if(!empty($fields['description'])) {
    //масссив для замен 
    $replaces = [
        '[[*pagetitle]]' => $product['pagetitle'],
        '[[+article]]'   => $product['article']
    ];
    
    // все доступные поля можно посмотреть в логе расскоментировав две строки ниже:
    // $modx->log(1,'Поля в XML: '.print_r($fields,1));
    // $modx->log(1,'Поля товара: '.print_r($product,1));
    
    $fields['description'] = $modx->runSnippet('Jevix',[
        'input'=> str_replace(array_keys($replaces), array_values($replaces), $fields['description']),
        'cfgAllowTags'=>'h3,ul,ol,li,p,br',
        'cfgSetAutoLinkMode'=>0,
        'cfgAllowTagParams'=>'{}',
        'cfgSetTagNoAutoBr' => 'ul,ol',
        'cfgSetTagChilds' => '[["ul",["li"],false,true],["ol",["li"],false,true]]',
        'cfgSetTagParamDefault' => '[]',
        'cfgSetTagParamsRequired' => '{}',
        'cfgSetTagNoTypography' => '',
        'cfgSetTagPreformatted' => '',
        'cfgSetTagShort' => 'br'
    ]);
}

return $fields;
Евгений Шеронов
04 июня 2020, 03:29
+2
Вот я тоже задавался вопросом «а зачем?».

Судя по github экономией тут не пахнет)
В результате пары недель ...
Стоимость пары недель любого разработчика — это годы для хостинга c MySQL)

Мало того, что схему нужно добавлять, так ещё в дополнениях бывают подготовленные запросы не через XPDO, и вполне может быть отличный синтаксис запросов. Так что и код править может придётся.
По мне такой путь точно в никуда.

Я бы ещё понял использование SQLite на сайте для какого-то внутреннего локального использования, где будет только 1 человек пользоваться сайтом.

Вот например, поддержка PostgreSQL принесла бы больше пользы. Но здесь будет проблема в том, что shared-хостингов с постгресом сильно меньше, следовательно поставить не у каждого получится.
Ну и некоторые решения могли бы сильно от БД зависеть, например от типов данных.

Так что сейчас даже хорошо, что в MODX все используют MySQL, всё легко перенести, не нужно вникать в другие БД, где их искать, как подключаться и т.д.

Хотя и с MySQL то можно много улучшать, добавлять поддержку новых типов, массивы, JSON.
Но под это дело простые шаред хостинги уже не успевают обновлять MySQL, но это уже другая тема)
Евгений Шеронов
18 мая 2020, 12:14
0
Действительно, а я подумал, что все файлы имеют такой же вид, как в статье описан пример конфига.

Ну теперь это очевидно для всех, что в тех файлах настроек должен быть return, чтобы способ сработал.
Но даже если там будут переменные, они также включатся в эту область.
Евгений Шеронов
18 мая 2020, 11:52
0
Только так работать не должно, потому что require возвращает true или падает с ошибкой.

А переменные, определённые в файле становятся доступны в текущей области действия.
Если же массив с настройками там называется $config_options, то получать его лучше так:
//...
require $file;
if (isset($config_options) && is_array($config_options)) {
    $modx->config = array_merge($modx->config, $config_options);
}
//...
Евгений Шеронов
11 мая 2020, 20:43
1
0
Я не специально проигнорировал сообщение. Но ответить лучше поздно, чем никогда)

По сути это делается через sfMenu просто с указанием параметров &parents=`[[*id]]` и &mincount=`1`.
Там ещё можно учитывать относительность через параметр &relative=`1` (тогда ссылки будут каждый раз уходить в глубину от выбранного параметра, если такие правила есть).

Но, конечно, как и на DNS, это просто популярные фильтры для этой страницы, и желательно, чтобы они были на странице. Их можно скрыть стилями или передать немного скрипты, чтобы проставленное значение сохранялось для пагинации.

А как сделать фильтры для mSearch2 особо разницы нет, хоть ТВ поля, хоть опции, хоть через Tagger.
Евгений Шеронов
21 апреля 2020, 16:59
0
Для разработки прям то что надо.

А как себя ведёт БД в докере на production?
Пока только видел, что так совсем не стоит делать по ряду причин.
И в этом случае, если контейнер Docker с БД упадёт, то все данные до последнего сохранённого дампа тоже пропадут?