• Как правильно задать запрос UPDATE где название столбца переменная?

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

    Уже по наличию нумерованных столбцов сразу видно, что структура БД кривая. А текущая проблема делает это еще более наглядным: собственно, сама постановка вопроса, "как задать имя столбца через переменную", говорит о том, что имя колонки используется в условии. То есть оно должно быть значением в строке.

    Здесь нужна связанная таблица, один ко многим, и она сразу снимет все проблемы, а запросы станут мягкими и шелковистыми:

    UPDATE link_count SET count=count+? WHERE link_id=? and number=?
    Ответ написан
    3 комментария
  • Как удалить запись в таблице MySQL по трём параметрам?

    ipatiev
    @ipatiev
    Потомок старинного рода Ипатьевых-Колотитьевых
    Чтобы правильно удалить запись в таблице по трём параметрам, надо указать все три параметра в условии WHERE
    DELETE FROM table_name WHERE col_1=val_1 AND col_2=val_2 AND col_3=val_3


    Не два, не пять, не десять, а ровно три параметра.
    Ответ написан
    Комментировать
  • Как решить ошибку отправки почты, с использованием PHPMailer?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Чтобы исправить ошибку, надо прочитать, что в ней написано.
    Для этого надо найти на сервере лог ошибок.
    Если вы не знаете, что такое сервер или лог ошибок, то попробуйте поискать в панели управления хостингом.
    На худой конец обратитесь в службу поддержки хостинга, чтобы они вам прочитали текст ошибки
    Ответ написан
  • Как решить проблему с подключением к Clickhouse из php?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Надо прочитать сообщение об ошибке.
    В нем говорится, что код на 71 строке в файле vendor\smi2\phpclickhouse\src\Client.php не видит элемент массива $config c ключом 'username'.

    После этого надо убедиться, что в передаваемом в класс Cilent массиве присутствует элемент с ключом username и этот ключ написан правильно, без опечаток.
    Ответ написан
  • Возникает ошибка "Заполните все поля". Все заполнено. Что не так с кодом?

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

    Например.
    Обычно эту бессмысленную фразу выводят примерно таким говнокодом:
    if (empty($_POST['pole1']) || empty($_POST['pole2']) || empty($_POST['pole3'])) {
        die("Заполните все поля");
    }

    Для того, чтобы разобраться с этой неразрешимой проблемой, вам понадобится немного логики.
    Я уверен, вам вполне по силам сделать умозаключение вида, "Если этот код выводит ошибку, то как минимум одно из полей содержит пустое значение".
    Сделав такой логический вывод, его следует проверить.
    Например таким кодом:
    var_dump($_POST['pole1'],$_POST['pole2'],$_POST['pole3']):

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

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

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

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

    Во-первых, при создании соединения с БД, надо сказать ПДО, чтобы он сообщал об ошибках.
    $this->conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    Во-вторых, временно, на период разработки, включить отображение ошибок РНР. Чтобы тупо увидеть, если произошла какая-то ошибка.
    ini_set('display_errors', 1);

    И в-третьих, начать собственно отладку.
    Для начала убедившись, что РНР код в принципе запускается, и проблема в нем, а не в форме.
    Для этого в самом начале action.php пишем большими буквами
    die("пхп хотя бы запустился");
    И если после нажатия на кнопку мы этот текст не увидели, то начинаем тупить в свою форму - а с чего она вообще должна что-то посылать в файл action.php (и попутно задаваться вопросом - а какое отношение наш вопрос имеет к php и sql?)?
    Если форма отправляется аяксом, то смотрим ответ пхп в инструментах разработчика, вкладка Сеть.

    Если обработку формы мы начали, то заезжаем внутрь условия
    die("начали обработку формы");

    И так далее, отслеживаем работу своего кода, выполняется ли он вообще, и содержат ли переменные нужные значения.

    А в целом, конечно, код очень жестокий.
    Вот прямо хочется спросить -
    зачем здесь функция test_input?
    зачем здесь try {}catch (){echo 'Error : '.$e-getMessage();}?
    зачем class Auth extends Database?
    почему showMessage - это часть класса Database? Ну вот серьёзно, каким местом вывод сообщения в браузер в виде HTML хоть как-то относится к работе с базой данных?

    Чтобы сделать этот код минимально осмысленным, надо
    выкинуть класс Database
    в класс Auth добавить
    public function __construct($pdo){
                $this->conn = $pdo;
        }

    и выкинуть из него require_once 'config.php';

    В config.php оставить только соединение с PDO
    в action написать
    require 'config.php';
    $user = new Auth($pdo);

    и выкинуть условие при регистрации, оставив только
    $user->register($name,$email,$hpass);
    $_SESSION['user'] = $email;

    И тогда этот код станет минимально осмысленным
    Ответ написан
    Комментировать
  • Как использовать уязвимость remote code execution?

    ipatiev
    @ipatiev
    Потомок старинного рода Ипатьевых-Колотитьевых
    Вопрос, который всегда привлекает мамкиных хакеров :)
    Такие скучные темы, как "какими качествами я должен обладать?", "какие знания требуются?", на худой конец "какие книжки читать?" их никогда не интересуют. Только "как находят" и "как взламывают" :)
    Это же ведь просто! Спросил на Хабре, тебе ответили - и вот уже загадочная романтическая профессия освоена.

    Ответ, кстати, всегда один и тот же:
    Если ты спрашиваешь, то уже не подходишь.
    Потому что ключевым навыком взломщика является умение работать с информацией. И если ты самостоятельно не смог найти ответ даже на такой общий вопрос, то найти даже пустячную уязвимость тебе точно не по зубам.

    как хакеры находят?

    С помощью нечеловеческой концентрации и терпения. И плюс вагона разнообразных знаний в куче смежных областей, от архитектуры процессоров до тонкостей генерации pdf. Сидишь, пробуешь тысячу разных подходов. В одном появляется зацепка. Ты уже к этой зацепке пробуешь тысячу подходов. В одном появляется зацепка. Ты пробуешь уже к этой зацепке тысячу подходов. Но ни один не работает. Возвращаешься к предыдущей. Там тоже больше ничто никуда не ведет. Возвращаешься к самому началу, и пробуешь что-то ещё.
    Где-то год назад на Хабре вроде была статья, которая довольно подробно описывала процесс поиска уязвимости, который в итоге привел к RCE через unserialize в пхп.

    Как использовать

    Для этого надо понять, как работает программа на атакуемом сервере. А дальше всё просто: скормить ей такие данные, которые приведут к выполнению содержащегося в них кода.
    Самый тупой пример - SQL инъекция, описанная в известном комиксе, которая заставляет сервер выполнить код, удаляющий таблицу пользователей из БД.
    Ответ написан
    5 комментариев
  • Когда нужен MVC, а когда API?

    ipatiev
    @ipatiev
    Потомок старинного рода Ипатьевых-Колотитьевых
    Понятно же, что человек просто использует термины не по назначению. А имеет в виду способ взаимодействия с клиентом.
    Словом "mvc" он называет классический способ, при котором сервер отдает клиенту HTML (а не JSON).
    А словом "api" - REST сервис, при котором сервер отдает клиенту как раз JSON.

    И суть вопроса сводится именно к различию между этими двумя способами:
    - когда сервер генерирует HTML на основе полученных из БД данных, и отдает его браузеру
    - или когда в браузере выполняется программа на JS, которая запрашивает с сервера только данные, а потом на их основе генерирует HTML

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

    При этом с точки зрения бэкенд программиста разницы принципиальной между этими способами нет.
    Главное в программе - это её бизнес-логика. И уметь надо в первую очередь писать её.
    А в каком формате отдавать данные в браузер - дело десятое. И выбирать между "mvc HTML" и "api REST" нет смысла - уметь надо и то и то.

    Ну и, как уже объяснили, MVC - это совсем другое. Архитектура приложения. Причем она используется для любых приложений, независимо от типа отдаваемых данных. M и C в "api" приложениях используются в полный рост. Только V немного упрощается. при этом поскольку MVC подразумевается по умолчанию, то и писать её в вакансиях тоже особого смысла нет.
    Ответ написан
    4 комментария
  • Как исправить не правильное форматирование css который вставляет php?

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

    некоторые файлы он вставляет с форматированием , а другие нет.


    РНР не вставляет никакие файлы. Из РНР вы получаете ссылку. Её читает браузер. Который дальше и читает файл, и "вставляет" код, и форматирует его.
    При чем то, что браузер показывает в инструментах разработчика, может не иметь вообще ничего общего с тем, что на самом деле лежит в файле. Если хотите посмотреть реальное "форматирование", то надо смотреть сам файл, а не то что браузер рисует в инспекторе
    Ответ написан
    4 комментария
  • Как получить данные из строки mysqli?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Чтобы получить одну строку из результата запроса, в mysqli есть функции
    • fetch_assoc(): возвращает всю строку в ассоциативный массив
    • fetch_row(): возвращает нумерованный массив (список)
    • fetch_obj(): возвращает объект класса stdClass
    • fetch_column(): возвращает значение из первой колонки запрошенной строки

    В общем случае случае осмысленный код для получения значения единственной колонки будет таким
    $sql = "SELECT link FROM tablet where id=?";
    $result = $conn->execute_query($sql, [$a]); 
    $link = $result->fetch_column();

    Но как правильно замечено в комментариях, правильнее будет рандомизировать сразу в запросе, причем все делать одним запросом, а не тремя
    function Axelmo($conn) {
        $sql2 = "SELECT link FROM tablet ORDER BY rand() LIMIT 1";
        return $conn->query($sql)->fetch_column();
    }

    Ну и чисто для иллюстрации, как сделать запрос с ограничением по id
    function Axelmo($min, $max, $conn) {
        $sql2 = "SELECT link FROM tablet where id >= ? AND id <= ? ORDER BY rand() LIMIT 1";
        return $conn->execute_query($sql, [$min, $max])->fetch_column();
    }
    Ответ написан
    1 комментарий
  • Зависит ли скорость записи в БД от количества в ней записей?

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

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

    Если же говорить про проблему медленной записи, то она происходит из того факта, что mysql по умолчанию убеждается в успешности записи каждой строки, перед тем как записывать следующую. Отсюда будут и варианты её решения

    Вариант 1, при котором никакой код менять не надо. Отключаем эти проверки устанавливая переменную mysql innodb_flush_log_at_trx_commit=0. Для этого надо обладать правами рута.
    Вариант 2: заключить все вставки в транзакцию
    Вариант 3: добавлять все записи одним запросом. Это можно сделать либо кодом Slava Rozhnev, либо запросом LOAD DATA INFILE

    Да, и между вашими вариантами 2 и три нет никакой разницы. Это один и тот же вариант, про который в любом случае надо забыть: он вообще никогда не должен применяться. Переменные должны попадать в запрос только через плейсхолдеры.
    Ответ написан
    2 комментария
  • Как в при записи набора строк в файл преобразовать символы, чтобы символ \n не делал перевод строки?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    file_put_contents('file.txt',json_encode($strings,JSON_PRETTY_PRINT|JSON_UNESCAPED_UNICODE));


    Если нужен CSV, то так и надо было сразу говорить
    В этом случае файл должен выглядеть так
    "Иван Иванович"
    "Пётр
     Петрович"
    "Дмитрий Дмитревич"

    И все прекрасно будет читаться.
    И разумеется, в РНР есть функция записи CSV
    Ответ написан
    Комментировать
  • Хэш sha1 разный в зависимости от того в каких кавычках строка?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    В приципе, в комментариях уже всё разжевали, но на всякий случай
    Выполняем простой код
    var_dump("{\"order_id\":\"FACTPRECHR152632\",\"amount\":\"8300.00\"}");
    var_dump('{\"order_id\":\"FACTPRECHR152632\",\"amount\":\"8300.00\"}');

    и смотрим на результат

    после этого выполняем ещё один простой код
    $json = json_encode(["order_id"=>"FACTPRECHR152632", "amount"=> "8300.00"]);
    var_dump($json);
    var_dump(addcslashes($json, '"'));

    смотрим на результат
    сравниваем его с предыдущим

    И после этого идем с вопросами к тому, кто придумал написать здесь addcslashes
    Ответ написан
    Комментировать
  • Сколько обращений к базе данных происходит в данном коде?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    "Обращений" - либо 4, либо 1, в зависимости от настроек и содержимого connectdbpdo()
    "заставлять базу что-то делать" - в любом случае один.
    Ответ написан
    Комментировать
  • Возможна ли sql инъекция?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Нет.
    Ответ написан
    1 комментарий
  • Как наследовать два класса в php?

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

    В первую очередь надо задать себе вопрос, а зачем вам отдельный класс на каждый вид запроса? Если там достаточно одного метода?

    Если у вас отдельный квери билдер на коленке, то вы можете сделать его отдельным классом, унаследовав от него сам враппер. В котором реализовать методы для запросов
    Ответ написан
    Комментировать
  • MySQL PDO, Почему все значения при выборке типа string?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Зачем вы задаёте не тот вопрос, с которым у вас проблема?:)

    Ваша проблема в том, что вы хотите проэксплуатировать баг в ПДО, из-за которого он не сообщает об ошибке.
    Не надо этого делать.
    Передавайте ровно столько параметров, сколько "масок" в запросе. Проблема решена.
    Ответ написан
    Комментировать
  • Почему не работает password verify?

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

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

    В данном конкретном случае проблема может быть в "переносе" данных между серверами, насколько можно судить из этого невнятного вопроса
    Ответ написан
    Комментировать