• Здравствуйте. Давно пытаюсь найти проекты на wp (даже сказал бы темы с базой) в открытом доступ, которые имеют уже много не стандартных решений: свои таблицы для постов, изменение MAIN_QUERY Запросов, итд.
    Хотелось бы посмотреть как более опытные разработчики реализуют эти вещи. Или может какие-нибудь ресурсы есть где о таких вещах говорят?

Просмотр 15 ответов — с 1 по 15 (всего 17)
  • в открытом доступе это исходники сайтов что ли?

    Да исходники, или может советы по реализации чего то CUSTOM на wp. Просто не видя чужих исходников, сложно оценить делаешь ты верно или нет.

    Лучше ориентируйтесь на Кодекс, потому что в темах и плагинах, даже именитых и популярных, порой встречаются такие ужасы, что хочется их развидеть 🙂

    И не стесняйтесь спрашивать! Готовый код тут могут и не дать, но правильное направление (и даже не одно!) укажут.

    Меня очень сильно тревожит момент что все мета данные о посте находятся в wp_postmeta и когда я делаю выборку в каталоге товаров по типу, странам, салонам, брендам итд, получается огромный sql запрос, потому что все хранится не в одной таблице в строчку для данного POST_TYPE а в таблице post_meta в столбик. Вместо 1 inner join мы получаем 3-5.
    Из-за этого мой сайт стал грузиться очень долго. Порядка 1.5-3 сек за запрос (Это на 4 ядерном сервере, с 8гб озу).
    Мы используем плагин ACF pro для создания meta полей к постам. Из-за того что выборки очень долгие.
    Я принял решение Создать свои отдельные таблицы для post_type salon, product, product_salon. И реплицировать мета данные при сохранении этих ACF field (на хуки повесил).

    Что вы скажите по этому поводу. Целесообразное решение?

    • Ответ изменён 7 лет, 10 месяцев назад пользователем Andrew Pisarevsky.

    Меня очень сильно тревожит момент что все мета данные о посте находятся в wp_postmeta

    Строго говоря, существует два подхода к хранению метаданных.
    1. вертикальный — как у WP — легко создать, легко получить, но очень тяжело сделать выборку.
    2. горизонтальный — динамическая таблица с отдельным столбцом для каждого ключа. Легко делать выборки, но каждый новый ключ — тяжеленный ALTER TABLE.

    Я считаю, что если количество ключей для задачи заранее известно и не слишком велико и требуются выборки по комбинации их значений, то лучше создать для них «горизонтальную» таблицу. Остальные метаданные могут спокойненько лежать в post_meta. Я так делал каталог продуктов: формальные атрибуты продуктов в отдельной таблице, остальное — штатно в postmeta.

    А вот в целесообразности использования ACF я не уверен. По-моему, это просто лишняя нагрузка.

    Я так делал каталог продуктов: формальные атрибуты продуктов в отдельной таблице, остальное — штатно в postmeta.

    Я так понимаю вы создали свою произвольную таблицу? А обращались вы к ней с помощью $wpdb ?
    У нас программист который писал техническое задание категорически запрещает использовать $wpdb ( «говорит что это прямые запросы в БД,и использовать ее нельзя» ), требует все делать через WP_QUERY и через фильтры

    add_filter('posts_fields', 'tt_posts_fields');
    add_filter('posts_join', 'tt_posts_join');
    add_filter('posts_where', 'tt_posts_where');
    add_filter('posts_orderby', 'tt_posts_orderby');
    add_filter( 'posts_groupby', 'tt_posts_groupby' );

    В итоге мы получаем не читаемый код выборки на страницах

        global $mam_global_join, $mam_global_where;
        $mam_global_join = '
            INNER JOIN wp_postmeta AS pm2 ON ( wp_postmeta.post_id = pm2.post_id ) 
            INNER JOIN wp_postmeta AS pm3 ON ( pm2.meta_value = pm3.post_id ) 
        ';
        $mam_global_where = '
            AND pm2.meta_key =  \'tt_sp_salon\'
            AND pm3.meta_key =  \'tt_salon_region\'
            AND pm3.meta_value = ' . $tt_currnet_region['ID_region'] . '
        ';
    }
    
    $salon_product_query = new WP_Query( $args );

    $mam_global_join, $mam_global_where — они как раз через те фильтры и дополняют запрос.

    Я не вижу ничего страшного в использовании $wpdb, при условии что мы используем кеширование запросов.

            $post = wp_cache_get( $post_id, GROUP_CACHE_PRODUCT );
            if( ! $post ) {
                $post = $wpdb->get_row( $wpdb->prepare( 'SELECT * FROM tt_product WHERE post_id = %d LIMIT 1', $post_id ) );
                wp_cache_set( $post_id, $post, GROUP_CACHE_PRODUCT );
            }

    Конечно чтобы генерировать хорошие ключи кеша мне кажется должен быть «класс» уже написанный кем-то, чтобы это дело стандартизировать, но такого я не нашел.

    Что вы скажете по этому поводу, как правильно реализовывать выборку, является ли $wpdb таким злом.

    Я так понимаю вы создали свою произвольную таблицу? А обращались вы к ней с помощью $wpdb ?

    Разумеется.

    У нас программист который писал техническое задание категорически запрещает использовать $wpdb ( «говорит что это прямые запросы в БД,и использовать ее нельзя» ), требует все делать через WP_QUERY и через фильтры

    Та ну. Это справедливо (с оговорками) для штатных запросов и штатных таблиц. Кастомные на то и кастомные, чтобы обцаться с ними по-своему.

    И это не совсем прямые запросы, это через API движка.

    Я не вижу ничего страшного в использовании $wpdb, при условии что мы используем кеширование запросов.

    Кэширование — материя тонкая, его нельзя использовать «потому что так положено». Там огромное количество нюансов, даже краткое описание которых может потянуть статью (не уголовную:)). Кстати, на тему «кэширование в вордпресс» в Сети есть неплохие статьи.

    является ли $wpdb таким злом.

    $wpdb является всего лишь инструментом. И как любой другой инструмент, этот может быть использован как во благо, так и во зло.

    Спасибо. Насчет ACF мы использовали его, т.к. очень удобно помогает добавлять произвольные поля. Да и чтобы что-то прикрутить равное по интерфейсу ACF в админке, придется неимоверные усилия приложить, или может имеются фреймворки позволяющие легко работать с полями?
    А как вы MAIN_QUERY запросы изменяете в тех же архивах, я кроме варианта через

    add_filter('posts_fields', 'tt_posts_fields');
    add_filter('posts_join', 'tt_posts_join');
    add_filter('posts_where', 'tt_posts_where');
    add_filter('posts_orderby', 'tt_posts_orderby');
    add_filter( 'posts_groupby', 'tt_posts_groupby' );

    ничего не нашел

    • Ответ изменён 7 лет, 10 месяцев назад пользователем Andrew Pisarevsky.

    Последнее время — в основном фильтром ‘pre_get_posts’

    У нас программист который писал техническое задание категорически запрещает использовать $wpdb ( «говорит что это прямые запросы в БД,и использовать ее нельзя» ), требует все делать через WP_QUERY и через фильтры

    Та ну. Это справедливо (с оговорками) для штатных запросов и штатных таблиц. Кастомные на то и кастомные, чтобы обцаться с ними по-своему.

    кастомные таблицы я уже ввел, из-за большой потери в выборке.
    Изначально все было на штатных таблицах, но чтобы получить достойный запрос с наибольшей скоростью выборки — приходилось прибегать к такому методу

        global $mam_global_join, $mam_global_where;
        $mam_global_join = '
            INNER JOIN wp_postmeta AS pm2 ON ( wp_postmeta.post_id = pm2.post_id ) 
            INNER JOIN wp_postmeta AS pm3 ON ( pm2.meta_value = pm3.post_id ) 
        ';
        $mam_global_where = '
            AND pm2.meta_key =  \'tt_sp_salon\'
            AND pm3.meta_key =  \'tt_salon_region\'
            AND pm3.meta_value = ' . $tt_currnet_region['ID_region'] . '
        ';
    }
    
    $salon_product_query = new WP_Query( $args );

    Является ли это правильным решением?

    Последнее время — в основном фильтром ‘pre_get_posts’

    Да да перепутал, main_query меняется через этот фильтр, а если нужно сделать запрос вида

    SELECT * FROM wp_posts 
    INNER KOIN custom_table ON custom_table.post_id = wp_posts.ID

    то есть подключить уже CUSTOM таблицу в выборку, в этом случае я писал что использовал бы

    add_filter(‘posts_fields’, ‘tt_posts_fields’);
    add_filter(‘posts_join’, ‘tt_posts_join’);
    add_filter(‘posts_where’, ‘tt_posts_where’);
    add_filter(‘posts_orderby’, ‘tt_posts_orderby’);
    add_filter( ‘posts_groupby’, ‘tt_posts_groupby’ );

    Это будет верным решением?

    Является ли это правильным решением?

    Кодекс предлагает использовать ‘meta_query’:

    
    $args = array(
    	'post_type'  => 'my_custom_post_type',
    	'meta_key'   => 'age',
    	'orderby'    => 'meta_value_num',
    	'order'      => 'ASC',
    	'meta_query' => array(
    		array(
    			'key'     => 'age',
    			'value'   => array( 3, 4 ),
    			'compare' => 'IN',
    		),
    	),
    );
    $query = new WP_Query( $args );
    

    подключить уже CUSTOM таблицу в выборку

    Это будет верным решением?

    Я думаю, да. При этом я допускаю существование иных мнений. Равно как и других реализаций.

    Юрий, а с помощью чего вы реализовывали интерфейс добавления полей к постам в админке? Допустим если эти поля пойдут в custom table?

    Обычно делаю метабоксы (https://developer.wordpress.org/reference/functions/add_meta_box/)
    и сохранение на action ‘save_post’

Просмотр 15 ответов — с 1 по 15 (всего 17)
  • Тема «Крупные нестандартные проекты на WP в открытом доступе» закрыта для новых ответов.