Как модернизировать фильтр поля applyFilter?

InstantCMS 2.X
#1 16 марта 2021 в 11:47
Создал свое поле, которое хранит адреса в формате json.
Например:
{"country":"Россия","city":"Москва","street":"пр-т Мира"}
Что нужно изменить в
  1. public function applyFilter($model, $value) {
  2. return $model->filterLike($this->name, "%{$value}%");
  3. }
чтобы фильтр искал только по адресу и не цеплял "country","city" и т.д.?
#2 16 марта 2021 в 12:47
По идеи, никак, я думаю. Можно получить поле с json, преобразовать json в array и вывести в массив нужные значения.
#3 16 марта 2021 в 12:49
Если это всё {"country":"Россия","city":"Москва","street":"пр-т Мира"} хранится в одной ячейке в БД, то никак. В одной ячейке можно фильтровать по "Содержит", "Не содержит", либо писать свой фильтр с JSON_EXTRACT dev.mysql.com/doc/refman/8.0/en/json-search-functions.html#function_json-extract.
Попробуйте это, хоть я и не уверен что сработает
  1. return $model->filterLike(JSON_EXTRACT($this->name , '$.street'), "%{$value}%");
#4 16 марта 2021 в 13:03
Так пойдёт?
  1.  
  2. public function applyFilter($model, $value) {
  3. return $model->filterLike($this->name, '%"street":"'.$value.'"%');
  4. }
  5.  
#5 16 марта 2021 в 15:35
  1.  
  2. $my_json = '{"country":"Россия","city":"Москва","street":"пр-т Мира"}';
  3. $my_json = json_decode($my_json,true); //Array ( [country] => Россия [city] => Москва [street] => пр-т Мира )
  4.  
  5. foreach($my_json as $key =>$val){
  6. $adreses = $val;
  7. echo $adreses; // Россия Москва пр-т Мира
  8. }
#6 16 марта 2021 в 17:56


Если это всё {"country":"Россия","city":"Москва","street":"пр-т Мира"} хранится в одной ячейке в БД, то никак. В одной ячейке можно фильтровать по "Содержит", "Не содержит", либо писать свой фильтр с JSON_EXTRACT dev.mysql.com/doc/refman/8.0/en/json-search-functions.html#function_json-extract.
Попробуйте это, хоть я и не уверен что сработает

  1. return $model->filterLike(JSON_EXTRACT($this->name , '$.street'), "%{$value}%");

Loadырь
Не сработало. JSON_EXTRACT думаю помог бы, но куда его прикрутить?
Может найдутся добрые гении и сделают тип поля для работы с json данными, в том числе и в фильтре?
Вроде вещь нужная много для чего )
#7 16 марта 2021 в 19:34

Может найдутся добрые гении и сделают тип поля для работы с json данными, в том числе и в фильтре?

@torrius
Гениев-то полно, добрых — чуть меньше, но сделать может каждый. Если вам нужен поиск чисто по "улице", то я бы в это поле сохранял значение улицы, а вот всё остальное уже закинул в денормальное поле (поле с суффиксом _cache). Хоть оно и не для это предназначено.

Попробуйте тогда этот фильтр
  1. $this->filter("JSON_EXTRACT(`" . $this->name . "` , '$.street') LIKE '%" . $value . "%';");
#8 16 марта 2021 в 20:16


Гениев-то полно, добрых — чуть меньше, но сделать может каждый. Если вам нужен поиск чисто по "улице", то я бы в это поле сохранял значение улицы, а вот всё остальное уже закинул в денормальное поле (поле с суффиксом _cache). Хоть оно и не для это предназначено.

Попробуйте тогда этот фильтр

  1. $this->filter("JSON_EXTRACT(`" . $this->name . "` , '$.street') LIKE '%" . $value . "%';");

Loadырь
Это тоже не работает. Включается гифка бесконечной загрузки. Но никаких ошибок нигде не выскакивает.
Пробовал функцию JSON_EXTRACT в phpmyadmin, там выборка строк норм работает.
SELECT * FROM cms_con_board WHERE address->"$.street" = 'пр-т Мира';
Да, мне достаточно искать по значениям в одном ключе, например $.street.
Где можно посмотреть про "денормальное поле (поле с суффиксом _cache)" — что это такое?
Как вариант можно попробовать.
#9 17 марта 2021 в 08:00

Где можно посмотреть про "денормальное поле (поле с суффиксом _cache)" — что это такое?

@torrius
В доках об этом сильно умалчивается, но посмотрите как сделано поле "Местоположение" github.com/instantsoft/icms2/blob/master/system/fields/city.php#L13
Там идентификатор по которому работает само поле хранится в одной ячейке, а строковое значение этого поля, которое выводится на сайте — в другой ячейке. Ячеек может быть только две — основная и "ненормальная". Больше нельзя добавить в этом случае.

Гифка ничего вам не скажет. Надо включать режим отладки и смотреть в консоли браузера возможные ошибки.
В этом запросе возможно были запиханы лишние кавычки.
  1. $this->filter("JSON_EXTRACT(" . $this->name . ", '$.street') LIKE '%" . $value . "%';");
Возможно и тут есть либо лишние, либо не того формата кавычки. Пробуйте разные варианты.
#10 17 марта 2021 в 15:30


Там идентификатор по которому работает само поле хранится в одной ячейке, а строковое значение этого поля, которое выводится на сайте — в другой ячейке. Ячеек может быть только две — основная и "ненормальная". Больше нельзя добавить в этом случае.

Loadырь
Создал простейшее поле с содержимым в test.php
  1. class fieldTest extends cmsFormField {
  2. public $title = 'TEST';
  3. public $sql = 'varchar(500) NULL DEFAULT NULL';
  4. public $cache_sql = 'varchar(500) NULL DEFAULT NULL';
  5. public $filter_type = 'str';
  6. public $var_type = 'string';
  7. public $is_denormalization = true;
  8.  
  9. public function parse($value){
  10. return 'Cache: ' . $this->item[$this->getDenormalName()] . 'Test: ' . $this->item[$this->name];
  11. }
  12. }
в test.tpl.php
  1. echo html_input('text', $field->name, $field->item[$field->name], ['placeholder'=>'test']);
  2. echo html_input('text', $field->getDenormalName(), $field->item[$field->getDenormalName()], ['placeholder'=>'test_cache']);
Обычное поле пишет в базу вводимые значения, денорм — пишет NULL.
Если в самой базе поменять значение денорм-поля, то оно выводится в записи. Но если попробовать снова ввести данные в поле и сохранить, то в базе опять — NULL.
Что-то нужно сделать, чтобы в базу отправлялись вводимые значения из денорм-поля. Но вот что? )
Вы не можете отвечать в этой теме.
Войдите или зарегистрируйтесь, чтобы писать на форуме.
Используя этот сайт, вы соглашаетесь с тем, что мы используем файлы cookie.