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

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Путь истинный:
    1. Зайти в панельку своего хостинга, найти там, где лежат лог ошибок
    2. В нем всё написано.
    3. Во всех непонятных ситуациях повторить пп. 1-2

    Добавлять строчку ini_set('display_errors', 1); не следует. На хостинге вывод ошибок должен быть выключен. И даже в качестве временной меры это добавлять бессмысленно - ошибки всегда будут, надо учиться работать с логами.
    Ответ написан
    Комментировать
  • Как преобразовывать заглавную букву в главную и обратно при поиске как в гугле?

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

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    То что вам нужно, называется "профайлинг".
    Его можно делать с помощью разных инструментов, таких как Xdebug, но можно и коряво, вручную расставляя код типа такого
    $microtime = microtime(1);
    // что-то делаем
    $timer['sql'] = microtime(1) - $microtime;
    Потом куда-то выводим этот таймер, чтобы никто не видел.

    Но в принципе тут и без профайлинга можно сказать, что тормозит запрос в БД.
    На шаредах всегда так. Хотя кривые руки при работе с БД тоже скорее всего виноваты.
    Ответ написан
    6 комментариев
  • Форма обратной связи по SMTP работает, вводя только мою почту? Как исправить?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Вам же человеческим языком пишут, что нельзя подставлять липу в $mail->setFrom($email);
    Или просто уберите эту строчку, или пишите в нее СВОЮ ПОЧТУ.

    Как вариант, можете перед setFrom добавить addReplyTo()
    Ответ написан
    6 комментариев
  • Как вынести запросы rest api на постоянное соединение?

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

    И проблема здесь не в количестве соединений, а в том, кто писал код.
    Если в коде используется только одно соединение за все время работы скрипта (а не открывает новое соединение на каждый запрос, как у всех гениальных скриптописателей), и база данных устроена по уму (не тормозит), то хватит даже самого дохлого хостинга с лимитом в 5 одновременных подключений. Просто потому что любой запрос к рест апи должен работать не дольше 0.01 секунды. И любые проблемы будут появляться только при частоте обращений больше 100 в секунду.

    Соответственно, вместо фантазий про "одно соединение" надо переделывать кривой код и базу данных.
    Ответ написан
    Комментировать
  • Как создать базу данных и связать с PHP и MySQL?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    База данных нинужна
    Достаточно будет
    <?php
    file_put_contents('databaza.txt', json_encode($_POST, JSON_UNESCAPED_UNICODE)."\n", FILE_APPEND);

    ну и чтобы вывести
    foreach(file('databaza.txt') as $loh) {
         echo json_decode($loh, true)['email'], "<br>\n";
    }


    Ну а форму на HTML я думаю Frontend developer (senior+) уж как-нибудь осилит.
    Ответ написан
    2 комментария
  • Как написать регулярное выражение для обработки разметки из ckeditor?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    1. Никогда не используйте регулярки для парсинга HTML
    2. Никогда не задавайте вопрос про свой вариант решения проблемы. Всегда задавайте вопрос про саму проблему.
    3. Htmlpurifier, HtmlSanitizer
    Ответ написан
    Комментировать
  • Как оптимизировать код php во избежании дублирования, при добавление данных в БД?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Для того, чтобы не повторять программный код, специально были придуманы подпрограммы.
    Когда один и тот же код может выполняться для разных наборов данных.
    В РНР есть несколько способов сделать подпрограмму, но самый удобный - это написать функцию.
    Важно только соблюдать чувство меры и принцип единственной ответственности - функция должна делать что-то одно. К примеру, если она должна что-то писать в базу данных, то не должна при этом с базой соединяться.
    function save_data($pdo, $data, $type) {
        $stmt = $db->prepare('INSERT INTO ads (snippet, amp, date, anchor, link,type) 
                              VALUES (:snippet,:amp,:date,:anchor, :link, :type)');
        $pdo->beginTransaction();
        foreach ($data as $values) {
            $values['type'] = $type;
            $stmt->execute($values);
        }
        $pdo->commit();
    }

    Как я уже писал ранее, для скорости и консистентности множественные вставки желательно заключить в транзакцию.

    И вызывать примерно так

    $db = new PDO('mysql:host=localhost;dbname=test', 'root', '');
    // ТОЛЬКО EXCEPTION! c warning-ами в детский сад ходите детей пугать
    $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    
    $file = file_get_contents("ads.json");
    $data = json_decode($file, true);
    save_data($db, $data['p1']['ads'], 'ads');
    
    $file = file_get_contents("May-12_17-57-28.json");
    $data = json_decode($file, true);
    save_data($db, $data['p1']['serp'], 'serp');


    На этом этапе, посмотрев на повторяющийся код, можно сделать еще одну итерацию
    function import_data($filename, $type, $pdo) {
        $file = file_get_contents($filename);
        $data = json_decode($file, true);
        save_data($pdo, $data['p1'][$type], $type);    
    }

    Но можно уже и не частить
    Ответ написан
  • Не срабатывает sql запрос. Как быть?

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

    Но в данном случае можно сократить путь "получение сообщения об ошибке - чтение сообщения об ошибке - гугление сообщения об ошибке".
    Надо эти черточки и нолики перенести из bind_param в сам запрос.
    Ответ написан
    Комментировать
  • Почему неверно считается результат арифметического выражения?

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

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

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

    // Параметры подключения к БД, желательно держать в отдельном файле
    $username = 'myusername';
    $password = 'mypassword';
    $dbname = 'mydatabase';
    $dbhost = '127.0.0.1';
    
    // Подключение к БД
    $dsn = 'mysql:host=$dbhost;dbname=$bname;charset=utf8mb4';
    $options = array(
        // Обязательно - режим информирования об ошибках
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
    ); 
    $pdo = new PDO($dsn, $username, $password, $options);
    
    // Подготавливаем запрос
    $stmt = $pdo->prepare("INSERT INTO mytable (snippet, amp, date, anchor, link)
                           VALUES (:snippet, :amp, :date, :anchor, :link)"
    );
    
    // Используем транзакцию для скорости и консистентности
    $pdo->beginTransaction(); 
    // Перебираем массив
    foreach ($data as $values) {
        // Выполняем запрос с очередной порцией данных
        $stmt->execute($values);
    }
    // Завершаем транзакцию
    $pdo->commit();
    Ответ написан
  • Можно ли Views созданное в базе данных вывести на сайт?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Можно, но не нужно.
    Представления это те же таблицы, вид сбоку. Обращение к ним ничем не отличается от обращения к таблицам.
    Но вам не нужно никакое View, оно не решает ни одну из ваших проблем.
    Вам нужен банальный джойн с группировкой.
    И немного навести порядок в голове.
    Ответ написан
  • Php ошибка: Parse error: syntax error, unexpected token «}» in C:\Apache\Apache24\htdocs\postgresql.php on line 5. Что не так?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Две главные вещи, которые освоить перед тем как начинать знакомиться с программированием.
    1. Умение читать
    2. Умение логически мыслить, на уровне силлогизмов "если только программисты носят красные рубашки, а петя в красной рубашке, то он программист"
    Это очень важные умения, без которых в программировании совсем никак.

    Сначала читаем сообщение об ошибке:
    Ошибка синтаксиса. Неожиданный элемент «}» в 5 строке.
    Затем считаем строки. 5 строка это "echo "PostgreSQL connection failed";"
    Символа «}» в ней нет.

    Далее делаем логическое умозаключение:
    Если в приведенном коде на 5 строке нет символа «}», это означает, что сообщение об ошибке относится к какому-то другому коду, а совсем не к этому. То есть искать в нем ошибку бесполезно.
    Надо найти тот код, который вызывает эту ошибку, и искать проблему в нем.
    Ответ написан
    Комментировать
  • Экранирование sql запросов, достаточно ли функции?

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

    - trim() ни к инъекциям, ни к защите отношения не имеет
    - stripslashes() просто бессмысленная функция, которая только портит данные
    - htmlspecialchars() не имеет отношения к SQL. Применяется при выводе данных, а не при получении
    - real_escape_string() - единственная функция, которая имеет отношение к SQL, но при этом вообще не предназначенная ни для каких защит.

    Попробуйте на основании этой информации самостоятельно оценить полезность вашей функции.

    Возьмем классический пример
    $_GET['id'] = '1;DROP TABLE Students;';
    $id = formatstr($_GET['id']);
    $sql = "SELECT * FRPM Students WHERE id=$id";

    И посмотрим, помогло ли ваше самописное экранирование предотвратить хоть что-то (спойлер: нет).
    (да, та функция, которую лично вы используете для выполнения запросов, выполняет только один запрос за раз. И вместо инъекции вы получите ошибку. Но это не отменяет сам факт получения инъекции.)

    Как правильно все отметили выше, для защиты от инъекций используются подготовленные запросы, в которых все переменные заменяются на специальные маркеры, и передаются отдельно.
    Ответ написан
    2 комментария
  • Как исправить кракозябры вместо кириллических символов при записи переменной в сессию?

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

    А сессии тут вообще не при чем.
    Ответ написан
    1 комментарий
  • Как грамотно сделать обработку ислючений в php?

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

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

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

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

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

    Пример такого исключения - когда запрос в БД порождает ошибку.

    3. Пользовательские исключения, там где они нужны, обычно обрабатываются по месту, но есть нюансы.
    Собственно, под обработкой исключений часто понимают два разных действия:
    - собственно обработку, когда программа совершает какие-то действия, чтобы нивелировать негативный эффект. Например, если не удалось подключение к какому-то сервису, то либо попробовать подключиться к другому, либо просто подождать и попробовать снова.
    - простое информирование пользователя

    Для информирования можно действительно ловить исключение через try..catch и писать какое-то свое сообщение.
    Но можно и автоматизировать этот процесс, вот две статьи, которые показывают примеры, как это можно сделать:
    https://angelovdejan.me/2022/11/24/centralized-exc...
    https://habr.com/ru/articles/688202/
    Ответ написан
    Комментировать
  • Почему не записываются данные в БД, UPDATE не работает?

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

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

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Сервис - это часть модели. Класс, который реализует некую бизнес-логику, не связанную напрямую с хранилищем.
    Репозиторий - часть модели, класс, который содержит методы для работы с хранилищем.
    Стор - это какая-то местечковая приблуда. Из битрикса небось? Либо какие-то академические измышления, вот как в соседнем ответе. Вроде человек что-то пишет, но яснее ничего не становится.
    Маппер имеет много значений. Если речь про Data Mapper, то это разделение самих данных и их отображения в БД.

    Читать стандартно - Дядюшка Боб Мартин и Мартин Фаулер. Конкретно по РНР - Зандстра.
    Ответ написан
    2 комментария
  • Как исправить кракозябры вместо кириллических символов?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    У вас в этой таблице лежат данные, закодированные в windows-1251.
    Вам надо или перекодировать полученные данные нормально, через mb_convert_encoding(), а не вот это вот недоразумение utf8_encode.

    Или лучше всего один раз и навсегда перекодировать данные в БД.
    Для этого надо сделать дамп, поменять в нем set names с utf8 на cp1251, и выполнить сначала на тестовой БД
    Если данные будут читаться, то выполнить на боевой.
    Ответ написан
    1 комментарий