Профиль пользователя заблокирован сроком с 10 апреля 2022 г. и навсегда по причине: систематические нарушения правил сервиса
Ответы пользователя по тегу PHP
  • Как удалить файл при условии, что нет одного из одноименных с другим расширением?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    Вот ведь любители извращений
    foreach (glob('/dir/*.webp') as $f) {
        $filename = pathinfo($f, PATHINFO_FILENAME);
        if (count(glob('/dir/$filename.*')) == 1) {
            только один, можно удалять
        }
    }


    по уму конечно надо прочитать все файлы за раз и потом сгруппировать по имени, но от такого сложного алгоритма у бедняги ум за разум зайдет, надо его пожалеть
    Ответ написан
  • Как не дожидаться окончания file_get_contents?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    в простейшем варианте - fastcgi_finish_request(), если запросов не очень много
    если много, то только сервер очередей
    Ответ написан
    Комментировать
  • Как можно защитить XML файл от открытия любым человеком?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    Не класть файл в открытый доступ.
    Отдавать скриптом, который принимает в параметре имя файла, проверяет авторизацию и отдает файл с соответствующими заголовками
    "как отдать сгенерированный РНР скриптом ХМЛ файл" в гугле можно найти чуть более чем дофига примеров
    Ответ написан
    1 комментарий
  • Почему не получается записать в базу данных?

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

    Поэтому сначала учимся правильно соединяться.
    Весь этот детский лепет "не могу соединиться с БД" выкидываем и пишем нормальный код, который сам, без всяких проверок, сообщит нам об ошибках.
    В случае mysqli это
    mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
    $link = mysqli_connect($host, $user, $pass, $db_name);
    $link->set_charset("utf8mb4");

    Здесь первая строчка отвечает как раз за информирование об ошибках

    Кроме того надо не забыть про ошибки РНР
    Во-первых, всегда в коде должно быть error_reporting(E_ALL);
    Плюс на домашнем компе ini_set('display_errors',1);, а на боевом - ini_set('display_errors',0);ini_set('log_errors',1);, и смотреть, соответственно, в логах.

    После этого переписываем запрос. Причем так, чтобы данные в БД всегда попадали отдельно от самого запроса. Это непреложное правило, которое надо соблюдать всегда.
    Для этого надо
    • Заменить все переменные в запросе на специальные маркеры, которые называются плейсхолдеры или параметры, а по сути - просто знаки вопроса
    • Подготовить запрос к исполнению с помощью функции prepare(). Эта функция принимает строку запроса и возвращает экземпляр специального класса stmt, с которым в дальнейшем и производятся все манипуляции
    • Привязать переменные к запросу.
    • Выполнить подготовленный ранее запрос с помощью с помощью execute()

    В mysqli это будет так
    $sql = "INSERT INTO `events` (`title`, `discription`, `date`, `img`) VALUES (?,?,?,?)";
    $stmt = $link->prepare($sql);
    $stmt->bind_param("sssss", $title, $discription, $date, $path);
    $stmt->execute();

    bind_param() принимает в качестве параметров все переменные, которые должны попасть в запрос, в том же самом порядке, в котором стоят плейсхолдеры в запросе. Но кроме того, сначала в этой функции должны быть указаны типы для всех переменных, в виде строки, где тип переменной обозначается одной буквой. То есть букв в этой строке должно быть ровно столько, сколько дальше будет переменных. К счастью, можно особо не париться с типами и для всех переменных указывать тип "s".

    И тогда никаких ошибок запроса уже никогда не будет. Не говоря уже о том что при любых других вариантах твой сайт поломает любой пятиклассник

    Но по-хорошему для работы с БД в РНР лучше использовать PDO, Тем более что там колупаться с bind_param не нужно, а можно сразу отправить все данные в execute

    Подключение
    $host = '127.0.0.1';
    $db   = 'test';
    $user = 'root';
    $pass = '';
    $port = "3306";
    $charset = 'utf8mb4';
    $options = [
        \PDO::ATTR_ERRMODE            => \PDO::ERRMODE_EXCEPTION,
        \PDO::ATTR_DEFAULT_FETCH_MODE => \PDO::FETCH_ASSOC,
        \PDO::ATTR_EMULATE_PREPARES   => false,
    ];
    $dsn = "mysql:host=$host;dbname=$db;charset=$charset;port=$port";
    $pdo = new \PDO($dsn, $user, $pass, $options);

    Здесь за информирование об ошибках отвечает параметр PDO::ERRMODE_EXCEPTION, а остальные просто для удобства/корректности.

    Выполнение запроса
    $sql = "INSERT INTO `events` (`title`, `discription`, `date`, `img`) VALUES (?,?,?,?)";
    $stmt = $link->prepare($sql);
    $stmt->execute([$title, $discription, $date, $path]);
    Ответ написан
    2 комментария
  • Как избежать повтора инклюдов в ООП PHP?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    Из всей той ерунды, которую тут уже успели понаписать, и ещё понапишут самозваные "кураторы" и эксперты, единственно полезным является ответ Андрей Ежгуров
    Но он отвечает на следующий твой вопрос.

    А ответом на текущий является

    Передавать его в класс параметром

    Это единственно правильная практика, пусть она даже и кажется тебе не очень хорошим решением.
    Только не целиком конфиг а лишь те опции, которые нужны данному классу.
    Это то как на самом деле работает ООП. Для закрепления материала можешь почитать про dependency injection.
    Ответ написан
    6 комментариев
  • Как добавить только не пустые параметры в бд?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    Начнем с того, что "if isset" не проверяет, "пустая ли переменная". Она только проверяет, было ли переменной присвоено какое-то значение.
    Что, в свою очередь, очень забавно смотрится после того как буквально строчкой выше каждой переменной уже было присвоено значение.
    Ну то есть это условие сработает, если в запросе вообще не было такого поля, но во-первых, мне кажется не это имелось в виду, а во-вторых, если поля не было, то уже при присвоении будет ошибка, и после этого делать isset уже как-то глупо.

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

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

    В общем случае нам надо список полей, которые мы можем добавить в БД. Чтобы не колупаться с отдельными переменными. А дальше все просто - цикл, который проверяет на пустоту и формирует сам запрос плюс массив с данными для него.
    $fields = ['phrase','secret','custom1', ...];
    $conditions = [];
    $params = [];
    foreach($fields as $key) {
        if (strlen($val = trim(filter_input(INPUT_POST,$key)))) {
            $conditions[] = "`$key` =?";
            $params[] = $val;
        }
    }
    if ($params) {
        $sql = "INSERT INTO table SET ".implode(",",$conditions);
        $pdo->prepare($sql)->execute($params);
    }
    Ответ написан
    Комментировать
  • Тип возвращаемых значений метода. Как правильно?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    Зависит от сценария.
    Судя по коду, отсутствие активности - это не ошибка.
    То есть в данном случае можно вернуть null.

    А вот функции, которые возвращают false в случае ошибки устарели 20 лет назад. И если метод должен вернуть объект, но не может, то он должен кинуть исключение
    Ответ написан
    Комментировать
  • Как сделать погрузку контента по нажатию кнопки на php?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    делается просто:
    spoiler
    дополнительный контент


    можешь не благодарить
    Ответ написан
    1 комментарий
  • Как представление в MVC делает переход по id?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    Переход делает не "представление", а твой браузер
    Представь себе
    Ответ написан
    Комментировать
  • Почему сессия начинается каждый раз заново и она не сохраняется?

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

    Хотя конечно наиболее вероятная причина - Бом не даёт стартовать сессию, а ты этого не видишь потому что задавлены ошибки в пхп.
    Ответ написан
  • Как отправить POST запрос в другую дерикторию?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    /external-form/resources/views
    Ответ написан
    Комментировать
  • Почему не выводятся данные из БД на сайте?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    Ошибка Couldn't fetch mysqli обычно означает, что соединение с бд уже было закрыто
    Ответ написан
  • Ошибка подключения к mysql. Почему?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    В принципе Rsa97 уже все написал, но хочу подчеркнуть, что function query изначально было дурацкой идеей.
    Функция-то правильная, но вот название надо было давать другое.

    А, главное, если всё равно используется свой класс DB, то какой смысл было екстендить PDO, становится совсем непонятно.
    Ведь написать DB::query( тупо проще чем DB::$dbs->query(
    И с архитектурной точки зрения так будет в миллион раз правильнее.
    Ну это если не считать что сам по себе статический класс DB это решение так себе. Но для процедурщины сойдет.
    Ответ написан
    Комментировать
  • Как перенести строку в GET параметре?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    http_build_query()
    Ответ написан
    Комментировать
  • Объединить динамическое кол-во массивов в один массив PHP?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    array_merge()
    Ответ написан
    Комментировать
  • Почему 0 возвращает fasle?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    Вопрос конечно странный, а ответы так вообще ужас, но если речь идет о строгом сравнении, то в Твиге для этого используется оператор same as.

    То есть если нужно чтобы при нуле отображение было, а при false - нет, то пишем
    {% if count is not same as (false)%}

    Плюс, как выяснилось, твиговское empty не включает 0, то есть можно написать и так
    {% if count is not empty %}
    Ответ написан
    Комментировать
  • Как отдать файл, но перед этим его выполнить через .htaccess?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    Этот файл выполняется.
    .htaccess здесь не при чем
    Этот код - огромная дыра в безопасности. по меньшей мере делай basename($_GET['path']);
    Ответ написан
    Комментировать
  • Как реализовать постоянное подключение к бд?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    Никакое "постоянное" соединение с БД не нужно.
    Надо просто не запускать игры на хостинге за три копейки.

    "Хостинг", на котором нет таких нелепых ограничений, называется VPS
    Ответ написан
    9 комментариев
  • Как записать время по русски в бд?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    НИКАК не записывать!

    Вместо этого хоть немного узнать как работают базы данных.
    В mysql есть тип данных time - вот его надо поставить для колонки duree и писать в него только длительность.
    А минуты добавлять при выводе. Хоть на русском, хоть на китайском.

    И почитать про нормальную защиту от SQL инъекций.
    Вот эта фигня - str_replace("'","\'" - это мёртвому припарки.
    Ответ написан
    3 комментария