Задать вопрос
Ответы пользователя по тегу PHP
  • Как изменить названия файлов на нормальные после распаковки архива?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    В общем если я правильно понимаю, вам приходят как архивы, как сделанные под виндоус, с именами файлов в кодировке 1251 - и они распаковываются под виндоус правильно, так и сделанные под нормальными операционными системами, и в них имена закодированы в утф-8
    Если у вас есть возможность определять, где был сделан файл, то можно использовать эту информацию при перекодировании.

    Ну или тупо в лоб - искать в имени файлов русские буквы в той или иной кодировке, например 1251. То есть символы с кодами B0-EF. Если не встретились - перекодировать из утф в 1251
    Ответ написан
  • Как устранить Undefined array key после назначения переменных через explode()?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    На "западном аналогичном этому сайте" только что случайно наткнулся на красивое решение.
    $arrdata = array_pad(explode('|', $file[0]), 666, '');

    где 666 - это количество колонок, которое должно быть после explode.
    array_pad добьёт их пустыми строками. можно поставить нули при желании.
    Ответ написан
    22 комментария
  • Как исправить Fatal error: Uncaught Error: Call to undefined function mysql_fetch_assoc()?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    поменять на mysqli_fetch_assoc
    а, не
    поменять на какое-то $obj_sql->FetchAssoc()
    Ответ написан
    Комментировать
  • PDO не добавляет запись с такими символами что делать?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    ;charset=utf8mb4 в DSN
    Ответ написан
    Комментировать
  • Чистый php, если нет Бд, то можно ли её создать?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Можно, но код, который создает БД при ошибке - это глупость.
    Так не делают.

    Можно создать отдельный скрипт для настройки окружения, который создаст БД и таблицы например.
    В этом скрипте просто не указывать 4-й параметр в mysqli_connect.
    И дальше просто написать mysqli_query() c запросом создания таблицы.

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

    spoiler
    И отучайтесь уже писать этот говнокод, or die("Ошибка соединения с БД." . mysqli_error($link));
    он и так-то всегда был признаком профнепригодности, а в современном РНР уже и вовсе не имеет смысла
    Ответ написан
    5 комментариев
  • Как сделать безопасный "Запомнить меня" на сайте?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Сгенерировать сильно уникальный токен, что-нибудь вроде random_bytes(16), положить его в БД и в куки

    > Как предотвратить несанкционированную авторизацию на случи, если у пользователя украдут cookie?

    Никак. В принципе, вся безопасность современного веба завязана на предположении, что куки не украдут. В супер-важных приложениях, типа банковских, можно дополнительно проверять IP адрес, его подделать невозможно. И при смене адреса просить перелогиниться. Но в обычном приложении это будет скорее неудобством.

    > Как идентифицировать его, что куки используется не на другом устройстве?

    Ну можно по идее запоминать устройство, по user agent. Но это придется отдельно хранить авторизации на всех устройствах. Но если покрадут куки, то уведут и юзер агент.

    Причем все это относится и к обычной авторизации, без функции "Запомнить меня". Так что если эти вопросы до сих пор вас не волновали, то и сейчас по идее не должны.
    Ответ написан
    1 комментарий
  • В запросе SQL в php условия в кавычках как?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Никогда не понимал любителей ломать пальцы обо все эти точечки-кавычечки-запяточечки. Это же надо так запариться, старательно после каждого слова выписывая пунктуацию. Есть же нормальные двойные кавычки.
    "mysqldump -u$user -p$password --single-transaction --force --opt --where 'ENTITY_FIELD = STATUS_ID AND ASSIGNED_BY_ID >0' $database $table > relations.sql"
    Ответ написан
  • Как перейти на другой сайт с POST запросом?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Это называется Межсайтовая подделка запросов и ни один нормальный банк не даст ее сделать.
    А так -то отправлять форму яваскриптом, ничего экстраординарного.
    Ответ написан
  • В чем разница обычного импорта и обращение с косой чертой?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Комментировать
  • Как типизировать ключ и значение массива?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Типизировать ключи особого смысла нет, а для значений/структуры массива нативного решения нет, надо делать руками.
    Если под "типизацией ключей" имеется строго определенный набор ключей, то это называется DTO/ValueObject. То есть тупо вместо массива используется объект, в котором структура его свойств может быть четко определена.

    Для типизации же значений служат коллекции Вот, например, недавний пост, но вообще их тыщи.
    Ответ написан
    Комментировать
  • Как сгрупировать значения multiselect инпута в подмассивы если в форме несколько multiselect инпутов с одним названием tags[]?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Если в форме несколько multiselect инпутов с одним названием tags[], то, разумеется, никак.
    Чтобы при сохранении формы значения из отдельных инпутов были в подмассиве массива tags, надо добавить эти подмассивы. Л - Логика.
    tags[0][]=
    tags[1][]=
    и так далее
    Ответ написан
    9 комментариев
  • Когда стоит начинать учить фреймворки?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Ну, по-хорошему, ещё рановато.
    Всё-таки, фреймворки служат для ускорения разработки веб-приложений, а не одностраничных черновиков.
    При чем это очень важный момент.
    Не использовав в своей работе всё, что требуется при разработке веб-приложения (в том числе безопасность, следование рекомендациям протокола НТТР, валидация данных, и примрно ещё десяток нужных вещей) - то не сможешь реально понять, как много фреймворк делает за тебя.
    Ответ написан
    Комментировать
  • Как удалять файлы с сервера по условию, что они не используются в текущий момент?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    В таких условиях надо делать вытесняющий кэш.
    Если при запросе нового файла выясняется, что для него нет места, то удаляется самый старый файл.

    Хотя конечно непонятно, как это всё поможет в ситуации, когда заходят посмотреть сразу 20 разных событий.
    Ответ написан
    1 комментарий
  • Почему не работает php внутри html?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Причин может быть примерно миллион.
    Например, сервер смотрит на файлик .htaccess и в упор его не видит
    Для начала надо уточнить, что все это крутится под веб-сервером Апач и что в нем включена директива AllowOverride
    Ответ написан
  • Почему функция sort не сортирует, а выдает bool?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Наверное потому что она так устроена? И это поведение описано в документации?
    Ответ написан
    3 комментария
  • Как выполнить вызов метода в другом методе?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    call_user_func нинужна
    class A
    {
        function execute($function, $params = []) {
            return $function(...$params);
        }
        function payload($param) {
            return $param * $param;
        }
    }
    $a = new A;
    echo $a->execute([$a, 'payload'], [5]);


    а можно ещё так, если объект тот же самый

    class A
    {
        function execute($function, $params) {
            return [$this,$function](...$params);
        }
        function payload($param) {
            return $param * $param;
        }
    }
    $a = new A;
    echo $a->execute('payload', [5]);
    Ответ написан
  • Как понять что делает данный код php?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Гадость.
    Тут даже смотреть не надо чтобы понять, что код делает гадость

    код ниже после __halt_compiler(); никак не интерпретируется языком PHP, что явно следует из названия этой функции.
    Ответ написан
    1 комментарий
  • Насчет экспорта таблицы MySQL в Excel средствами PHP?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Ну например можно генерить html

    Кстати, в этом примере просто попробуйте Content-Type: text/csv
    только вместо разделителя тогда лучше использовать точку с запятой.
    Ответ написан
    2 комментария
  • Какой лучше взять ORM?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Это хороший вопрос, но ответ на него зависит от вашего уровня. Очень сильно зависит.
    Специалисты вам наверняка посоветуют Doctrine или Cycle. Но вы их явно не потянете.
    Для знакомства с ORM я бы порекомендовал Eloquent, при всех минусах этого выбора.

    Но если честно, то учитывая, что вы ищете замену RB, я бы порекомендовал начать с самого простого.
    spoiler
    Написать ORM руками. Причем даже не классический, поддерживающий связи и квери билдер, а совсем простой Table Gateway, типа такого:
    abstract class BasicTableGateway
    {
        protected $db;
        protected $table;
        protected $fields;
        protected $primary = 'id';
    
        public function __construct(\PDO $db)
        {
            $this->db = $db;
        }
        public function read($id): ?array
        {
            $stmt =$this->db->prepare("SELECT * FROM `$this->table` WHERE `$this->primary`=?");
            $stmt->execute([$id]);
            return $stmt->fetch();
        }
        public function insert($data): int
        {
            $this->validate($data);
    
            $fields = '`'.implode("`,`", array_keys($data)).'`';
            $placeholders = str_repeat('?,', count($data) - 1) . '?';
            $sql = "INSERT INTO `$this->table` ($fields) VALUES ($placeholders)";
            $this->db->prepare($sql)->execute(array_values($data));
            return $this->db->lastInsertId();
        }
        protected function validate($data)
        {
            $diff = array_diff(array_keys($data), $this->fields);
            if ($diff) {
                throw new \InvalidArgumentException("Unknown field(s): ". implode($diff));
            }
        }
    }

    И дальше применять его примерно так
    class UserGateway extends BasicTableGateway {
        protected $table = 'gw_users';
        protected $fields = ['email', 'password', 'name', 'birthday'];
    }
    $userGateway = new UserGateway($pdo);
    $data = [
        'email' => 'foo@bar.com',
        'password' => 123,
        'name' => 'Fooster',
    ];
    $id = $userGateway->insert($data);
    $user = $userGateway->read($id);
    echo json_encode($user),PHP_EOL;

    И никаких тебе "бинов" - обычный ПДО, обычные массивы, все просто и наглядно.


    Хотя пожалуй Dr. Bacon прав, вам и это будет сложновато. Возьмите лучше просто функцию:
    function pdo($pdo, $sql, $args = NULL)
    {
        if (!$args)
        {
             return $pdo->query($sql);
        }
        $stmt = $pdo->prepare($sql);
        $stmt->execute($args);
        return $stmt;
    }

    и дальше просто запросами

    // Create
    pdo($pdo, "INSERT INTO users VALUES (null, ?,?,?)", [$name, $email, $password]);
    // Read
    $user = pdo($pdo, "SELECT * FROM users WHERE email=?", [$email])->fetch();
    // Update
    pdo($pdo, "UPDATE users SET name=:name WHERE id=:id", ['id'=>$id, 'name'=>$name]);
    // Delete
    $deleted = pdo($pdo, "DELETE FROM users WHERE id=?", [$id])->rowCount();


    После того, как SQL будет отскакивать от зубов - можно будет посмотреть в сторону какого-нибудь ORM
    Ответ написан
    1 комментарий
  • Как реализовать хэширование пароля при регистрации?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Соглашусь с предыдущим комментатором, код ужасный. Но главная проблема здесь не в коде, а в голове.
    Все программирование построено на такой штуке, как логика. И если не умеешь мыслить логически - причем на самом элементарном, бытовом уровне - то в программировании точно делать нечего.

    Зачем спрашивать, как хэшировать пароль, если у вас в коде это хэширование уже есть? Вот же оно -
    $password = password_hash($password, PASSWORD_DEFAULT);
    Где логика?
    Зачем сравнивать хэши паролей, если вы хотите сравнить сами введенные пароли? Где логика? Хэши никогда не совпадут.
    Зачем писать, что пароль "Заносится в базу данных без хэширования", если при текущем коде ничего никуда вообще не заносится, потому что не проходит сравнение хэшей. Где логика?
    А если эту дурацкую проверку убрать, или поменять на сравнение самих паролей, то занесется именно хэш, можно убедиться

    Но главная тут проблема - это конечно SQL инъекция.
    Какой вообще смысл делать регистрацию, авторизацию - если кто угодно сможет зайти вообще без пароля под кем угодно? Где логика?
    Надо обязательно научиться выполнять все запросы с переменными только через подготовленные выражения. А потом уже браться за регистрацию, пагинацию, и что угодно. Сначала учимся класть кирпичи, а потом только строим дом. А не наоброт.

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