• Как встроить чужой api на свой сайт?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    1. Для получения данных используйте функции wp_remote_get(), wp_remote_retrieve_body(),
    2. Для парсинга данных из json используйте json_decode()
    3. Во избежание множественных запросов используйте transients cache для кеширования ответа

    Документация по всем упомянутым функциям есть в Кодексе.
    Ответ написан
    Комментировать
  • Как правильно называется подобный эффект?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    Комментировать
  • Какие идеальные взаимоотношения между заказчиком и исполнителем?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    2. Заказ оказался сложнее (появились подводные камни)


    Вот на этом этапе нужно остановиться, выдохнуть, и начать разговаривать с заказчиком. Он ведь живой человек. Такая ситуация может возникнуть в основном по 2м причинам:

    1. Исполнитель недооценил свои силы и сделал некорректную оценку времени/стоимости. ИМХО, его проблема. С опытом проходит, но риски есть всегда. От них перестраховываются накидыванием запаса к изначальной оценке.

    2. Заказчик изменил требования. Это называется scope change и автоматически должно вести за собой переоценку сроков и стоимости (если не работаете по Agile и на почасовке).

    Грубо, логика такая:

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

    Если же подводные камни появились из-за ошибки в оценке сложности проекта самим разработчиком, то клиент не должен платить за это. Но если эти подводные камни добавляют работы и могут сдвинуть сроки, я считаю крайне необходимым сообщить об этом клиенту, как только вам об этом стало известно. Так и говорите - всплыли некоторые подводные камни, предусмотреть не могли. Моя вина, на стоимость работ не повлияет. На может повлиять на сроки - на столько и на столько.
    Ответ написан
    6 комментариев
  • Как добавить js-скрипт в админку для пользовательского типа записи?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    Можно

    <?php 
    function my_cpt_enqueue( $hook_suffix ){
    
        $cpt = 'my-post-type'; // тут измените на свой custom post type
    
        if( in_array( $hook_suffix, array( 'post.php', 'post-new.php' ) ) ) {
    
            $screen = get_current_screen();
    
            if( is_object( $screen ) && $cpt == $screen->post_type ){
    
                // тут подгружаете скрипт
    
            }
        }
    }
    add_action( 'admin_enqueue_scripts', 'my_cpt_enqueue');
    Ответ написан
    Комментировать
  • Почему не работает хук?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    Дополню ответ Алексей Николаев конкретным кодом с комментами:

    ...
    add_filter( 'ul_ol_hook', 'ul_ol_func' );


    <?php echo apply_filters('ul_ol_hook', $tblock_textarea); ?>


    1. Ваш коллбек изменяет данные, значит это должен быть фильтр.
    2. Фильтр возвращает измененные данные, а не выводит их, значит надо делать echo или выводить другим способом.
    Ответ написан
    Комментировать
  • Как сделать древовидные комментарии?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    1. В структуре БД понадобится колонка "parent_id":

    ID - автоинкремент, уникальный ID комментария
    parent_ID - уникальный ID родительского комментария
    object_ID - уникальный ID страницы/записи/объекта, к которому комментарий относится
    ... - остальные колонки

    2. Как выводить деревья знает гугл.
    Ответ написан
  • Есть ли Поп Ап плагин В вордпресс?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    Неужели так сложно зайти на WordPress.org в раздел Plugins и выполнить простейший поиск?

    https://wordpress.org/plugins/search/pop-up/
    https://wordpress.org/plugins/search/lightbox/
    Ответ написан
    Комментировать
  • Как прикрепить файл картинку при отправке сообщения?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    Раз уж вы тег WordPress поставили, и сайт у вас на нем - то делайте все как положено. Почитайте про работу с ajax, загрузку файлов и отправку писем с вложениями:

    https://wp-kama.ru/id_2018/ajax-v-wordpress.html
    https://wp-kama.ru/id_9026/jquery-ajax-zagruzka-fa...
    https://codex.wordpress.org/Function_Reference/wp_...
    https://developer.wordpress.org/reference/function...

    Грубо говоря, WP из коробки предоставляет вам возможность обрабатывать ajax-запросы с фронта, загружать файлы (одновременно проводя проверку загружаемых файлов), отправлять письма с вложениями.
    Ответ написан
  • 2gis в Wordpress как убрать лишние слова в кавычках без потери содержимого?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    Это шорткоды плагина Visual Composer. Руками убирайте, если плагин не используется и его виджеты не нужны. Некоторый контент (из динамических виджетов) будет утерян.
    Ответ написан
    Комментировать
  • Что за предупреждение вылазит в админке wordpress?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    Эти константы должны содержать корректный URL, а не /. Не изобретайте странные велосипеды. Данные константы используются для генерации полных абсолютных URL с корректными путями.
    Ответ написан
  • Как сделать медиафайлы на другом хостинге?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    Никак, особенно если у вас обычный shared хостинг.

    УРЛ файлов можно заменять, не проблема. А вот путь (который используется при загрузке файлов) должен быть локальным. Загружать файлы через медиа-библиотеку на сторонний сервер не получится. Есть вариант после заливки на текущий сервер уже своим кастомным кодом синхронизировать файл на другой сервер и перезаписывать урлы. Именно по такому принципу работает Offload S3 и аналогичные решения. Но объем кода подобной реализации сильно превышает возможности ответов на Тостере. К тому же, не факт что ваши shared хостинги предоставляют необходимые возможности.

    С какой целью вам это вообще надо?
    Ответ написан
  • Как сделать относительные ссылки без домена?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    Это WP. Поэтому:

    1. Все ссылки, которые вписаны в контент, который хранится в БД будут абсолютными.
    2. Все остальные ссылки генерируются абсолютными на лету одной из многих функций ядра.

    Зачем вам это? Какую конкретную проблему вы пытаетесь решить? Комментарии в стиле "все фреймворки делают относительные урлы" неуместны.
    Ответ написан
  • Как использовать javascript на странице index.php в wordpress?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    Javascript должен либо работать в том месте, где он стоит и будет прочитан (что не совсем правильно, имхо, потому как это скриптовый язык и ему в 99.99% нужен готовый DOM, а не его кусок), либо по событию. Подходящее событие определяется исходя из задачи. В вашем случае это DOMContentLoaded.

    Вставлять не обязательно (и даже нежелательно) в начало BODY, хоть многие счетчики / чаты поддержки и прочее говнецо именно так рекоммендуют. Минус такого подхода в том, что эти ваши скрипты, которые стоят в начале BODY и вызываются не по ивенту, а "сразу", будут блокировать все остальное. Это антипаттерн в плане оптимизации. Ставьте такой код перед закрывающим BODY. Эффект будет тот же, за исключением мелочей - например, счетчики статистики могут не успеть посчитать какое-то мизерное количество юзеров, которые ушли с сайта чуть раньше, чем страница прогрузилась до скрипта. Ну и хрен с ними, этими данными можно пренебречь. Намного важнее чтобы 99% пользователей получали страницу быстрее благодаря меньшему TTI.

    Как подгрузить их в WP? Да обычными стандартными средствами через functions.php. Если грузить в конце документа. Лучше всего сам js-код разместить в отдельном js-файле, его подключать в подвал, с async / defer по возможности.

    Было бы интересно узнать что это у вас за код такой, который нужно конкретно ставить в нужном месте. Скорее всего это просто неправильно написанный js.
    Ответ написан
    Комментировать
  • Как оптимизировать работу лендинга на wordpress?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    Гуглдиск - не хостинг и не CDN. Хранить то на нем можно, и даже отдавать. Но высокой скорости я бы не ждал.

    И вообще это будет анти-оптимизация. Во-первых, скорость гуглдиска не заточена под обычную отдачу статики. Во-вторых, это дополнительный внешний запрос, который будет включать в себя DNS lookup, установку безопасного соединения вместе с SSL handshake и прочие потери на сети. Nginx на вашем собственном сервере вернет картинку в разы быстрее, по уже установленному соединению. Даже Apache ее быстрее вернет. А если у вас Nginx и HTTP/2 - то прям на порядок быстрее это все прилетит. Вот это и есть оптимизация. А пихать картинки на redundancy файлохранилище - это не оптимизация, а что-то странное.
    Ответ написан
  • Как вывести записи из определенных категорий (пересечения их)?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    Изначально разделяйте вопросы или не разветвляйте потом. Ответил вот тут https://toster.ru/answer?answer_id=1113578
    Ответ написан
    Комментировать
  • Где почить (официальные доки) про вывод записей из 2 категорий /category/slug1+slug2 (AND)?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    Лучше всего посмотреть, что происходит под капотом. С помощью плагина Query Monitor можно увидеть результирующий запрос и проанализировать его. Я специально создал несколько категорий и постов, и для отладки одному посту назначил 3 категории, одна из которых является дочерней категорией другой (только хардкор!):

    SELECT SQL_CALC_FOUND_ROWS wp_posts.ID
    FROM wp_posts 
    LEFT JOIN wp_term_relationships
    ON (wp_posts.ID = wp_term_relationships.object_id) 
    LEFT JOIN wp_term_relationships AS tt1
    ON (wp_posts.ID = tt1.object_id) 
    LEFT JOIN wp_term_relationships AS tt2
    ON (wp_posts.ID = tt2.object_id)
    WHERE 1=1 
    AND ( wp_term_relationships.term_taxonomy_id IN (2,3,4) 
    AND tt1.term_taxonomy_id IN (1) 
    AND tt2.term_taxonomy_id IN (3) )
    AND wp_posts.post_type = 'post'
    AND (wp_posts.post_status = 'publish'
    OR wp_posts.post_status = 'acf-disabled'
    OR wp_posts.post_status = 'private')
    GROUP BY wp_posts.ID
    ORDER BY wp_posts.post_date DESC
    LIMIT 0, 10


    Самое интересное тут (убрал лишнее для наглядности):

    WHERE ( 
    wp_term_relationships.term_taxonomy_id IN (2,3,4) 
    AND 
    tt1.term_taxonomy_id IN (1) 
    AND 
    tt2.term_taxonomy_id IN (3) 
    )


    Какие выводы можно сделать?

    1. Под каждый новый термин идет дополнительный LEFT JOIN все той же таблицы wp_term_relationships
    2. WHERE использует оператор AND, то есть будут выбраны записи у которых есть все 3 термина
    3. Важный нюанс - в первом условии IN (2,3,4) запрошены и родительская категори (2), так и все ее дочерние (3, 4) - это интересный момент main query на страницах архивов терминов

    Итого:

    - Первый термин в URL идет основой запроса
    - Все последующие докидываются в запрос через LEFT JOIN с использованием оператора AND в WHERE

    Значит, работает все именно так, как вам надо. За исключением важного нюанса номер 3 (см. выше). Но это стандартное поведение WP, его можно поменять:

    https://wordpress.stackexchange.com/questions/5525...
    https://gist.github.com/CodeProKid/1d21fb763514149...

    Остается вопрос "как сгенерировать такую ссылку". Это несложно - достаточно склеить адрес сайта, category base, и слаги категорий через +. Пишем простую функцию:

    /**
     * Generate a link for multiple categories
     * 
     * @param $categories array An array of category slugs
     *
     * @return string
     */
    function my_categories_link( $categories ) {
        
        $category_base = get_option( 'category_base' ) ? get_option( 'category_base' ) : 'category';
        $categories_str = implode( '+', $categories );
    	
        return sprintf( "%s/%s/%s/",
            home_url(),
            $category_base,
            $categories_str
        );
    }


    В темплейте, там где ссылку надо сделать:

    echo my_categories_link( [ 'one', 'two' ] );

    Где one и two - слаги нужных категорий.

    Можно допилить функцию, чтобы она принимала на выбор - ID, слаги или объекты категорий. Но это уже тонкости :)
    Ответ написан
  • Как повторно использовать цикл вывода записей?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    Из описания задачи сложно понять что вы хотите сделать. Для повторного использования цикла существует функция rewind_posts(), но после такой "перемотки" вы просто попадете в начало стандартного цикла. То есть, сможете работать с теми же записями, по которым уже один раз прошлись, то есть, будете выводить дубликаты. А вы хотите без дубликатов. Тогда вопрос - а что тогда должен вывести цикл? Следующую страницу / порцию записей?
    Ответ написан
  • Вывод дочерних категорий текущей категории?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    Как и у меню, у категорий есть возможность использовать свой Walker, который расширяет класс Walker_Category. Внутри же walker'а уже можно смотреть вложенность, текущую категорию, принадлежность нужному родителю и тд.
    Ответ написан
    Комментировать
  • Присвоить шаблон родительской категории для подкатегории?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    Фильтр template_include + conditional функция cat_is_ancestor_of:

    function parent_category_template( $template ) {
    
    	if ( is_category() && cat_is_ancestor_of( $parent_category_id, get_queried_object_id() )  ) {
    		$new_template = locate_template( array( 'category-parent.php' ) );
    		if ( '' != $new_template ) {
    			return $new_template;
    		}
    	}
    
    	return $template;
    }
    add_filter( 'template_include', 'parent_category_template', 99 );
    Ответ написан
    Комментировать