Николай Савин

Николай Савин

Был в сети 29 июня 2026, 12:35
Заказы принимаю
Привет.
Будет ли поддержка modx3?
Так MS3 целиком предназначен для MODX3. Я не занимаюсь развитием платформы для MODX2.
Продукты будут в отдельной таблице?
Тут ничего не изменилось. Поля товара как хранились в ms2_products так и хранятся.
Миграции phinx — а xpdo объекты будут работать
А как ты их между собой связал? Это же разные сущности.
Если вопрос о том, как новые поля попадут в xpdo модель — то там наш старый привычный еще из ms2 способ, который на лету обновляет $meta['map']

Цепочка загрузки:
  • 1. OnMODXInit → $ms3->loadMap()
  • 2. MiniShop3::loadMap() → $this->extraFields->loadMap()
  • 3. ExtraFields::loadMap() → загружает ms3_extra_fields (active=1)
  • 4. ExtraFields::getFieldInfo() → формирует метаданные
  • 5. ExtraFields::addFieldToMap() → МОДИФИЦИРУЕТ $modx->map[$class] ← ВОТ ГДЕ МАГИЯ!
  • 6. xPDO видит новые поля как нативные
Если придираться, то:
Тут я бы разделил ответ
1. Репозиторий — это паттерн. Нет четких правил по его использованию или обязательств его использовать. Так что каждый волен делать так, как видит. Вот Laravel до пятой версии вообще всю логику внутри моделей тягал и ничего.
2. На практике, насколько я видел как пишут другие, сервис и репозиторий по сути своей одно и тоже. Их задача разгрузить контроллер, вынести логику в отдельный контейнер.

Я вижу так.
Контроллер принимает запрос от API и отдает ответ. На этом все. Его зона ответственности Request-Магия-Response.
Репозиторий и\или Service — логика. Здесь идет разбор запроса, обращения к DB, построение ответа. Задача сервиса — подготовить ответ согласно запроса.
Model — исключительно работа с базой. Ее задача сходит в базу и выполнить поставленную задачу.
Нет ощущения. что дело не в неработающих примерах, как вы это подаете?
Для начала прекращайте смешивать синтаксис — у вас проблемы из-за этого, в том числе. Напишите все нормально либо в fenom, либо в MODX синтаксисе. Это разные технологии, они по разному устроены и работают.
Продолжаю эксперименты с AI контентом. Для сравнения подключил DeepSeek к нашем дайджесту. Как по мне, получилось намного лучше, сравнение с Yandex GPT наглядное.

@Aleksandr Huz на этот раз тебя не забыли.
DeepSeek конечно отсыпал знатно и всему сообществу, и мне за минишоп и отдельным товарищам
Твой код верный. Должен работать. Я бы его немного вот так переделал, чтобы фильтровать GET и проверить существование заголовка HTTP_ACCEPT_LANGUAGE
<?php
  /* Запускаем плагин только на фронтенде и с включенными sef-url */
  if ($modx->context->key == 'mgr' || !$modx->getOption('friendly_urls') || $modx->event->name != 'OnHandleRequest') {
      return;
  }

HTTP_ACCEPT_LANGUAGE есть в 95% случаев, но обычно не гарантия что он обязательно будет
  /* Разрешенные контексты */
  $allowedContexts = ['en' => 'en', 'ru' => 'web'];

  /* Проверяем GET-параметр cultureKey */
  $cultureKey = filter_input(INPUT_GET, 'cultureKey', FILTER_SANITIZE_STRING);
  if (!empty($cultureKey)) {
      $targetContext = isset($allowedContexts[$cultureKey]) ? $allowedContexts[$cultureKey] : 'web';
      $modx->switchContext($targetContext);
  } else {
      /* Если cultureKey не указан, проверяем язык браузера */
      $acceptLanguage = $_SERVER['HTTP_ACCEPT_LANGUAGE'] ?? '';
      if (!empty($acceptLanguage)) {
          $browserLang = strtolower(substr($acceptLanguage, 0, 2));
          if ($browserLang === 'en') {
              $modx->switchContext('en');
          }
      }
      /* В остальных случаях оставляем текущий контекст */
  }
Алексей скромничает, он за эту неделю довольно много работы выполнил, закрыв большинство известных нам багов. Мы с @Иван Бочкарев от лица сообщества выплатили Алексею скромные 10 000 рублей вознаграждения из фонда, накопленного за счет ваших пожертвований друзья!
То, что ты нашел в принципе актуально. Так и делают.
Попробуй вот такой конфиг

server {
    listen 80;
    server_name example.com www.example.com;
    root /home/sites/example.com;
    index index.php;
    client_max_body_size 30M;
    
    # Новый блок для статических файлов с кешированием
    location ~* \.(jpg|jpeg|gif|png|svg|ico|pdf|mp4|webm|ogg|mp3|wav|ttf|otf|woff|woff2|eot)$ {
        # Срок действия кеша в браузере (аналог Expires в Apache)
        expires 1M; # access plus 1 month
        
        # Заголовок для указания, что кеш публичный (аналог Header append Cache-Control "public")
        add_header Cache-Control "public";
    }

    # Отдельный блок для CSS, JS (у них у вас срок больше)
    location ~* \.(css|js)$ {
        expires 2M; # access plus 2 months
        add_header Cache-Control "public";
    }

    location / {
        root /home/sites/example.com;
        if (!-e $request_filename) {
            rewrite ^/(.*)$ /index.php?q=$1 last;
        }
    }
    
    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(.*)$;
        fastcgi_pass   127.0.0.1:9000;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        include fastcgi_params;
        fastcgi_ignore_client_abort on;
        fastcgi_param  SERVER_NAME $http_host;
    }

    # Правило для запрета доступа к файлам Apache
    location ~ /\.ht {
        deny  all;
    }
}
Так миниатюры создает не компонент, а подключенная библиотека Glide 3.0.1 — Она либо поддерживает работу с PDF, либо нет (я не смотрел)
Соответственно автор может только своевременно обновлять либу, и никак не в силах предсказывать ее дальнейшее развитие
Основана на лучшей из существующих PHP библиотек (насколько я знаю) Intervention Image — за это прям мое почтение. Почти наверняка будут вопросы — а почему бы не использовать уже встроенную в MODX либу phpthumb, зачем на ровном месте тащить что-то другое. Таков современный мир — микросервисы решают.