• Как создать frontend формы с возможностями сохранения и редактирования?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    Gravity Forms
    Ninja Forms
    Caldera Forms
    Torro Forms
    ...
    Да любой адекватный плагин для форм под WordPress предоставляет этот функционал.
    Ответ написан
  • Как оптимизировать сайт на wordpress+visual composer?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    Бекенд у вас весьма шустрый:

    bf3ea512b4264ec0a546b7e2a70bafee.jpg

    Это весьма и весьма достойный результат. С сервером и на серверной стороне все в порядке. А теперь узкие места:

    1. Загрузка шрифтов с серверов Google. С вашим шустрым сервером имеет смысл шрифты стянуть себе и отдавать локально. Срежете секунды полторы:

    67053ff4cfef4f458eb6d4723a36a7e2.jpgab83df494f21431284650396046227eb.jpg

    2. Далее, есть проблема с несколькими стилями:

    vcare.uz/wp-content/plugins/js_composer/assets/lib...
    vcare.uz/wp-content/plugins/js_composer/assets/lib...
    vcare.uz/wp-content/plugins/js_composer/assets/lib...

    Они долго грузятся, можете сами в Developer Tools посмотреть. Проблема не только в том, что они долго грузятся, но и в том, что они встают в очередь так как расположены в подвале и из-за использования HTTP/1.1. Можно решить 2мя путями:

    - конкатенация в один файл
    - использование HTTP/2

    В идеале, можно искать баланс между HTTP/2 + выборочная конкатенация.

    3. Файлы

    - new.vcare.uz/wp-content/uploads/2017/08/header-1.j...
    - new.vcare.uz/wp-content/uploads/2017/08/bg-white22...

    С ними 2 проблемы:

    - грузится с поддомена (+ DNS lookup и прочие потери на новый коннект)
    - динамический параметр, который предотвращает кеширование файла на стороне клиента

    Перенесите файл на основной домен и уберите параметр.

    4. Contact Form 7

    7cad4ec44dba469b86e2fbaa7c31558d.jpg

    У вас 7 (!!!) аякс-запросов этот плагин генерит. Я так понимаю, это 7 разных форм на странице. Запросы запускаются достаточно рано в цикле жизни страницы, и блокируют других ресурсов, занимая соединения с сервером. По протоколу HTTP/1.1, насколько я помню, браузер открывает до 6 соединений с сервером. В вашем случае, часть из этих 6 к моменту вызова этих ajax-запросов уже занята, и они встают в очередь друг за другом, вместе с другими ресурсами. Это умножает время ожидания. Переход на HTTP/2 заметно снизит влияние, но желательно избавиться от них вообще. Я бы советовал заменить CF7 на более адекватный плагин. Попробуйте, к примеру, Torro Forms (толковый и бесплатный, еще и с нормальным интерфейсом).

    5. Еще один запрос к admin-ajax.php

    f94caf0158b642b2958aefe1b9825ae5.jpg

    Собственно, он инициирован Visual Composer'ом - это Masonry сетка. Возможно, он у меня дозапустился потому что я начал скролить страницу и докрутил до того места, где он нужен. Возможно, он не запускается по умолчанию и проблемой не является.

    6. Front-end performance (парсинг и рендеринг):

    1691686d9b5f493fb147d10e0da4a894.jpg

    Парсинг скриптов занимает много времени, ибо их много. Но от этого можно избавиться только путем уменьшения их количества, что, возможно, не вариант. А вот второй очень тревожный сигнал - это как раз время ожидания (Idle). Это как раз говорит о невозможности браузера продолжать работу на каких-то этапах из-за того, что он ждет пока прилетят запрошенные ресурсы. Переход на HTTP/2 крайне желателен + замена CF7. Это как раз тот случай, когда HTTP/2 должен дать ощутимый эффект.

    Ну это так, беглый анализ. Посмотрите результаты тестирования тут: https://tools.pingdom.com/#!/2GQ2d/http://vcare.uz/
    Ответ написан
    3 комментария
  • В чём преимущество автозагрузчика классов?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    Автозагрузка нужна в первую очередь для того, чтобы не подключать их везде (имеется в виду в других классах) руками. Потому что в случае изменения путей, имен файлов и тд потом надо весь код перелопатить и везде все поменять. Плюс, надо помнить что где подключено, чтобы классы были доступны там, где они нужны. Для большого приложения, особенно если использовать ООП во всей красе - interface, abstract, trait и конкретные субклассы, это огромный плюс. Ну и да, классы будут загружаться только если они реально нужны, а не всегда, что сократит в том числе и время парсинга.

    А можно избавиться от строки $obj = new MyClass(); и создавать экземпляр автоматически в момент $obj->displayVar();?


    ( new MyClass )->displayVar();
    Ответ написан
    Комментировать
  • Как вывести метки у которых в slug присутствует определенное значеник?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    Функция the_post_tags() мне неизвестна. В коде WP такой нет. Подозреваю, вы имели в виду the_tags().

    Данная функция (the_tags()) выводит список тегов, строкой. А для обработки в цикле foreach вам нужно во-первых данные получить (нужна функция которая возвращает данные а не выводит), а во-вторых возвращаемые данные должны быть массивом, а не строкой.

    $tags = get_the_tags();
    
    foreach ( $tags as $tag ) {
        if ( strpos( $tag->slug, '_en' ) !== false ) {
            echo $tag->name;
        }
    }
    Ответ написан
    1 комментарий
  • Как посмотреть все хуки wp_head() c указанием файлов или сразу кода функций?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    В дополнение к Debug Bar могу посоветовать:

    Query Monitor - для отладки в целом, ну и хуков тоже

    ce4e138638484564972545d38b5e8f29.pngWP Inspect - конкретно по хукам

    536ab5e2550a49bfa5282d60f3c8a141.png
    Ответ написан
    Комментировать
  • Как вывести записи только из дочерних рубрик?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    О боги, ну сколько можно повторять, никогда не используйте query_posts!

    1. Используйте WP_Query или хук pre_get_posts
    2. В WP_Query используйте Tax_Query:
    $args   = [
        'posts_per_page' => 10,
        'tax_query'      => [
            'relation' => 'AND', // объединяем результаты по двум инструкциям
            // Инструкция 1 - получить все посты из родительской категории и ее потомков
            [
                'taxonomy'           => 'category',
                'field'                    => 'slug',
                'terms'                  => 'special_cat',
                'include_children' => true,
            ],
            // Инструкция 2 - а теперь исключить все посты родительской категории
            [
                'taxonomy'            => 'category',
                'field'                     => 'slug',
                'terms'                   => 'special_cat',
                'include_children' => false,
                'operator'              => 'NOT IN',
            ],
        ],
    ];
    $result = new WP_Query( $args );
    Ответ написан
  • Как заставить wp_head() выводить ссылки с https?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    Посмотрел код, у вас там только вот это на http
    <link rel="profile" href="http://gmpg.org/xfn/11">
    Но оно так и должно быть. Все остальное на https. Возможно, кеш?
    Ответ написан
  • Как организовать управление статьями кастомных страниц для пользователей?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    То, что вы хотите, реализуется многими плагинами, поищите на wordpress.org/extend/plugins. Впрочем, если хотите пойти путем джедая, разложу по полочкам.

    Пользователи сайта (сайт на WP) регистрируются.

    Стандартная фича. Но если не хотите логин/регистрацию через родную форму, пишите свою. Смотрите функции register_new_user() и wp_insert_user().

    Одни могут делать отзывы и подписываться на рассылку, вторые могут создавать свои странички и заполнять инфо.

    Для начала, вам понадобятся разные роли. Читаем Roles and Capabilities. Можно использовать плагин для создания ролей.

    Далее, если вы хотите чтобы пользователи на фронтенде сайта могли данные редактировать, вам понадобится создать страничку, скажем, "Account". Далее для нее добавьте endpoints нужных "виртуальных страничек". Вывод endpoint'ов проводите через проверку ролей и показывайте пользователю только нужные.

    Вообще такой контент хранится у меня через ACF и PODS. Как сделать интерфейс управления страничками и параметрами для пользователей? Чтобы человек зашел, и мог добавить, например, свою компанию, редактировать её инфо.

    А теперь для каждого созданного endpoint делаете темплейт, соответствующую форму, и обработчик этой формы. Для создания записей вам пригодятся функции wp_update_post(), update_post_meta().

    И да, не забываем про проверку авторизации, ролей, редиректы где нужно, валидацию и санитизацию всех входящих данных, очистку данных на выводе и тд. В общем, стандартные моменты.
    Ответ написан
    Комментировать
  • Как вывести метки внутри записи?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    eval() не использовать. Никогда.

    Подобные моменты решаются через шорткоды.

    1. В functions.php
    function post_tags_within_content() {
        global $post;
        $tags = get_the_tag_list( '<p>'Tags: , ', ', '</p>', $post->ID );
        return $tags;
    }
    add_shortcode( 'tags', 'post_tags_within_content' );

    2. Использование в контенте поста:
    [tags]
    3. Получаемый результат:
    ...
    <p>Tags: tag1, tag2, tag3</p>
    ...

    при этом tag1, tag2, tag3 будут ссылками на соответствующие термины.

    Параметры функции get_the_tag_list() - в документации.
    Ответ написан
    Комментировать
  • Пагинация с множественным wp_query + offset's?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    Пагинация работает от основного запроса (Main WP_Query), а не от кастомных, и оффсеты тут ни при чем.
    Ответ написан
    Комментировать
  • Wordpress плагин устанавливается на английском, почему?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    Попробуйте зайти в Dashboard - Updates, и посмотреть, нету ли блока Update Translations. Вполне возможно, сам плагин поставляется из коробки без всех файлов переводов, и после активации плагина их надо докачивать.
    Ответ написан
  • Какая серверная ОС более продуктивна для совместной работы nginx и apache?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    Вы уже с самого начала не разобрались:
    nginx + apache (фронтенд и бэкенд)

    И Nginx, и Apache - это веб-серверы, вашей терминологией - фронтенд. Бекенд - это PHP, Python и тд. Первое, что надо сделать - выбросить Apache вообще, если для его использования нету реально обоснованной причины.
    Ответ написан
    6 комментариев
  • Что делать с индексированием страниц на WordPress после Joomla?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    Сделайте редиректы или возврат 404 на уровне сервера. Если Apache - в .htaccess, если Nginx - создайте отдельный файл с редиректами и в конфиге виртуального хоста подключите его.
    Ответ написан
    1 комментарий
  • Как сделать отображение таксономии в админке по условию?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    2 варианта.

    1. Javascript. По умолчанию визуально скрываете метабокс (CSS). При выборе чекбокса в метабоксе категорий проверяете его значение, если оно совпадает с нужным - показываете метабокс, если нет - прячете. Плюс - работает "на лету", даже с черновиками, нет необходимости сохранять запись чтобы увидеть результат.

    2. PHP. Хукаетесь в do_meta_boxes, проверяете есть ли нужная вам категория у записи, если нет - делаете remove_meta_box() для вашей таксономии. Плюс - метабокс не выводится вообще, если он не нужен. Минус - записи сначала надо присвоить категорию и сохранить, чтобы метабокс появился.
    Ответ написан
    4 комментария
  • Как добавить новый тип записей в WordPress и сделать гибкий фильтр по ним?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    1. Статьи делаются на основе стандартного типа записей 'post'
    2. Игры делаются через произвольный тип записи (custom post type) 'game'
    3. Чтобы и игры, так же как статьи, можно было складывать в категории:
    - если категории нужны те же, что и для статей, то для cpt 'game' дополнительно подключается стандартная таксономия 'post_category'
    - если для игр нужны свои уникальные категории, то регистрируется произвольная таксономия 'game_category'
    4. Все дополнительные характеристики/свойства игр пропускайте в голове через такой фильтр:
    - если набор терминов (значений) в характеристики плюс-минус понятен (например, жанры игр), по нему нужна фильтрация запросов, а также сам термин может иметь дополнительные данные (как минимум, описание) - тогда для этой характеристики подходит произвольная таксономия (в вашем случае - платформа, жанр)
    - если значения характеристики могут быть разными, отсутствовать вообще, быть достаточно большим текстом, не нужны для полноценной фильтрации через основной запрос и тд (например, в вашем случае это "особенности") - тогда для этой характеристики подходит произвольное поле (custom field / post_meta)
    Ответ написан
    Комментировать
  • Wordpress Кэширует php?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    PHP WordPress кешировать не может по определению. Сам PHP может кешироваться самим PHP, через opcache (о чем вам уже написали). Что WordPress действительно может кешировать, так это данные. С помощью Transients API и Object Cache API. Соответственно, смотрите наличие класса object-cache.php в папке wp-content, и записи со словом transient в таблице wp_options. Для работы с transients (и их очистки) можете использовать плагин Transients Manager.
    Ответ написан
    Комментировать
  • Как изменить в адресной строке имя шаблона страницы?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    Это стандартный rewrite rule для post formats. Его можно модифицировать через хук post_format_rewrite_rules. Хукаетесь в него, он принимает в виде параметра массив правил в формате "регулярное выражение" => "урл с параметрами". Далее можете циклом пройтись по ним, заменить все что надо. После этого надо пересохранить правила.
    Ответ написан
    1 комментарий
  • Динамический шаблон для статических страниц Wordpress?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    Ответ написан
    Комментировать
  • Чем еще query_posts отличается от get_posts?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    Как вам уже сказали, использовать query_posts не стоит. Вообще забудьте о существовании этой функции.

    Чем query_posts отличается от get_posts

    Неужели так сложно открыть код и сравнить, чтобы раз и навсегда закрыть для себя этот вопрос? Ниже, код взят из файлов ядра, комментарии мои.

    1. Код функции query_posts() из файла wp-includes/query.php
    function query_posts($query) {
    	// Первым делом, функция убивает текущий WP_Query, 
    	// запрос который был выполнен для текущей страницы,
    	// ЗАМЕНЯЯ его новым, пустым экземпляром WP_Query.
    	$GLOBALS['wp_query'] = new WP_Query();
    	// Далее, функция обращается к этому новому экземпляру,
    	// и выполняет запрос с передаными в функцию параметрами.
    	// Результаты запроса возвращаются, но при этом глобальный 
    	// изначальный WP_Query тоже ЗАМЕНЕН. То есть, данная функция 
    	// деструктивна! Она меняет глобальный объект и имеет побочные эффекты.
    	return $GLOBALS['wp_query']->query($query);
    }

    2. Код функции get_posts() из файла wp-includes/post.php
    function get_posts( $args = null ) {
    	// Функция изначально содержит некий набор параметров по умолчанию.
    	// Из важных - возвращает 5 постов, устанавливает suppress_filters в true, 
    	// что означает что все фильтры на хуках posts_* НЕ ПРИМЕНЯЮТСЯ. А вот 
    	// в том же query_posts они применяются, потому как там вызывается прямо
    	// WP_Query, у которого параметр suppress_filters по умолчанию = false.
    	$defaults = array(
    		'numberposts' => 5,
    		'category' => 0, 'orderby' => 'date',
    		'order' => 'DESC', 'include' => array(),
    		'exclude' => array(), 'meta_key' => '',
    		'meta_value' =>'', 'post_type' => 'post',
    		'suppress_filters' => true
    	);
    
    	// Берем параметры, переданные в функцию, и склеиваем их с параметрами
    	// по умолчанию.
    	$r = wp_parse_args( $args, $defaults );
    
    	// Если параметр Х не передан явно, определяем значение, которое будем использовать:
    	if ( empty( $r['post_status'] ) )
    		$r['post_status'] = ( 'attachment' == $r['post_type'] ) ? 'inherit' : 'publish';
    	if ( ! empty($r['numberposts']) && empty($r['posts_per_page']) )
    		$r['posts_per_page'] = $r['numberposts'];
    	if ( ! empty($r['category']) )
    		$r['cat'] = $r['category'];
    	if ( ! empty($r['include']) ) {
    		$incposts = wp_parse_id_list( $r['include'] );
    		$r['posts_per_page'] = count($incposts);  // only the number of posts included
    		$r['post__in'] = $incposts;
    	} elseif ( ! empty($r['exclude']) )
    		$r['post__not_in'] = wp_parse_id_list( $r['exclude'] );
    
    	// Еще один интересный параметр, "не включать в результаты запроса прилепленные посты".
    	$r['ignore_sticky_posts'] = true;
    
    	// И еще один очень важный параметр. Он означает, что не нужно считать общее количество
    	// найденных записей по нашему запросу, поскольку нам нужна всего лишь небольшая порция,
    	// никакой пагинации и тд. Это упрощает и ускоряет SQL-запрос.
    	$r['no_found_rows'] = true;
    
    	// И вот, наконец, создается НОВЫЙ экземпляр WP_Query, который НЕ ЗАМЕНЯЕТ никаких 
    	// глобальных объектов. На нем выполняется запрос со сформированными выше параметрами, 
    	// и его результат возвращается из функции наверх. 
    	// Никакого взаимодействия с глобальным scope.
    	$get_posts = new WP_Query;
    	return $get_posts->query($r);
    }


    А вот, собственно, и ответ на ваш вопрос, вот этот фрагмент функции get_posts():
    if ( empty( $r['post_status'] ) )
        $r['post_status'] = ( 'attachment' == $r['post_type'] ) ? 'inherit' : 'publish';
    Ответ написан
  • Редирект со старых страниц на новые WordPress при смене структуры URL?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    Настроить переадресацию на уровне Apache / Nginx
    Ответ написан
    Комментировать