Ответы пользователя по тегу WordPress
  • Как сделать метабокс, который будет иметь все метки метабокса "Метки"?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    1. Найдите в ядре WP код вывода метабокса меток.
    2. Скопируйте к себе.
    3. Модифицируйте код под свои задачи.
    Ответ написан
    4 комментария
  • Как отключить оповещение на е-майл, регистрация нового пользователя?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    Вот список всех ситуаций и писем, которые WP рассылает: https://gist.github.com/johnbillion/0a48021de5510c...
    В описании каждого письма есть инструкция как его отключить. Например, чтобы отключить все письма при регистрации нового пользователя:
    remove_action( 'register_new_user', 'wp_send_new_user_notifications' );

    Впрочем, пользователю желательно отправлять. Давайте отключим только администратору:
    remove_action( 'register_new_user', 'wp_send_new_user_notifications' );
    add_action( 'register_new_user', 'notify_only_user' );
    
    function notify_only_user( $user_id, $notify = 'user' )
    {
        wp_send_new_user_notifications( $user_id, $notify );
    }
    Ответ написан
    Комментировать
  • Как автоматически убрать привязку поста к рубрике через определенное время?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    1. Создайте ежедневную cron-задачу, см. wp_schedule_event()
    2. В хуке на этой задаче проверяйте получаете все посты из нужной вам категории, сравниваете их дату с текущей, если пора отключать - отключаете c помощью wp_remove_object_terms()
    Ответ написан
    Комментировать
  • Wordpress цикл bootstrap grid?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    Давайте уже закроем этот вопрос. Несколько моментов:

    1. Не нужно запускать цикл несколько раз, все условия проверяются внутри одного цикла.
    2. Свойство $query->current_post проверяем внутри цикла, счетчик начинается с 0.

    <div class="container">
    	<div class="row">
    
    		<?php
    		$args = [
    			'post_status'            => 'publish',
    			'posts_per_page'         => 5,
    			'no_found_rows'          => true,
    			'cache_results'          => true,
    			'update_post_meta_cache' => false,
    			'update_post_term_cache' => false,
    		];
    		$query = new WP_Query( $args );
    
    		while ( $query->have_posts() ) : $query->the_post();
    
    			// 1я запись, целиком в .col-6
    			if ( $query->current_post === 0 )
    			{
    				echo '<div class="col-6">'; // Открыли .col-6
    					echo '<div class="post-card">';
    						the_post_thumbnail( 'custom-size', [ 'class' => 'img-fluid' ] );
    						the_title();
    					echo '</div>';
    				echo '</div>'; // Закрыли .col-6
    			}
    
    			// 2я и 4я записи, только открываем .col-3 и выводим 1 запись
    			if ( $query->current_post === 1 || $query->current_post === 3 )
    			{
    				echo '<div class="col-3">'; // Открыли .col-3
    					echo '<div class="post-card">';
    						the_post_thumbnail( 'custom-size', [ 'class' => 'img-fluid' ] );
    						the_title();
    					echo '</div>';
    			}
    
    			// 3я и 5я записи, выводим запись и закрываем .col-3
    			if ( $query->current_post === 2 || $query->current_post === 4 )
    			{
    					echo '<div class="post-card">';
    						the_post_thumbnail( 'custom-size', [ 'class' => 'img-fluid' ] );
    						the_title();
    					echo '</div>';
    				echo '</div>'; // Закрыли .col-3
    			}
    
    		endwhile; ?>
    
    	</div>
    </div>


    Данный код выведет вот такой HTML:

    <div class="row">
    	<div class="col-6">
    		<div class="post-card">
    			...
    		</div>
    	</div>
    
    	<div class="col-3">
    		<div class="post-card">
    			...
    		</div>
    
    		<div class="post-card">
    			...
    		</div>
    	</div>
    
    	<div class="col-3">
    		<div class="post-card">
    			...
    		</div>
    
    		<div class="post-card">
    			...
    		</div>
    	</div>
    </div>


    Но, важно понимать порядок постов в колонках .col-3 - он будет таким:

    .col-6      .col-3      .col-3
    ------      ------      ------
    post-1      post-2      post-4
                post-3      post-5


    а не вот таким:

    .col-6      .col-3      .col-3
    ------      ------      ------
    post-1      post-2      post-3
                post-4      post-5


    В принципе, еще есть другой путь:

    - Посты получаете через get_posts() в виде массива объектов WP_Post.
    - HTML генерите без цикла, формируете как вам надо.
    - В нужных местах подставляете нужный объект WP_Post по его индексу в массиве.
    Ответ написан
    5 комментариев
  • Как перевести строку с указанием своего языка в Wordpress?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    Конечно нет. Сигнатура функции __( $sting, $domain ) принимает 2 аргумента, а не 3, и языка там нет. Текущая активная локаль устанавливается отдельно, на раннем этапе загрузки движка. После этого файлы с переводами для установленной локали загружаются в память и все дальнейшие операции по "переводу" строк происходят с этим загруженным массивом строк. Переключение на лету на другой язык означает необходимость догрузки файлов переводов или проактивную их загрузку заранее. Обе идеи - не самые светлые.
    Ответ написан
    Комментировать
  • Wp default loop break?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    Во-первых, переменная $i вам не нужна, у объекта WP_Query есть свойство $query->current_post.

    Во-вторых, не нужно делать каждый раз wp_reset_postdata() и продолжать цикл, достаточного одного стандартного цикла while( have_posts() ), а внутри if.

    В третьих, у вас в целом разметка одинаковая, отличаются только классы / стили. Поэтому вашу задачу в принципе можно решить чисто на CSS. Но если все же хотите задействовать PHP, то будет что-то типа такого:

    $arguments = [
        'posts_per_page' => 5
    ]; 
    
    $query = new WP_Query( $arguments ); ?>
    
    <div class="row">
    
    <?php 
    // Обычный WordPress Loop:
    while ( $query->have_posts() ) : $query->the_post();
    
        // Можно ограничиться одним кастомным классом с индексом:
        echo "<div class=\"custom-post-style-{$query->current_post}\">";
    
       ...
    
    endwhile; ?>
    
    </div>
    Ответ написан
    4 комментария
  • Как завернуть тег a в span wp menu?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    Регулярками конечно можно, но это молотком ювелирку ровнять. Тем более у вас уже подключен свой вокер:

    'walker' => new My_Walker_Nav_Menu(),

    В нем должен быть метод start_el(). Или скопируйте метод из родительского класса Walker_Nav_Menu и подправьте код ближе к концу метода, вот этот фрагмент:

    $item_output = $args->before;
    $item_output .= '<a'. $attributes .'>';
    $item_output .= $args->link_before . $title . $args->link_after;
    $item_output .= '</a>';
    $item_output .= $args->after;


    измените на:

    $item_output = $args->before;
    $item_output .= '<span>';
    $item_output .= '<a'. $attributes .'>';
    $item_output .= $args->link_before . $title . $args->link_after;
    $item_output .= '</a>';
    $item_output .= '</span>';
    $item_output .= $args->after;


    Но это только в случае если у вас уже есть кастомный вокер. Если нет - все еще проще. Во фрагменте выше обратите внимание на строки:

    $item_output = $args->before;
    ...
    $item_output .= $args->after;


    Документация нам говорит следующее:

    'before'
    (string) Text before the link markup.
    'after'
    (string) Text after the link markup.


    Пусть слово "text" вас не смущает, с помощью этих параметров передается и html-код:

    wp_nav_menu( [
    	'menu'            => '',
    	'container'       => 'nav',
    	'container_class' => 'menu',
    	'echo'            => true,
    	'fallback_cb'     => 'wp_page_menu',
    	'before'          => '<span>',
    	'after'           => '</span>',
    	'items_wrap'      => '<ul>%3$s</ul>',
    	// 'walker'          => new My_Walker_Nav_Menu(),  // Вот это вам не надо, если вы не знаете что делаете.
    ] );


    То есть, стандартный вокер собирает элемент из таких блоков:

    [before] + <a [attributes]> + [link_before] + title + [link_after] + </a> + [after]
    Ответ написан
  • Как присвоить тег?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    Из документации:

    $terms (array/int/string) (required)
    The slug or id of the term (such as category or tag IDs)

    А вот это:

    'до 2019'

    больше похоже на name, а не slug или id. Во-первых, термин (тег) уже должен существовать, во-вторых, передавайте его id. Для slug под капотом делается дополнительный запрос чтобы получить id, собственно на этом запросе и валится ваш код - WP видит string, и воспринимает его как ожидаемый slug, делает запрос термина по этому слагу и получает фигу, потому что термина с таким слагом существовать не может.
    Ответ написан
    Комментировать
  • Как хранить таксономии?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    Хранить конфигурацию таксономий в опциях - пожалуй, самое странное решение из возможных. Минусы (предполагается, что autoload=yes, потому как таксономии регистрируем при каждом запросе) могут быть неочевидны на первый взгляд, но с точки зрения производительности они существенны, а иногда критичны. Автозагрузочные опции грузятся одним пакетом в $all_options. И кешируются. Далее, если есть object cache, то все это кешируется одним куском. А тот же memcached имеет определенные лимиты на объем данных. Превысили лимит - получили проблемы. Далее, вы каждый раз десериализуете данные и работаете с массивами. В последних версиях PHP десериализация вполне быстрая (igbinary правда все равно быстрее), но вы это делаете каждый раз, без острой на то необходимости. Тот же массив в виде обычного array в PHP-файле во-первых не десериализуется, во-вторых скомпилен в байткод посредством Opcache.

    Самый главный вопрос - зачем вообще это хранить в опциях? Какую проблему / задачу вы этим пытались решить?
    Ответ написан
  • Как закрыть от поисковиков копию сайта?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    1. В настройках установить "не индексировать" - в robots.txt будет "Disallow /" для всех роботов. Теоретически этого достаточно, но некоторые роботы могут проигнорировать. Впрочем, основные (Google, Yandex и тд) не игнорируют, так что можно считать что это достаточно надежный способ.
    2. Дополнительно, не стоит сильно переживать, так как адреса то разные будут, и по идее как раз вторая копия будет "дубликатом", даже если и проиндексируется. Теоретически, позиции первой, оригинальной копии не должны страдать. Но тоже могут быть нюансы.
    3. Сайты, которые не должны быть публичными (песочницы всякие, staging-сайты) принято закрывать от публичного доступа вообще. Вариантов как это сделать - масса. Навскидку:
    • плагин (или кодом) Maintenance Mode - показывает заглушку всем, кроме авторизованного администратора (или всех авторизованных юзеров - зависит от настроек)
    • установка пароля через http auth
    • разрешение доступа на уровне сервера по IP
    • работа сайта по IP сервера вместо реального домена + локальный резолвинг доменного имени через /etc/hosts (на Win тоже есть)
    Ответ написан
    Комментировать
  • Работа с WP-Cron?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    Встроенный WP Cron годится только для самых простых задачек, для более надежного срабатывания четко когда надо используйте крон на уровне ОS. В конфиге выключите встроенный крон:

    define( 'DISABLE_WP_CRON', true );

    И создайте крон-задачу на уровне OS, задав нужный интервал и команду вида:

    wget -q -O - https://example.com/wp-cron.php?doing_wp_cron >/dev/null 2>&1

    Вместо wget можете использовать curl, httpie, или /usr/local/bin/php, тут смотрите по ситуации. Как настраивать крон-задачи из командной строки можете погуглить, как добавить если у вас какая-нибудь CPanel - тоже.

    А еще есть https://github.com/humanmade/Cavalcade

    Ну а для долгих и асинхронных скриптов есть RabbitMQ и вот это все. Посмотрите https://github.com/10up/WP-Minions
    Ответ написан
    Комментировать
  • Как получить путь (thumbnail)?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    Функция wp_upload_dir():

    <?php
    $upload_dir = wp_upload_dir();
    var_dump( $upload_dir );
    
    /*
        Array (
            'path' => /path/to/wordpress/wp-content/uploads/2018/12
            'url' => https://example.com/wp-content/uploads/2018/12
            'subdir' => /2018/12
            'basedir' => /path/to/wordpress/wp-content/uploads
            'baseurl' => https://example.com/wp-content/uploads
            'error' =>
        )
    */
    
    echo $upload_dir['url']; // Вот это наверное вам надо
    Ответ написан
    1 комментарий
  • Как в Wordpress реализовать полноценный поиск через Ajax без тега form?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    $('.my-class').keypress(function(eventObject){
      eventObject.preventDefault();
      ..

    Давно не писал на js, но вроде так.
    Ответ написан
  • Как изменить список выводимых записей в Wordpress?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    1. Хук pre_get_posts.
    2. В нем изолируете с помощью $query->{conditional_check} (is_admin, is_main_query и тд) нужный контекст.
    3. С помощью $query->set( 'параметр', 'значение' ) устанавливаете нужные параметры. Дополнительное поле это будет meta_query.
    Ответ написан
    Комментировать
  • Как использовать куки/сессии в WordPress?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    Обычными сессиями в PHP.

    https://www.ironistic.com/using-php-sessions-in-wo...

    Но с учетом нюансов, если пользуетесь кешированием.

    https://pressjitsu.com/blog/wordpress-sessions-per...
    Ответ написан
    Комментировать
  • Не работает WPML. Как быть?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    <?php _e('Get In Touch', 'Связаться с нами'); ?>

    Это некорректный код. Сигнатура функции:
    _e( 'String in original language', 'textdomain' );
    Где textdomain - это уникальный слаг, по которому подгружается файл переводов. А не сам перевод строки на русский, который вы вставили.
    Ответ написан
    1 комментарий
  • Как открывать ссылки внутри шаблона Wordpress?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    Вам за школьную парту обратно надо, почитать про routing, а потом про rewrite rules в WordPress. Все запросы WP обрабатывает один и тот же файл /index.php в корне (кроме статики конечно же).
    Ответ написан
    4 комментария
  • Почему берется не та относительная ссылка из функции?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    Либо в wp-config.php константа с URL, либо в базе данных в wp_options.
    Ответ написан
    Комментировать
  • WordPress: я вписываю весь нужный код в functions.php. Правильно ли это?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    Говнокод, но да.

    Файл functions.php - это просто обычный php-файл, который подключается на определенном этапе работы движка и весь код в нем выполняется. Все кастомизации можно тулить туда. Разумно ли это - другой вопрос, и уже выходит за рамки ответа "да / нет". Если кода много, то стоит задуматься о его организации. По простой логике, функциональность принято делить на отдельные классы, в случае с WP это часто просто отдельные файлы. Я лично предпочитаю в самом functions.php определять только то, что вешается на хук after_setup_theme, а дальше идет просто автолоадер всего остального или инклуды других файлов, которые размещены в theme_dir/inc
    Ответ написан
    1 комментарий
  • Как добавить такой функционал на WordPress?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    1. WordPress пишется с двумя заглавными буквами, capital_P_dangit()
    2. Git не пишется капсом, это не аббревиатура.
    3. FRONTEND тоже не аббревиатура. Кроме того, корректно писать "front end" (noun), но "front-end developer" (adjective).
    4. Less тоже, кстати, официально пишется не как LESS.
    5. "как мне его добавить в эту панельку" - эта панелька называется Customizer.
    6. WordPress из списка своих навыков можете смело убирать - вы его не знаете.
    7. Что касается добавления своего контрола в панель кастомайзера – читайте доку. Осилите сами – сможете заодно и вернуть тег "WordPress" в свои навыки. Правда, желательно со сноской.
    Ответ написан
    Комментировать