Профиль пользователя заблокирован сроком с 10 апреля 2022 г. и навсегда по причине: систематические нарушения правил сервиса
  • Лучший способ авторизации через php?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    "Не читайте до обеда советских газет".

    86% статей в интернете написаны чудовищными дителантами, которые сами едва десяток операторов освоили.
    Иногда к прочим данным также добавляют IP или UserAgent которые также проверяются и обновляются при взаимодействии со скриптом авторизации. Иногда таблица в БД разносится на несколько.

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

    Без контекста сложно понять, что имеется в виду.

    Общее правило - не доверять голословным утверждениям. Если автор понимает, о чем пишет, то сможет и объяснить ту или иную рекомендацию или оценку.

    Из перечисленного выше я бы только добавил защиту от подбора пароля.
    Ответ написан
    1 комментарий
  • Почему не работает функция php?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    Этот вопрос надо задавать не в Спортлото, а своей базе данных.
    Только она знает, почему запрос не выполняется.

    Для этого надо правильно соединяться с mysqli.
    Не одной строчкой, а указывая все нужные параметры. В частности режим отображения ошибок:
    mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
    И тогда БД сможет тебе наконец сказать, что ей не так.

    Если взять код mysqli.php по ссылке выше, то правильный, безопасный, и сообшающий о своих ошибках код будет таким
    function SendNotice($conn, $p1, $p2) {
        $sql = "SELECT `id` FROM `users` WHERE `login` = ?";
        $row = prepared_query($mysqli, $sql, [$p1])->get_result()->fetch_assoc();
        if (!$row['id']) echo 'Ошибка!';
        $sql = "INSERT INTO `notifications` VALUES (null, ?, 0, NOW(), ?)";
        prepared_query($conn, $sql, [$row[id], $p2]);
    }

    И вызываться она должна так
    include 'mysqli.php';
    SendNotice($conn, 'test', 'Test text');
    Ответ написан
    2 комментария
  • Генерация php кода и его исполнение из бд, возможно ли?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    Какой-то бред.
    Элементы перемещаются с помощью CSS, "РНР код" здесь вообще не при чем.

    Чудовищнее всего здесь ответы: "очень-очень осторожно", "нужно делать валидацию". При этом спроси их - что именно осторожно? Какую именно валидацию? - не ответят. Потому что простого ответа нет, надо учитывать кучу деталей. А в итоге все равно станутся дыры.

    В общем, генерировать РНР код можно, но только на этапе разработки. Генерировать РНР код на основе пользовательского ввода - это ад и харакири.
    Ответ написан
    6 комментариев
  • Invalid datetime format. Как решить?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    Дай обезьяне микроскоп, она им будет орехи колоть.
    Родимый, зачем тебе RedBean, если ты его используешь как муэскуэль_квери() из прошлого века?
    Документацию для кого пишут? Ну ты бы хоть базовые примеры посмотрел перед тем, как за это поделие браться.
    А если не понимаешь как им пользоваться, то вообще не трогай, посмотри видеокурсы от руселлера и лепи обычный гуанокод, ORM для этого не нужен

    <?php
    require("connect.php");
    
    $task = R::dispense( 'tasks' );
    $task->task = strip_tags( $_POST['tasks'] );
    $task->date = date('Y-m-d');
    $task->time = date('H:i:s');
    $id = R::store($task);
    Ответ написан
    1 комментарий
  • Что лучше Laravel или Lumen для REST API?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    Именно поэтому подход Симфони 4 рулит. Выбираешь только те компоненты, которые нужны.
    Ответ написан
    Комментировать
  • Как с помощью класса для PDO получить результат update?

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

    А ответ на вопрос простой но неожиданный - никак.
    Результат запроса update тебе не нужен.

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

    Если же говорить о количестве строк, которые затронул запрос, то, поскольку у тебя абстракция не течет, то вместо метода sql(), который тупо дублирует run(), я бы сдела метод dml()

    public static function dml($query, $args = []) {
        $stmt = self::run($query, $args);
        return $stmt->rowCount();
      }

    и применял ее только для запросов, модифицирующих данные (DML).
    Ответ написан
    1 комментарий
  • Как запускать php скрипт после каждого завершения работы?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    просто в командной строке написать
    while true; do php -f /путь/скрипт.php; done
    остановить - Ctrl-C
    Ответ написан
    5 комментариев
  • Виртуальный поддомен или физический?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    Этот вопрос задавался 100500 раз, но искать лень.

    В ДНС делается wildcard запись *.example.com, чтобы все запросы к субдоменам вели на один хост.
    Апач настраивается аналогично.
    Конкретный запрошенный хост берется из HTTP_HOST.
    Всё, больше ничего не надо.
    Ответ написан
    5 комментариев
  • Как правильно передать и обработать X-Request-ID?

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

    Генерировать уникально. UUID подойдет.
    Передавать наверное через квери стринг - тогда этот ид попадет в лог веб-сервера, на случай, если пхп совсем уж упадет еще до запуска обработчика ошибок. Ну, или если такая точность не особо критична, то просто дополнительным полем в джейсон.
    Плюс в обработчике ошибок РНР учитывать это значение и добавлять к сообщению об ошибке, записанному в лог.
    Ответ написан
    Комментировать
  • Как получить уникальные значения JSON массива из ячейки MySQL?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    Не надо хранить в базе данных " массивы значений в JSON'е".
    MySQL - реляционная датабаза. Это означает, что база данных строится из связанных таблиц.
    И вместо колонки values должна быть отдельная таблица,
    table_id | value
    1 | 1
    1 | 2
    1 | 3
    2 | 2
    2 | 3
    2 | 4

    И тогда все выборки будут делаться примитивными SQL запросами, без малейших затруднений со стороны разработчика.
    Ответ написан
    5 комментариев
  • Хорошо ли написан класс БД?

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

    Можно поправить только по мелочам.

    - код соединения никуда не годится. Брать отсюда: Как правильно соединяться с mysql в PDO
    - при этом конфиграцию (хост, пароль, чарсет и прочее) вынести отдельно и передавать в конструктор в виде массива
    - query() переписать так:
    private function query($query, array $params = array()){
        $stmt = $this->db->prepare($query);
        $stmt->execute($params);
        return $stmt;
      }

    - добавить getRow() и использовать в getById именно его.
    - getRows переименовать в getAll чтобы не было путаницы и переписать так
    public function getRows($query, array $params = array(), $mode= PDO::FETCH_ASSOC){
        return $this->query($query, $params)->fetchAll($mode);
      }
    - либо добавить методы для всех методов PDO, либо сделать $db публичной. потому что когда тебе нужно будет выполнить десяток инсертов обернутых в транзакцию, эта обертка превратится в тыкву.
    Ответ написан
    5 комментариев
  • Какой есть 100% способ перекодировать строку в utf-8?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    Такого способа нет.
    Для стопроцентного результата необходимо знать кодировку исходного текста.
    Ответ написан
  • Как соединить работу двух методов?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    1. В контроллере ничего подобного в принципе никогда быть не должно. Ни двух методов, ни одного. Никакой работы с БД в контроллере в принципе быть не может. Контроллер должен только принять данный из формы и вызвать метод модели. Только не убогого класса для маппинга таблицы из БД в класс РНР, который называют моделью новички, а нормальной модели, реелизующей всю бизнес-логику приложения.
    2. По-хорошему, это код для репозитория, поскольку он работает с базой данных. Но конкретная реализация зависит от того как реализован класс customer

    В идеале цепочка вызовов должна быть такая
    Контроллер вызывает инстанс хелпера (или сервиса) CustomerHelper.
    В этот хелпер через конструктор передается инстанс CustomerRepository и присваивается свойству класса.
    В методе Create класса CustomerHelper вызывается метод Create класса CustomerRepository.
    И в этом методе уже и происходит искомая транзакция.
    Ответ написан
    3 комментария
  • Почему не хочет создаваться запись в бд?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    Слово group является зарезервированным в mysql, и его надо брать в обратные кавычки.

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

    Не говоря уже про дырявость и дурацкую идею про "сначала пусть заработает". Проверять работу запроса надо в mysql. А в PHP "пробовать" не надо, надо сразу писать запрос через prepare
    Ответ написан
    Комментировать
  • Как изменить путь $_SERVER['DOCUMENT_ROOT']?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    RewriteEngine On
    RewriteRule ^main/(.*)$ /$1 [L]


    Но на будущее надо не лениться и не пложить папочки на локальном компе, а делать честные домены.
    Это совсем нетрудно.
    Ответ написан
  • Нужен ли класс в этом случае? Или можно держать функцию особняком?

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

    Кроме того, авторы видеокурсов в большинстве своем - неграмотные имбецилы, которые с трудом понимают код, который пишут. Кроме шуток. Пример. Вот так пишут обезьяны:
    $i = 0;
        $newsList = array();
        while($row = $result->fetch()) {
          $newsList[$i]['id'] = $row['id'];
          $newsList[$i]['title'] = $row['title'];
          $newsList[$i]['date'] = $row['date'];
          $newsList[$i]['author_name'] = $row['author_name'];
          $newsList[$i]['short_content'] = $row['short_content'];
          $i++;
        }
        return $newsList;

    Реально, макаки.
    Этот гамадрил где-то сам увидел обучающий материал из 1990-х годов прошлого века, запомнил его, и теперь лепит уже в свои "обучающие ведидео".
    при том что если бы он понимал смысл этого кода, то написал бы просто
    $newsList = array();
        while($row = $result->fetch()) {
          $newsList[] = $row;
        }
        return $newsList;

    Поскольку $row уже содержит все нужные данные и переливать их из пустого в порожнее не нужно.
    А если бы наш бабуин хотя бы раз в жизни поинтересовался инструментами, которые он использует, то написал бы и вовсе одну строчку,

    return $result->fetchAll();

    Поскольку все уже написано до нас - надо только руку протянуть и использовать готовое.

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

    Если вернуться к теме "отдельные функции или класс", то для примера приведенного здесь класс, действительно, не нужен. Любая коллекция статических методов может быть заменена на набор функций.

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

    abstract class Model {
        protected $table;
        protected $db;
        public function __construct($db) {
             $this->db = $db;
        }
        public function find($id) {
            $sql = "SELECT * FROM `$this->table` WHERE id=?";
            $stmt = $this->db->prepare($sql);
            $stmt->execute([$id]);
            return $stmt->fetch();
        }
    }
    class News extends Model {
            protected $table = 'news';
    }
    $news = new News($db);
    $article = $news->find($id);


    Вот это уже будет минимальное оопэ, и использование класса будет более чем оправдано - один раз написали код, а потом его используем.

    Если хочется нормальных обучающих материалов, рекомендую канал Дмитрия Елисеева, https://www.youtube.com/user/ElisDN/videos
    Ответ написан
  • Как проверить в php результат запроса?

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

    Проверять надо не карман, а деньги. Не результат запроса, а строки, которые он вернул. То есть надо просто сделать фетч и вот уже результат фетча проверять в условии. То есть if ($post)

    Ну и как всегда надо напомнить, что переменные никогда не пихают в запрос напрямую, а передают отдельно. Готовый код можно посмотреть здесь, https://phpdelusions.net/mysqli/check_value
    Ответ написан
    Комментировать
  • Почему так странно ищет substr?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    Что вопрос, что ответы - АД.

    Как правильно написали, это PHP serialize, только не целая строка, а какой-то огрызок
    Поэтому надо брать оригинаьную строку, и делать так
    $array = unserialize($findstr);
    echo $array['name'];
    Ответ написан
    Комментировать
  • Подключение к базе данных MySql, как правильно и современно?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    Вопрос хороший, но неправильно сформулирован.
    Поскольку тут на самом деле два вопроса - какой драйвер использовать и уже потом - как правильно соединяться.
    Ответ на первый вопрос очевиден. Если выбирать из mysql_connect, mysqli и PDO, то достаточно зайти на страницу мануала, посвященную каждому варианту, и посмотреть, что там написано. Ну или попробовать использовать в своем коде и посмотреть что получится.

    А вот вопрос, как правильно подключаться в двух оставшихся вариантах, действительно важный, и ответ на него, как обычно, почти никто не знает, поскольку все друг у друга списывают статьи не 2-х, а 22-х летней давности. К счастью, есть сайты с актуальной информацией.

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

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

    Но правильным ответом, если выбирать из перечисленных трех, будет PDO. Здесь тоже не так просто, поэтому смотрим как правильно соединяться используя PDO - учитывая те же ключевые моменты, которые указаны выше.

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

    Пароль в базе данных не шифруется а хэшируется. Делается это с посощью функции password_hash
    Ответ написан
    3 комментария
  • Где сейчас тусуются серьезные PHP программисты?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    Завсит от цели, для чего это спрашивается.

    Если чтобы поприставать с нубскими вопросами - то нигде.
    Если чтобы почитать умных мыслей - РНР дайджест на Хабре прекрасно суммирует все, что было написано за две недели. У меня например никогда не хватает времени, чтобы прочесть всё. Куда больше-то - я уж и не знаю.
    Если чтобы поучаствовать в серьезном прокете - на гитхабе, выбирай любой.
    Если чтобы послушать интересные доклады и пообщаться вживую - то конференции.
    Если интересует внутренне устройство языка - то php internals.
    Если интересует, что пишут пхп селебрити про что угодно, кроме программирования - то твиттер (Расмус показывает картинки из аэропортов и роботов, которых собирает его сын, Сара постит котиков - и так далее).

    Где точно не тусуются:
    Тостер и всякие подобные ресурсы типа стаковерфлоя.
    Ну то есть специалиста можно найти, если поискать, но концентрация будет гомеопатическая, если учитывать количество восторженных щеночков, которые увидели язык вчера, и спешат срочно поделиться уже накопленным багажом знаний.
    Чаты. Телеграм, дискорд - вот это вот все.
    Самая адовая трата времени, которая в принципе бывает в жизни.
    Опять же, люди пишут о чем угодно, кроме программирования, и ради пары полезных строчек надо убить весь день.
    Ответ написан
    4 комментария