Принцип создания veppa поиска

PHP
Как уже и писалось ранее в Veppa нет поиска, и некоторым любителям veppa очень сильно его не хватает.
Тема со старым обсуждение поиска на стороннем коде
Собственный поиск по сайту.
Уже прошло много времени после моего переезда на самопис, но все же я буду помогать веповцам в реализации той или иной возможности, а так же поддерживать русскоязычное сообщество veppa. В этой теме я решил поделится поделится своими старыми наработками и объяснить что к чему.

Логика поиск очень простая, к тому же есть аналогичный код в двиге, это поиск по тегам
[CODE]tags/ТЕГ[/CODE]
Грубо говоря вам это и нужно, только нужно изменить каталог в urle и переделать sql запрос, точнее два sql запроса, а так же вывести сообщение если ничего не найдено, а не выводить ошибку 404 если запрос вернул пустой результат. Кстати не забывает править код веппы на отсутствие ошибки 404, где я о ней писал, попросту забыта данная проверка и там где нужно выводит ошибку 404, veppa отдает заголовок сервера 200 с вобщем то пустой страницей, которых может быть тысячи и это для ПС очень не хорошо.

Первым делом нужно покопаться в index.php и найти следующую строку
'tags/:any' => '/index/tag/$1',

Принцип работы роутера очень прост, из ссылки следует
/index/tag/$1

index — это наш IndexController.php который обращается к функции
tag — функция в IndexController которая принимает гет запрос
$1 — это ваше ключевое слово при запросе к примеру
/index/tag/пейзаж

Думаю тут все понятно.
Само собой можно и саму функцию tag переделать так чтобы она работала как полноценный поиск, но лучше все же сделать для поиска отдельную функцию.

[B]Что же нам нужно?[/B]
Первым делом скопировать функцию
function tag

далее
переименовать скопированную функцию Tag к примеру на tagsearch и немного изменить ее содержание, все же не по тегам ищем!
public function tagsearch($tag, $order='', $page=1)
    {
        $tag = trim(rawurldecode($tag));

        // Выполняем выборку при условии что слово длиннее 3-х символов
        if (strlen($tag) > '3')
        {
            // SQL запрос поиска с like по двум полям таблицы
            $tag_object = Wallpaper::findOneFrom("Wallpaper", "(tags like '%{$tag}%') OR (name like '%{$tag}%')", array($tag));
            // Похожий запрос на предыдущий, но он выводить только колличество строк
            $total = Wallpaper::getSearchByTagIdCount($tag);

            // $order это сортировка /l/ or /d/ or /r/ or /h/
            if ($order)
            {
                // Передаем данные в функцию _searchOrder если сортировка
                return $this->_searchOrder($tag, $order, $page, $total, $tag_object, $where);
            }
            // Если $order пустой и $total содержит сумму строк при выборке, то значит это первая страница и так же передаем данные в _searchOrder
            if ($total)
            {
                return $this->_searchOrder($tag, 'l', 1, $total, $tag_object, $where);
            }

            // Чтобы вывести тег добавляем его в массив
            $vars['tag'] = $tag;

            // Если $tag_object пуст
            if ( empty($tag_object) )
            {
                $this->setMeta('title', __('По запросу "{name}" ничего не найдено!', array('{name}' => $tag)));
            }
            else
            {
                $this->setMeta('title', __('{name} на рабочий стол', array('{name}' => $tag)));
            }

        }
        else // если $tag меньше трех символов
        {
            $this->setMeta('title', __('Извините, но запрос слишком короткий. Введите в поиск от 4-х символов'));
        }

        // Формируем отображение страницы (просто шаблон)
        $this->display('index/list', $vars);
    }

Функция выше принимает, обрабатывает и передает все данные в функцию _searchOrder при удачном результате, ну а _searchOrder уже формируем все что нам необходимо вывести, но об этом чуть позже, для начала откроем модель Wallpaper.php и создадим новую функцию подсчета количества записей в таблице
function getSearchByTagIdCount($id)
    {
        $key_array = explode(' ', $id);

        // ищем по словам
        $where = "w.tags like '%{$key_array[0]}%' and w.tags like '%{$key_array[1]}%' and w.tags like '%{$key_array[2]}%' and w.tags like '%{$key_array[3]}%' and w.tags like '%{$key_array[4]}%'";
        
        $sql = "SELECT count(w.id) as total
                        FROM " . TABLE_PREFIX . "wallpaper w
                        WHERE $where";
        $num = Record::query($sql, array($id));

        return $num[0]->total;
    }


Теперь вернемся к функции _searchOrder она аналогична функции _tagOrder
private function _searchOrder($tag, $order='', $page=1, $total, $tag_object, $where)
    {
        // page and limit
        if ($page < 1)
        {
            $page = 1;
        }
        // Дял пагинации
        $st = ($page - 1) * self::$num;

        // paginator
        $total_pages = ceil($total / self::$num;
        // Tag::url_search - это просто формирование ссылки, ничего серьезно и чуть позже об этом
        $url = Tag::url_search($tag, $order, '{page}');
        $vars['paginator'] = Paginator::render($page, $total_pages, $url, true);
        $vars['order_links'] = $this->_orderLinks($order, Tag::url_search($tag));

        // get wallpapers
        switch ($order)
        {
            case 'l':
                $order_sql = 'added_at';
                $this->setMeta('title', __('{name} - последние', array('{name}' => mb_convert_case($tag, MB_CASE_TITLE, "UTF-8"))));
                break;
            case 'h':
                $order_sql = 'week';
                $this->setMeta('title', __('{name} - интересные', array('{name}' => mb_convert_case($tag, MB_CASE_TITLE, "UTF-8"))));
                break;
            case 'd':
                $order_sql = 'dwn';
                $this->setMeta('title', __('{name - качают', array('{name}' => mb_convert_case($tag, MB_CASE_TITLE, "UTF-8"))));
                break;
            case 'r':
                $order_sql = 'rank';
                $this->setMeta('title', __('{name} - лучшие', array('{name}' => mb_convert_case($tag, MB_CASE_TITLE, "UTF-8"))));
                break;
            default:
                page_not_found();
        }
        // get latest wallpapers
        $vars['wallpapers'] = Wallpaper::getSearchByTagId($tag, $order_sql, $st, self::$num);
        // todo add tags
        // Wallpaper::appendObject($vars['wallpapers'],'id',);

        $this->_addCommonListVars($vars);

        $this->display('index/list', $vars);
    }


Тут думаю и объяснять ничего не нужно, так как функция аналогична _tagOrder за исключением Tag::url_search
Открываем Tag.php
и пишем новую функцию
static function url_search($tag,$order='',$page=1)
    {
        return get_url('search/'.mb_strtolower($tag, 'UTF-8').'/'.($order?$order.'/'.$page.'/':''));
    }

Ну а теперь нам нужно добавить строчку в роутер (index.php)
После
'/tag/:any' => '/index/tag/$1',

вставить
'/search/:any/' => '/index/tagsearch/$1',

И попробовать произвести поиск по сайту
/search/пейзажи
Вот собственно и все. Надеюсь что помог кому то…

1 комментарий

avatar
Ошибки могут быть, я буквально вырезал из старого двига данный код, но там есть и другой код в связке и пришлось выпиливать некоторые куски кода для того чтобы не модернизировать вол двига veppa
  • admin
  • 0
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.