Версия — 2.18.0
ICMS установлен на локальном сервере — Open Server + на домашнем сервере.
Столкнулся с проблемой.
В админке, если зайти в каталог дополнений, то список дополнений не загружается. Выводит сообщение — «По вашему запросу нет дополнений».
После некоторых манипуляций понял причину — блокировка ответов с сервера ICMS.
На запрос прилетает только несколько килобайт ответа и дальше блокируется.
Причем если на компе с локальным сервером включить ВПН, то все норм грузится.
Кто-нибудь замечал подобное? в чем может быть причина?
Сервер дополнений InstantCMS в «черном списке»?
Andrew Lutz
Andrew Lutz, так экшн, по факту, такой же метод контроллер. Вам необязательно его выносить в отдельный файл, можно прямо внутри контроллера писать его как
public function actionSubcatsView(){ dump('Список категорий'); }Вот про это в документации docs.instantcms.ru/dev/controllers/actions
Просто вы же в виджете хотите потом эту json строку разбирать, подготавливать и отправлять в шаблон виджета.
Вынесите подготовку чистых данных в сам контроллер. В виджет отдавайте чистые данные, а экшном — в формате json… Кода в сравнении с вашим вариантом почти не добавится, зато поддерживать такой вариант в дальнейшем будет сильно проще.
Но я не настаиваю. Просто делюсь мнением.
Хм… а ведь да, точно )
Благодарю за мудрый совет )
Мне еще многому тут учиться.
Если я правильно понял, то вроде вот:
return $this->cms_template->render('шаблон_из_папки_тэмплэйт', [ 'test' => 'Ok Ok Ok' ]);и в шаблоне будет доступно $test
Да, если создать в папке шаблона файл например /content/get_action.tpl.php то можно вывести в нем $test.
Но как это сделать в шаблоне виджета? или это надо как-то сделать потом уже?
Я смотрел на примере стандартного файла category_view.tpl.php в папке контроллера content. В него тоже данные попадают из одноименного экшена.
Вот только как они потом передаются в общий виджет /content/widget/template.tpl.php — для меня загадка.
$controller = cmsCore::getController('content'); dump($controller->runAction('subcats_view'));Действительно работает! это даже радует )
Только теперь не понятны предостережения — «имхо так делать не стоит. Сделайте отдельный компонент, в нем нужный метод для отдачи данных массива ». Это действительно важно?
А то в будущем фантазирую движок превратить в подобие SPA. Для этого думаю всю логику можно переваривать в экшенах, отдавая чистый JSON либо внутрь, либо аяксу. В зависимости кому нужно отдать страницу — пользователю или поисковику.
Не могу никак разобраться...
Сделал тестовый экшен
content/actions/subcats_view.php
<?php class actionContentSubcatsView extends cmsAction { public function run() { return $this->cms_template->renderJSON([ 'test' => 'Ok Ok Ok' ]); } }
Далее написал пустой тестовый виджет, в шаблоне которого
<script> ;(async function(){ let resp = await fetch('/content/subcats_view'); let json = await resp.json(); console.log(json.test); }()); </script>
В консоли как и полагается выводится 'Ok Ok Ok'. Работает.
Данные можно отрендерить JS-ом и вывести где-то на странице.
Теперь вопрос.
Как мне запросить и получить данные того же экшена, но без JS?
То есть может есть метод, который сможет вернуть данные экшена прямо в шаблон (например в шаблон любого виджета), чтобы отрендерить с помощью php?
Очень буду признателен за совет.
Теперь общий принцип понятен )
Andrew Lutz, делал компонент для вывода второго описания в категории. Поправьте компонент под себя instantcms.ru/forum/razdelit-opisanie-kategorii-na-verhnyuyu-i-nizhnyuyu-chasti.html#post-360858
Да, почти то, что надо! Спасибо, очень помогло!
А то хотелось понять как вообще в принципе добавлять свои поля в настройки категории.
И выводить затем: в карточку категории в списке категорий и в страницу самой категории.
В дефолтном варианте очень скудный набор — заголовок, описание, обложка и все.
Добавил еще одно поле для вывода иконки категории.
Вроде все работает.
Но спрошу на всякий случай — все ли правильно или есть более изящные решения, если нужно будет по-больше полей?
content_cat_form.php
if (!$model->db->isFieldExists($table_name, 'description_extended')) { $model->db->query("ALTER TABLE `cms_$table_name` ADD `description_extended` TEXT NULL DEFAULT NULL AFTER `description`;"); } if (!$model->db->isFieldExists($table_name, 'icon_title')) { $model->db->query("ALTER TABLE `cms_$table_name` ADD `icon_title` TEXT NULL DEFAULT NULL AFTER `title`;"); } $form->addField($fieldset_ids[0], new fieldHtml('description_extended', [ 'title' => 'Расширенное описание категории', 'can_multilanguage' => true, 'multilanguage_params' => [ 'is_table_field' => true, 'table' => $table_name ] ])); $form->addField($fieldset_ids[0], new fieldString('icon_title', [ 'title' => 'Название иконки категории' ] ) );
Как добавить свое дополнительное поле на страницу «Редактировать категорию» и вывести его потом в шаблоне страницы категории?
Нашел нужный файл /system/content/forms/form_category.php, добавил поле
new fieldCheckbox('test', [ 'title' => 'test' ]),
Поле выводится на странице настройки категории, но введенные значения не сохраняется.
Буду благодарен, если кто подскажет что-куда прописать, чтобы:
1 Значения сохранялись.
2 Значения можно было вывести в шаблоне категорий (/templates/{templateName}/controllers/content/category_view.tpl.php).
В виджетах как-то автоматом все получается. А тут я че-то не понимать ))
Подскажите, как реализовать сохранение контента в поле-редакторе текста, например:
— после случайного закрытия вкладки браузера, ее перезагрузки
— после неудачного сохранения (допустим с интернетом что-то)
Еще неплохо бы сделать отдельную кнопку для сохранения без перезагрузки страницы и без удаления данных текстовой формы.
Есть идеи у кого?
Я попробовал это сделать с \system\controllers\content\widgets\list\widget.phpВсунете виджет в контроллер content, тогда заработает.
Никаких изменений его поведения не обнаружил.
Скорее как здесь — move.ru, ну или как на Авито, в Циане и т.д. Доска объяв недвижимости специфична, в отличие от простых объяв. Нужно активно работать с адресами и картой. Пока в инстанте никто еще не реализовал этот функционал, а зря. Приходится самому делать, хоть я и не прогер )Посмотрел видео и думаю вы хотите сделать что-то такое prefitchi.ru/hotels ?
Уже обошел ) Ключ у меня используется только единожды при добавлении объявления. Там идет проверка введенного адреса и если он есть, то вычисляются координаты. Которые потом, при просмотре списка и записи контента выводятся в отдельном шаблоне уже без ключа — он им не нужен.Затем вы столкнетесь с ограничениями Яндекса на карте (25000 запросов в сутки и эта цифра не такая и большая как многим кажется). И это тоже вам надо будет как-то обходить.
Так что в день можно загружать минимум 5-10 тыс объяв. Сам просмотр их на сайте — "бесплатный" ))
Да, по идее надо, но думаю пока обойдусь. Так как не планирую размещать тысячи объяв. А для ускорения, можно выводить только минимальную информацию — заголовок, цена и координаты. Остальное можно подгружать (фото и прочее) аяксом при клике пользователем по метке на карте. (Уже работает).Из-за этих ограничений потом вам надо будет решить задачу "Как вывести на карте только те записи, которые входят в область карты при ее прокрутке?".
Да, все верно.вся фишка в том, что категория должна автоматически определяться и записи должны фильтроваться по фильтру набранному пользователем на сайте.
Сегодня именно этот файл исследовал. Чувствую, что в нем разгадка. Но не могу понять (нет знаний) как это все втыкнуть в виджет? )В типе контента список формируется тут github.com/instantsoft/icms2/blob/master/system/controllers/content/frontend.php#L217. Там можете увидеть и как фильтрация сделана из фильтра.
Спасибо за помощь! Но что-то не получается.
Можно написать всё что угодно. Но много зависит, где вы делаете свой виджет. В content, в каком-то другом контроллере или вообще без контроллера.
Тут github.com/instantsoft/icms2/blob/master/system/controllers/content/widgets/list/widget.php есть пример того, что можно написать в файле widget.php. В вашем случае надо будет определить текущую категорию через
и задать ее вместо этого блока github.com/instantsoft/icms2/blob/master/system/controllers/content/widgets/list/widget.php#L54
getCategoryBySLUG($ctype_name, $slug)
Виджет пока без контроллера. Но потом, может, запихну в контроллер контента, или создам отдельный.
По сути, мне надо получить то же, что и выводится в стандартном списке контента, только без пагинации.
Записал на видео, может понятней будет вопрос? )
youtu.be/MHvygibNamQ
Люди, помогите? )
Делаю виджет.
Виджет показывается на страницах списка контента.
В нем нужно вывести список значений полей записей контента, допустим, — заголовки (title).
Например, мы находимся на странице списка объявлений в категории — Недвижимость -> Квартиры, отфильтрованного по цене.
В виджете нужно вывести весь отфильтрованный список заголовков из текущей категории.
Что можно написать в файле widget.php, чтобы записать этот список в переменную для передачи в шаблон?
Виджет показывается на страницах списка контента.
В нем нужно вывести список значений полей записей контента, допустим, — заголовки (title).
Например, мы находимся на странице списка объявлений в категории — Недвижимость -> Квартиры, отфильтрованного по цене.
В виджете нужно вывести весь отфильтрованный список заголовков из текущей категории.
Что можно написать в файле widget.php, чтобы записать этот список в переменную для передачи в шаблон?
Создал простейшее поле с содержимым в test.php
Там идентификатор по которому работает само поле хранится в одной ячейке, а строковое значение этого поля, которое выводится на сайте — в другой ячейке. Ячеек может быть только две — основная и "ненормальная". Больше нельзя добавить в этом случае.
class fieldTest extends cmsFormField { public $title = 'TEST'; public $sql = 'varchar(500) NULL DEFAULT NULL'; public $cache_sql = 'varchar(500) NULL DEFAULT NULL'; public $filter_type = 'str'; public $var_type = 'string'; public $is_denormalization = true; public function parse($value){ return 'Cache: ' . $this->item[$this->getDenormalName()] . 'Test: ' . $this->item[$this->name]; } }
echo html_input('text', $field->name, $field->item[$field->name], ['placeholder'=>'test']); echo html_input('text', $field->getDenormalName(), $field->item[$field->getDenormalName()], ['placeholder'=>'test_cache']);
Если в самой базе поменять значение денорм-поля, то оно выводится в записи. Но если попробовать снова ввести данные в поле и сохранить, то в базе опять — NULL.
Что-то нужно сделать, чтобы в базу отправлялись вводимые значения из денорм-поля. Но вот что? )
Это тоже не работает. Включается гифка бесконечной загрузки. Но никаких ошибок нигде не выскакивает.
Гениев-то полно, добрых — чуть меньше, но сделать может каждый. Если вам нужен поиск чисто по "улице", то я бы в это поле сохранял значение улицы, а вот всё остальное уже закинул в денормальное поле (поле с суффиксом _cache). Хоть оно и не для это предназначено.
Попробуйте тогда этот фильтр
$this->filter("JSON_EXTRACT(`" . $this->name . "` , '$.street') LIKE '%" . $value . "%';");
Пробовал функцию JSON_EXTRACT в phpmyadmin, там выборка строк норм работает.
SELECT * FROM cms_con_board WHERE address->"$.street" = 'пр-т Мира';
Да, мне достаточно искать по значениям в одном ключе, например $.street.
Где можно посмотреть про "денормальное поле (поле с суффиксом _cache)" — что это такое?
Как вариант можно попробовать.
Не сработало. JSON_EXTRACT думаю помог бы, но куда его прикрутить?
Если это всё {"country":"Россия","city":"Москва","street":"пр-т Мира"} хранится в одной ячейке в БД, то никак. В одной ячейке можно фильтровать по "Содержит", "Не содержит", либо писать свой фильтр с JSON_EXTRACT dev.mysql.com/doc/refman/8.0/en/json-search-functions.html#function_json-extract.
Попробуйте это, хоть я и не уверен что сработает
return $model->filterLike(JSON_EXTRACT($this->name , '$.street'), "%{$value}%");
Может найдутся добрые гении и сделают тип поля для работы с json данными, в том числе и в фильтре?
Вроде вещь нужная много для чего )