• Как отфильтровать записи по меткам wordpress?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    как мне получить метку по которой был осуществлен переход?

    get_queried_object()?

    On a category archive, tag archive, or other taxonomy archive page, it will return the WP_Term object of the current category, tag, or other term.
    Ответ написан
    2 комментария
  • Как перейти от ACF PRO на Gutenberg?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    ACF Pro помогает создавать блоки для Gutenberg с помощью PHP, это удобно и значительно ускоряет работу. Но если надо полностью отказаться от ACF Pro и использовать только Gutenberg, то придется запилить свои блоки (привет React) или же найти готовые, подходящие под ваши задачи.

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

    Простой пример - блок testimonials. На ACF мы создаем обычно рипитер, в нем нужные поля которые будут повторяться, скажем - text, name, photo (текст отзыва, имя клиента и его аватар). А на gutenberg достаточно иметь блок testimonial с этими же полями, и просто вставить его X раз подряд - вот вам и повторяющиеся данные.
    Ответ написан
    Комментировать
  • Как задать класс изображениям внутри записи на Wordpress?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    Самый простой способ - на хуке the_content обычной заменой или регуляркой, но это если у картинок всегда одна структура (например, мы точно знаем что тег будет <img src="..." class="..." ...). Но вообще парсить html регулярками не самая светлая мысль - для этого есть DOMDocument:
    function add_class_to_images( $content )
    {
        $document = new DOMDocument();
        libxml_use_internal_errors(true); // чтобы не ругался на семантические HTML5 теги
        $document->loadHTML( $content );
        libxml_clear_errors();
    
        $images = $document->getElementsByTagName( 'img' );
    
        /** @var \DOMElement $image */
        foreach ( $images as $image ) {
            $image->setAttribute( 
                'class', 
                $image->getAttribute( 'class' ) . ' my-new-class'
            );
        }
    
        return $document->saveHTML();
    }
    add_filter( 'the_content', 'add_class_to_images' );
    Ответ написан
    9 комментариев
  • Как уменьшить запасы товаров в woocommerce при статусе "pending"?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    Так, а давайте для начала определим, почему у вас заказы попадают в статусе pending?

    Потому что pending - это промежуточный, "технический" статус между созданием заказа и его оплатой с последующим переходом в статус processing (в случае успешной оплаты) или failed (в случае ошибки с оплатой или отказа).

    Методы оплаты с "отложенной оплатой" (банковский перевод, наличкой/наложенным при получении) могут использовать статус on-hold - если оплату нужно подтверждать (заказ не начнет выполняться пока не будет подтверждения платежа), или сразу processing, если подтверждение не требуется (наличкой при получении). И processing, и on-hold уменьшают сток, потому что это как раз статусы, с которыми вам и надо работать - они для этого и созданы. А pending - это немножко про другое.

    Подробнее: https://docs.woocommerce.com/document/managing-ord...
    Ответ написан
    Комментировать
  • Как кто пробился на фриланс-биржах?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    Как по мне, то все достаточно просто:

    1. Идем сразу на Upwork, там есть деньги и адекватные заказчики. Местные биржи - болото.
    2. Листаем список проектов, тщательно отбираем только те, которые нам подходят. Не надо подаваться на все подряд в своей нише.
    3. Задача должна быть четко по нашему профилю, в этой задаче мы должны иметь возможность кратко дать понять, что знаем как ее решить - "уже решали, вот пример, на выходе получите вот эти результаты". Фильтр - наше все.
    4. Клиент должен быть в нашем ценовом диапазоне. Если у вас ставка $20/час, а у клиента написано что средняя ставка которую он платит - $5/час, то писать ему - трата времени и коннектов. Опять же, фильтр - наше все.
    5. Отвечаем на тщательно отобранные заявки. Они должны быть свежие, если прошло полдня и более с момента публикации заявки - особого смысла писать уже нету, если только задача не нишевая / специфичная.
    6. Ответ должен быть индивидуальным, никакой копипасты. Суть ответа должна быть заточена на эту конкретную задачу. Не надо писать всю автобиографию. Самый важный первый абзац, первые 1-2-3 предложения - именно их клиент видит в message preview и они могут быть триггером чтобы открыть вашу заявку. Текст лаконичный, короткие понятные предложения, абзацы. Суть - "задачу понимаю, уже сталкивался, решается вот так, есть вот такие нюансы о которых вы не подумали, мой estimate X часов. По этой ссылке пример решения подобной задачи, а вот по этой - подробнее обо мне и моем опыте/подходе если вам интересно".
    7. Отправляем. Конверсия при таком подходе достаточно высокая.

    Дополнительные мысли:

    - 30 заявок за 1.5 года это ни о чем. На первых порах 30 заявок в неделю может быть мало, пока не научитесь хорошо фильтровать, писать отличные cover letters и пока не получите Rising Talent / Top Rated + 100% JSS.
    - Первых клиентов получить сложнее всего, да. Дальше будет легче. В том числе сами будут писать и приглашать.
    - Даже при отсутствии заказов старайтесь обходить стороной подозрительных заказчиков и стремные проекты - идея хоть как-то заработать копейку несмотря на риски может сейчас казаться не такой уж плохой, но по итогу себе же дороже выйдет.
    Ответ написан
    Комментировать
  • Почему пишет, что путь не правильный?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    Всегда используйте абсолютные пути. Всегда. И не будет таких вопросов.
    // require '../template/items-work.php';
    require get_template_directory() . '/template/items-work.php';
    Ответ написан
    Комментировать
  • Как очистить ключ от пробелов в meta_query?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    Вам поможет array_map, чтобы применить определенное действие к каждому элементу массива, и preg_replace с простенькой регуляркой, который удалит все whitespace-символы.

    <?php
    // Входящие данные
    $values = [2500, '2 999'];
    
    // Очистка от пробелов
    $values = array_map(static function($value) {
        return preg_replace('/\s/', '', $value);
    }, $values);
    
    // Запрос
    $recent2 = new WP_Query(
        [
            'showposts' => 100, // Не используйте -1, используйте достаточно большое для ваших задач число
            'meta_query' => [
                [
                    'key' => 'cena', // Не называйте данные транслитом, используйтe price
                    'value' => $values,
                    'compare' => 'BETWEEN'
                ]
            ]
        ]
    );
    Ответ написан
  • Как правильно создать ajax-тему Wordpress?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    REST API + роутинг на фронтенде
    Ответ написан
  • Как синхронизировать данные двух таблиц wp_users и wp_2_users?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    Готов поставить ящик пива, что ваша задача решается немного другим путем. Смотрите мой ответ в другом вашем вопросе: Как сделать регистрацию на wordpress в две таблицы?
    Ответ написан
    Комментировать
  • Как сделать регистрацию на wordpress в две таблицы?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    Я бы вам советовал подойти к задаче с другой стороны. На самом деле пользователи должны создаваться в одной таблице, точнее в одной паре таблиц (wp_users и wp_usermeta), и храниться в единственном экземпляре. А на втором сайте вы просто указываете, что надо использовать эту пару таблиц от первого сайта. Для этого в wp-config.php есть 2 конфигурационные константы:
    define( 'CUSTOM_USER_TABLE', $table_prefix.'my_users' );
    define( 'CUSTOM_USER_META_TABLE', $table_prefix.'my_usermeta' );

    Подробнее тут.
    Ответ написан
  • Как решить проблему с 404 ошибкой при изменении количества товаров на страницу WooCommerce?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    Если там при выборе количества записей на страницу просто добавляется параметр ?prod-count=5 к текущему URL и браузер отправляется по этому новому URL, то проще всего повесить обработчик этого get-запроса где-нибудь на template_redirect. Смотрите, есть ли GET-параметр prod-count, если да - смотрите на какой вы странице, сколько всего результатов у WC_Product_Query, сколько выводить просит prod-count. Считаете, и если получается что страница Х у вас не будет существовать - редиректите на нужную.
    Ответ написан
    7 комментариев
  • Не работает ajax сервер WAMP?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    Ошибки нужно читать, они содержат детальное описание проблемы. Разобьем вот эту ошибку на кусочки:
    Notice: Undefined index: text in D:\Wamp\www\tost\index.php on line 12


    1. Notice: - ошибка уровня notice, по сути даже не ошибка, а уведомление.
    2. Undefined index: text - индекса "text" не существует, это говорит о том, что вы пытаетесь обратиться к индексе "text" какого-то массива, но такого индекса (элемента массива) не существует.
    3. D:\Wamp\www\tost\index.php on line 12 - а вот это конкретное место в вашем коде где эта ошибка возникла. Это строка 12, она содержит вот такой код: echo 'Данные приняты - '.$_POST['text'];

    Что с этим кодом не так? Вы пытаетесь вывести элемент массива $_POST под индексом "text", но еще до того, как вы отправили данные этим самым методом POST. Чтобы этого избежать, необходимо выполнить проверку:

    <html>
    <head>
        <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
        <title>Document</title>
        <script src="jquery-3.3.1min.js"></script>
        <script src="js.js"></script>
    </head>
    <body>
    <h1>Нажать</h1>
     
    <?php
    if (isset($_POST['text'])) {
        echo 'Данные приняты - ' . htmlspecialchars($_POST['text']);
    } ?>
     
    </body>
    </html>


    В этом случае мы сначала проверяем, чтобы данные были действительно отправлены, и только тогда их выводим. Кроме того, мы используем https://www.php.net/manual/en/function.htmlspecial... чтобы обезопасить себя.
    Ответ написан
    Комментировать
  • Почему не создаются посты без перезагрузки?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    Вы не поняли как работает ajax. Данные вы отправили, пост создался. Но чтобы на странице/страницах, которые УЖЕ загружены в браузере увидеть обновления, нужно либо вручную их обновить, либо из полученного по аякс ответа сгенерировать нужный html и вставить его в эти страницы (сможете только в ту из которой инициировали загрузку). Если же вы хотите в других вкладках чтобы открытые страницы сами обновлялись когда на бекенде новые данные появились, то вам нужны другие технологии. Читайте про веб-сокеты.
    Ответ написан
    1 комментарий
  • Загрузка изображения перед его загрузкой. Как это делают?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    Для начала решите, что вам на самом деле нужно - предварительный просмотр изображения (чтобы выглядело как будто картинка загружена, пользователь видел ее в контенте который пишет) или реальная загрузка изображения на сервер. В зависимости от ответа будет разная техника.

    Осознанно учтите и взвесьте основные минусы загрузки на сервер. Самая главная - картинки на сервере будут накапливаться и вам придется разрабатывать систему определения "нужных" и "ненужных" а также механизм автоматического удаления ненужных. Потому что мусора будет много. Кто-то писал черновик и не опубликовал / закрыл окно и забил, а картинка (или даже несколько) уже загружена. Кто-то загрузил одну картинку, посмотрел, не понравилось, выбрал и загрузил другую. И так 10 раз подряд пока не подобрал картинку которая нравится. А у вас 9 ненужных картинок на сервере загружено. Через некоторое время у вас папка с загрузками вырастает до гигабайтов / тысяч файлов, вы смотрите на это и реально не понимаете что из этого используется, а что нет.

    Исходя из этого, в большинстве случае все, что вам нужно это предварительный просмотр на клиенте с помощью javascript. Это можно сделать ванильным js или использовать адекватную библиотеку типа https://github.com/blueimp/JavaScript-Load-Image которая уже решает кучу мелких задач, о которых вы еще даже не догадываетесь (например автоматический поворот по метаданным, ресайз превью в целях оптимизации производительности, crossorigin и тд).

    Если же все-таки вы решите грузить из сразу на сервер, то начните с минимального ТЗ. Используете ли вы какую-то CMS или фреймворк. Куда и как будете загружать файлы. Как будете хранить историю загруженных и очищать ненужные. И так далее. Сам процесс загрузки тривиален - у вас должен быть URL который методом PUT или POST принимает данные (изображение + любую полезную инфу, например ID/UUID черновика записи к которому картинка загружена), обрабатывает их и возвращает URL изображения. Аяксом туда шлете картинку, получаете ответ с адресом картинки на сервере, вставляете его в DOM.
    Ответ написан
    Комментировать
  • Как выявить нагрузку на CPU в index.php Wordpress?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    Дело в том, что index.php это входная точка, там всего пару строк кода. Это не один изолированный скрипт со всеми фичами, который вы можете как-то отдебажить. Он поднимает все ядро WP, там тысячи других файлов. Для отладки используется профилирование кода - Xdebug, XHProf, Tideways, Blackfire. На shared хостинге разумеется этого всего не будет.
    Ответ написан
    Комментировать
  • Зачем писать url: admin-ajax.php?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    Ваш js отправляет данные на файл-обработчик, который является входной точкой. Воспринимайте его как API endpoint. Потому что отправить запрос на файл functions.php вы не сможете, это include. А вот /wp-admin/admin-ajax.php - это не include, там поднимается слегка облегченная версия всего WordPress которая рассчитана исключительно на то, чтобы принять ваши отправленные данные, определить какой action вы хотите использовать и через этот action передать полученные данные на обработчик, который висит на этом экшне. И вот уже в functions.php вы на этот экшн в формате wp_ajax_{$action} и wp_ajax_nopriv_{$action} подключаете свой обработчик, который примет отправленные данные, сделает с ними все что нужно и вернет ответ, который в свою очередь /wp-admin/admin-ajax.php вернет обратно вашему js.

    По ссылке Пычев Анатолий более подробно с примерами. А вообще откройте в редакторе сам файл /wp-admin/admin-ajax.php и часть вопросов сама отпадет.
    Ответ написан
  • Как скрыть таксономии при добавлении поста?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    Вам погомут conditional rules.

    Создайте одно поле с выбором таксономий (городов). Это может быть поле типа select, radio, checkbox - зависит от того нужно ли вам выбирать один или несколько городов. В значения этого поля добавьте все ваши города/таксономии. Можно это сделать вручную, а можно программно заполнить из существующих таксономий.

    Дальше под каждую таксономию (город) создайте свое поле типа Taxonomy, в котором и будут выбираться термины. Включите в этом поле галочки Create Terms, Save Terms и Load Terms, а также включите Conditional Logic - именно в этом вся магия. Теперь в conditional настройте условие. Вот так это выглядит:

    5e9820dca3b3f788190769.jpeg

    А вот так это выглядит на странице редактирования записи - по умолчанию город не выбран:

    5e9820f420767468763297.jpeg

    А если выбрали город - показало поле для выбора категории в этом городе:

    5e9821140e5ab394583256.jpeg

    Вот вам экспорт этой тестовой группы полей, имопртните себе в ACF и поковыряйте:

    [
        {
            "key": "group_5e981df6cbdcc",
            "title": "Taxonomies",
            "fields": [
                {
                    "key": "field_5e981e4bb1454",
                    "label": "City",
                    "name": "taxonomy",
                    "type": "checkbox",
                    "choices": {
                        "spb": "SPB",
                        "msk": "Moscow",
                        "omsk": "Omsk"
                    },
                    "layout": "vertical",
                    "return_format": "value",
                },
                {
                    "key": "field_5e981e18b1453",
                    "label": "MSK",
                    "name": "term",
                    "type": "taxonomy",
                    "conditional_logic": [
                        [
                            {
                                "field": "field_5e981e4bb1454",
                                "operator": "==",
                                "value": "msk"
                            }
                        ]
                    ],
                    "taxonomy": "post_tag",
                    "field_type": "checkbox",
                    "add_term": 1,
                    "save_terms": 1,
                    "load_terms": 1,
                    "return_format": "id",
                    "multiple": 0,
                    "allow_null": 0
                }
            ],
            "location": [
                [
                    {
                        "param": "post_type",
                        "operator": "==",
                        "value": "post"
                    }
                ]
            ],
            "menu_order": 0,
            "position": "side",
            "style": "default",
            "label_placement": "top",
            "instruction_placement": "label",
            "active": true,
        }
    ]
    Ответ написан
    2 комментария
  • MustHave плагины для wordpress?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    Давайте для начала определим вашу роль и ваши цели.

    Если ваша роль - разработчик, то must-have плагинами будут те, которые облегчат вашу работу - Advanced Custom Fields (желательно Pro), Query Monitor, Laps и тд, или же малой кровью решать типовые задачи - Classic Editor, Disable Comments, Safe SVG, Enable Media Replace и подобные. Под "малой кровью" имеется в виду что они имеют минимальный overhead, не делают ничего лишнего и вы сами лучше все равно не напишете. Все остальное пишем сами, форкаем у других разработчиков, тюним под свои задачи и тд - со временем накапливаем собственный инструментарий.

    Если ваша роль - имплементатор (собираете сайтики на WP, но в PHP не умеете), то набор плагинов будет другим. Тут уж коллеги-имплементаторы подскажут какие плагины важны, какие нужны.

    Если ваша роль - владелец сайта, который все сам хочет делать - это ближе к имплементаторам.

    Если ваша роль - контент пилить, а все остальное вторично - просто выбирайте плагины под нужную функциональность и старайтесь всегда в голове держать простое умозаключение - чем плагин навороченнее (больше фич, больше настроек, больше страниц в админке и тд), тем он как правило медленнее. Чем бoльше таких плагинов - тем медленнее сайт. Поэтому стараемся ставить только то, что абсолютно необходимо и из доступных вариантов на фичу выбираем тот, который наиболее легковесный. В идеале - тестируем несколько штук и выбираем один.

    Теперь по целям. Чего вы хотите? Чтобы можно было быстро собрать сайт для тестирования бизнес идеи с минимальными расходами? Это одна кухня. Чтобы был легкий и быстрый контент-сайт, который выдерживает серьезный трафик? Это другая кухня. Интернет-магазин? Вообще другое. А в какой нише этот интернет-магазин? Физические товары или цифровые? А рынок местный или международный? Это все будет вас приводить к разному набору плагинов. Думаю, смысл уже понятен.
    Ответ написан
    2 комментария
  • Добрый день, как писать на новом фреймворке корректно?

    HeadOnFire
    @HeadOnFire
    PHP, Laravel & WordPress Evangelist
    Лучше 3 года копипастить адекватный код, написанный опытными и светлыми головами, чем городить свои костыли и не только не развиваться, а тупо скатываться в бездну говнокода.
    Ответ написан
  • WordPress, как скрыть информацию из профиля пользователя от поисковиков?

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