• Как убрать выбор страны Woocommerce?

    @werwolflg
    Я отключил проверку доставки таким образом в файле темы functions.php.
    add_filter( 'woocommerce_cart_needs_shipping', 'filter_function_disable_shipping' );
    function filter_function_disable_shipping( $needs_shipping ){
    return false;
    }
    Само поле убирается так:
    add_filter( 'woocommerce_checkout_fields' , 'custom_override_checkout_fields' );
    function custom_override_checkout_fields( $fields ) {
    unset($fields['billing']['billing_country']);
    return $fields;
    }
    Ответ написан
    1 комментарий
  • На каком этапе обучения стоит учить ООП?

    saboteur_kiev
    @saboteur_kiev Куратор тега Python
    software engineer
    ООП это не та тема, которую изучил между for и while
    это довольно большой и комплексный кусок знаний, который в любом случае придется учить долго.
    Поэтому раньше начнешь - раньше будет результат.
    Ответ написан
    Комментировать
  • Как найти участки кода несовместимые с PHP 8.1 версии?

    pxz
    @pxz
    ✔ Совет: Вам помогли? Отметьте ответы решением.
    Есть специальная тулза для этого — Rector.

    Позволяет выбрать целевую версию PHP и покажет в отчёте места, н совместимые или написанные в стиле старых версий. Также позволяет большинство участков кода отрефакторить автоматически.

    https://github.com/rectorphp/rector
    Ответ написан
    3 комментария
  • Как перенести недоступный сайт?

    iDx
    @iDx
    Полностью скопируй папку с сайтом на новый хостинг, бэкап базы данных залей, отредактируй wp-config.php.
    в гугле ищется как "перенос сайта wordpress на новый домен"
    Ответ написан
    1 комментарий
  • Как подключить скрипты в footer в Wordpress?

    Shucach
    @Shucach
    В WordPress лучше всего подключать через function.php таким образом
    add_action( 'wp_enqueue_scripts', 'true_include_myscript' );
    function true_include_myscript() {
        wp_enqueue_script( 'themename', get_stylesheet_directory_uri() . '/js/jquery.polaris.js', array('jquery'), null, true );
    }

    Значения true если нужно отобразить подключения в футере и false если в хедере.
    Ответ написан
    Комментировать
  • Как написать бота отслеживающего скидки на маркетплейсах?

    ipatiev
    @ipatiev
    Потомок старинного рода Ипатьевых-Колотитьевых
    Ну что вы как дети?
    Каждый раз этот вечнозелёный вопрос обрастает гроздьями любопытных.
    Спарсить весь интернет мы хочем, а научиться пользоваться одним поисковым сервисом - не можем.
    Ответ написан
    Комментировать
  • Лучшие практики создания тем на WordPress?

    @Kvason
    Веб-разработчик
    Элементор удаляй и больше не вспоминай, переделка готовых тем хороший вариант для малобюджетных проектов, но иногда написать с нуля проще чем все под себя переделывать. Отличный вариант для практики и хорошего портфолио с нуля верстка + натяжка на вп. Из плагинов я чаще всего использую Cyr-To-Lat и ACF либо Pods(по сути тот же ацф, но поменьше и полегче), еще для мультиязычности какой-нибудь Polylang либо WPML(но это если не жаль заплатить). В основном же обхожусь без плагинов и этой троицы вполне хватает, конечно если у тебя будут комменты либо формы Akismet лишним не будет, но это уже по потребности, то же касается WP Super Cache, All import и подобные вещи
    Ответ написан
    1 комментарий
  • Зачем задавать приватный модификатор доступа для свойств класса?

    Maksclub
    @Maksclub Куратор тега PHP
    maksfedorov.ru
    У вас очень логичный вопрос на счет сеттера: сеттер полностью уничтожает задумку с инкапсуляцией. Правильно это называется "семантическое нарушение инкапсуляции" — то есть как-бы мы инкапсулировали, но по факту назад открыли прямую запись в свойство напрямую. Все доводы "ну мы можем в сеттере валидировать" не корректны

    Правильным способом будет не использовать сеттеры. Вот моя статья на эту тему:
    https://habr.com/ru/post/469323/

    Более подробно: каждый класс нужно проектирвовать так, чтобы данные внутри были максимально связаны. Например каждый метод работать должен в хорошем случае с максимальным числом полей класса, тогда у него высокий cohesion... В тоже время снаружи наужно работать с максимальн омалым числом метода, тогда будет низкая связанность (coupling). Это пара принципов из GRASP.
    Когда вы делаете сеттеры и геттеры, то у вас данные внутри между собой почти никак не взаимодействут: с геттером работают снаружи, с сеттером работаю снаружи — весь класс нараспашку, а в нем в 100% случаев появляются данные, которые вместе не должны находиться и никак не связаны — анрушена и абстракция и инвариант и много чего еще...

    Про инвариант отдельно: например есть платеж, у него есть значение, с которым платеж инициирвоан (initValue), есть значение холда (holdAmount) и есть значение чарджа на списание (chargeAmount)
    Когда вы работаете с платежом, контролируя ивнариант в самом классе, то ваш каждый метод првоеряет др значения и позволяет перейти к др состоянию... методов будет 2-3, все инкапсулировано и безопасно.

    Например:
    class Payment {
         pub func charge(amount int) void {
              if (this.holdAmount < amount && this.initAmount < amount) {
                   throw new PaymentException('Unavailable charge amount')
              }
    
               if (this.status === PaymentStatus:finish) {
                   throw new PaymentException('Payment already fisnished')
              }
    
              this.chargeAmount = amount
              this.holdAmount -= amount
              this.status = PaymentStatus:finish
         }
    }


    Тут в одном методе полные проверки и класс сам контролирует все состояние внутри, также соблюдается закон Деметры. У даннго кода высокий cohesion (из GRASP), тк внутри идет плотная работа с внутр данными (значит они корректно тут закроекны) и низкий coupling ( с теми данными для данного кейса только один метод работы, все внутри)

    Когда вы раскроете сеттерами и геттерами, то ваше состояние становится непредсказуемо и полагается только на то, что снаружи точно подумали об инварианте (нет)
    Ответ написан
    18 комментариев
  • Почему при работе Linux Ubuntu все дергается?

    @Reikj
    Установите linux mint, и не будете знать проблем! :)
    Ответ написан
    7 комментариев
  • Можно ли использовать токен пользователя как альтернативу токена от csrf атак?

    @kandrash
    Кратко о себе
    Собственные решения "улучшающие безопасность" в 100% случаев ведут к новым дырам, через которые вас поимеют. Я б не рекомендовал.
    Ответ написан
    Комментировать
  • Как загрузить csv-файл на php?

    Compolomus
    @Compolomus Куратор тега PHP
    Комполом-быдлокодер
    https://www.php.net/manual/ru/tutorial.forms.php https://www.php.net/manual/ru/features.file-upload... -
    PHP-страницу upload.php с формой загрузки CSV-файла

    https://www.php.net/manual/ru/function.mkdir.php -
    Рядом с файлом upload.php требуется создать папку /upload/

    https://www.php.net/manual/ru/splfileobject.fgetcsv.php -
    прочитав CSV-файл.

    https://www.php.net/manual/ru/splfileobject.constr... -
    и создать в ней файлы

    https://www.php.net/manual/ru/splfileobject.fwrite.php -
    соответствующим содержимым
    Ответ написан
    Комментировать
  • Как правильно связать php сайт с mysql?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    На частные вопросы ответили в комментариях, поэтому ответим на вопрос из заголовка.

    Чтобы соединить сайт с mysql, в РНР вообще-то есть два API - mysqli и PDO. Несколько лет назад с mysqli вообще невозможно было нормально работать, но на данный момент они выровнялись, хотя PDO все равно удобнее, по трем причинам
    1. Единый интерфейс при работе с различными СУБД (неактуально, если mysql для нас является синонимом слова база данных)
    2. Набор функций-хелперов для получения данных из БД в различных форматах (при желании легко воспроизводится вручную)
    3. Именованные плейсхолдеры (для некоторых это главная причина использовать PDO)

    Но в целом, как я говорил выше, сейчас можно использовать любое API. Главное - не использовать тот древний говнокод, который приведён в вопросе.

    1. Создаём файл`config.sample.php` куда кладем все настройки приложения, в том числе базы данных
    return [
    	'db' => [
    		'host' => '127.0.0.1',
    		'username' => '',
    		'password' => '',
    		'dbname' => '',
    		'port' => 3306,
    		'charset' => 'utf8mb4',
    	],
    ];

    2. В файле, который включается во все скрипты сайта, добавляем код
    if (!file_exists('config.php'))
    {
    	throw new \Exception('Create config.php based on config.sample.php');
    }
    $config = require 'config.php';

    3. И дальше в этом же файле пишем собственно нормальный код подключения к БД
    либо к mysqli
    // включаем режим информирования об ошибках
    mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
    // подключаемся к серверу
    $dbc = $config['db'];
    $db = new \mysqli($dbc['host'], $dbc['username'], $dbc['password'], $dbc['dbname'], $dbc['port']);
    // не забываем установить кодировку, чтобы не было ошибок с кракозябрами
    $db->set_charset($dbc['charset']);

    либо к PDO
    $options = [
        \PDO::ATTR_ERRMODE            => \PDO::ERRMODE_EXCEPTION,
        \PDO::ATTR_DEFAULT_FETCH_MODE => \PDO::FETCH_ASSOC,
        \PDO::ATTR_EMULATE_PREPARES   => false,
    ];
    $dbc = $config['db'];
    $dsn = "mysql:host=$dbc[host];dbname=$dbc[dbname];charset=$dbc[charset];port=$dbc[port]";
    $pdo = new \PDO($dsn, $dbc['username'], $dbc['password'], $options);

    После того как будет освоена работа с системой контроля версий (а по-хорошему это надо было сделать уже давно) добавляем config.php в файл .gitignore
    Таким образом на каждом хосте, где исполняется этот код, будет собственный файл с настройками, создаваемый по образцу из config.sample.php

    Да, и Очень Важное Дополнение:
    почему нельзя сделать 1 соединение для сайта и не тратить каждый раз время на коннект к БД?

    Никогда не следует переживать по поводу воображаемых проблем. Вот только когда создание коннекта каждый раз станет реальной проблемой, только тогда и начинать переживать по этому поводу и искать пути решения (спойлер: никогда).
    Ответ написан
    14 комментариев
  • Почему php не может подключиться к БД?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    Чтобы узнать, почему не работает соединение или запрос, надо настроить РНР так чтобы он отображал ошибки, а mydsqli - чтобы оно бросало исключения.
    То есть код должен выглядеть вот так

    <?php
    // видеть все ошибки!
    ini_set('display_errors',1);
    error_reporting(E_ALL);
     // подключаем настройки
    require_once 'connect.php';
    
    // включаем режим информирования об ошибках
    mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
    // подключаемся к серверу
    $link = mysqli_connect($host, $user, $password, $database);
    // не забываем установить кодировку, чтобы не было ошибок с кракозябрами
    $mysqli->set_charset('utf8mb4');
       
    // выполняем операции с базой данных
    $query ="SELECT * FROM foo";
    $result = mysqli_query($link, $query);
    // дальше делаем что нужно
    
    // и кстати, в большинстве случаев закрывать подключение не надо


    ЗЫ. На боевом сервере ошибки на экран выводить конечно не стоит, а их надо писать в лог (собственно, именно поэтому все эти die - это ужас). И на боевом сервере display_errors надо отключать, а log_errors наоборот - подключать.
    Если совсем не можешь найти, где у сервера висит лог ошибок, можешь задать свой собственный, с помощью функции ini_set('error_log','/путь/к/файлу');. Но только размещать его надо разумеется в папке недоступной пользователям сайта


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

    Если разобраться, то код or die("Ошибка1 " . mysqli_error($link)); очень смешной (это не к тебе претензия, никто не ожидает от тебя понимания таких тонкостей, которые не то что новички, а половина здешних "кураторов" не понимают).
    Что тут происходит?
    слово or die (которое на самом деле вообще нельзя никогда писать) пишут тогда, когда ожидают что в переменной $link будет значение false. Но если в $link будет false, то тогда её бессмысленно подставлять в mysqli_error. Именно поэтому для получения ошибки соединения в мускули есть отдельная специальная функция.

    Но как я говорил выше, применять её не следует, как и or die.
    Ответ написан
    2 комментария
  • Как реализовать логику статистики на сайте?

    AgentSmith
    @AgentSmith
    Это мой правильный ответ на твой вопрос
    таблица Переходы.
    Поля:
    id, тип_перехода, дата, значение_счётчика

    Это первая глава в любой книге по базам данных. Книги читать - это не твоё, верно?
    Ответ написан
    4 комментария
  • Как раскодировать JSON в PHP?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    наверное, такой вопрос и надо задавать? Не "как раскодировать json", а как удалить лишние слеши в строке?
    И внезапно ответ найдется сам собой
    Ответ написан
    Комментировать
  • Чем плох md5(md5($pass)) для пароля?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    Иногда смотришь на вопрос и не понимаешь, о чем он.
    Судя по вопросу и цифрам в нем, автор и так уже осведомлен о правильных способах хэширования и должен уже знать ответ на свой вопрос.

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

    Возможно, непонимание происходит оттого, что существует не один, а несколько векторов атаки на пароль.
    1. Поиск хэша по "радужным таблицам" (rainbow tables): огромным базам данных, где собираются заранее посчитанные хэши для любых возможных строк.
    2. Метод грубой силы (bruteforce): перебирать все комбинации символов и применять к ним хэширующую функцию до тех пор, пока она не вернёт искомый хэш.
    3. Поиск по словарю. Похож на брутфорс, но перебор не всех возможных значений, а всего нескольких тысяч самых популярных паролей, типа "123", "password" и пр.
    phpfaq.ru/tech/hashing

    И только одного элемента недостаточно, а нужны все в комплексе:
    - Хэширующая функция должна иметь большую вычислительную сложность, чтобы усложнить подбор перебором. по этой причине md5() не подходит
    - Хэш должен быть посолен уникальной солью, чтобы нельзя было, затратив 1 раз кучу вычислительных усилий, заранее построить хэши для любых комбинаций символов. По этой причине фарш без соли - деньги на ветер.
    - Пароль не должен быть слишком простым, иначе даже медленный перебор его раскроет. Этот момент тоже надо учитывать
    Ответ написан
    Комментировать
  • Что скажете про курсы веб-разработки Скиллбокса?

    sergey-gornostaev
    @sergey-gornostaev
    Седой и строгий
    В очередной раз повторю: Подавляющее большинство курсов - бесполезная херня. Интересующий вас - не исключение.
    Ответ написан
    5 комментариев
  • Как сделать скидку на товар в шаблоне Opencart через PHP?

    Immortal_pony
    @Immortal_pony
    Во-первых, если выполнить ваш код, то результат будет 193.71, а на 0.18. Проверьте, что в price у вас лежит именно то что вы написали.

    Во-вторых, формула для вычисления скидки у вас неправильная. Вы вычисляете 3%, а вам нужно уменьшить price на 3%. Например, так:

    $salePrice = $price - ($price/100*3);

    Ну и в шаблоне потом
    <?= $salePrice ?>
    Ответ написан
    Комментировать
  • Как перенять объектно-ориентированное мышление?

    tzlom
    @tzlom
    Очень просто.
    Для начала - признайтесь себе что процедурное программирование у вас тоже страдает (иначе бы у вас не было этого вопроса), это не страшно, но с этим тоже надо что-то решать.
    Берёте любой свой процедурный проект (лучше маленький чтобы не застрять в рутине).
    Шаг первый - всё есть функция, поэтому весь код вне функций кладёте в функции, итого у вас получается что вне функций идёт только вызов main() (или как вы её назовёте)
    Второй шаг - функции работают только с тем, что в них передали. Удаляете глобальные переменные.
    Появляется проблема глубокой вложености, т.е. у вас внутри вызова А вызывается Б а в ней В которая хочет переменную из области видимости А, и таких случаев много. Тащить в Б все эти переменные - грустно и печально, поэтому делаем хитрость, каждая функция первым аргументом получает массив неких значений. Правило одно - функции не меняют имена и количество переменных в массиве, только значения.
    Третий шаг - функции должны быть короткими, выносите повторяющийся код в отдельные функции, если в функции используется много переменных - это повод разбить её на несколько меньших.
    Четвёртый шаг - вы уже пишете на ООП. Если 3 шага правильно сделаны, то осталось только оформить это дело согласно новым правилам - первый аргумент-массив это члены класса, соответственно функции использующие одинаковый массив - методы этого класса, прийдётся разобраться с доступом к полям и отдельными зависимостями, но это уже будет просто и понятно когда ты до этого доберёшься.
    Ответ написан
    4 комментария
  • Как перенять объектно-ориентированное мышление?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    Т.е. сложно понимаю, что "засунуть" в один объект, что в другой, что должно быть статическим методом, что приватным и тд.


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

    То есть по сути наше приложение - один объект. У него внутри вообще все. У этого объекта есть один метод - обработай запрос. Когда внешний мир его вызывает, меняются значения каких-то переменных, вызываются какие-то внутренние "приватные" для внешнего мира функции, и делается работа.

    Теперь задумаемся о декомпозиции всего этого хаоса. Мы находим какую-то задачу, которую выполняет наш код (например какую функцию вызвать для обработки каждого конкретного запроса) и выносим это в отдельный объект. Отправка email-ов - отдельный объект. Весь SQL зашиваем в отдельный объект. Соединение с базой - объект. Пользователи - объекты. Все - объекты.

    И главное, у каждого объекта есть своя область ответственности. UNIX way. Каждый объект делает что-то одно и делает это хорошо. Бывает так что ну... нужно сделать так что бы один объект делал две вещи. НЕ вопрос, мы можем его попросить сделать что-то сложное, а он будет как хороший менеджер тупо делегировать работу другим объектом. То есть он и сложную штуку сделает, и сам не будет знать как она делается.

    А все безхозные функции, которые не пренадлежат никаким объектам (например функции порождающие объекты) можно вынести в статические методы. Главное что бы статичесих переменных у нас небыло (ибо это те же глобальные переменные). И поменьше публичного ибо черт его знает что эти разработчики будут использовать. Причем "те разработчики" это вы завтра.

    Вообщем писав всё время на процедурке, сложно перейти на ооп.


    Просто не думайте что это что-то "принципиально другое". Это та же самая процедурка, просто благодаря классам и объектам, вы можете порезать систему на маленькие модули. Данные будут лежать рядом с процедурами и у вас будет больше контроля за происходящим.

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

    Подскажите, какой проект начать писать (гостевая, блог), или может начать изучать фреймворк.


    Фреймворки универсальны, а значит чистого ООП там быть не может. Во всяком случае нет ни одного фреймворка на котором стоит учиться ООП.

    Есть хорошие упражнения на развитие понимания объектно-ориентированного проектирования. Например вот: https://habrahabr.ru/post/206802/

    Сразу хочу отметить что это крайности. Упражнения же. Они должны ограничивать вас что бы заставлять думать и задавать правильные вопросы.

    Или может подскажите книгу/сайт где пошагово в ооп написан какой-то проект, чтобы быстрее пришло понимание.


    Так вы научитесь делать один конкретный проект а на втором вы уже проиграете. Так дела не делаются. Надо разобраться с причинами появления идеи ООП. Ну то есть что было до. Можно еще с функциональным программированием попробовать разобраться. В PHP оно слабо применимо, но основные идеи очень тесно переплетаются с ООП и познав немного функциональщины ваше ООП будет лучше. Да и если про ООП вы можете найти много булшита, про функциональщину врут мало.
    Ответ написан
    3 комментария