Задать вопрос
  • Как оптимизировать код 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
    Потомок старинного рода Ипатьевых-Колотитьевых
    возможно вся логика неправильная и можно сделать более грамотно.


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

    когда записей в таблице порядка 10 миллионов время выполнения запроса


    ВНЕЗАПНО оказалось, что если использовать микроскоп для забивания гвоздей, то в него становится почему-то плохо видно.

    В простой БД два поля - id и data. У поля data тип JSON. В нем хранятся данные, получаемые из нескольких форм.


    Но вы же, когда эту, с позволения сказать, "базу данных" проектировали, ведь радовались своему остроумию и хитрости? Зачем проектировать структуру базы данных, делать какие-то таблицы, между таблицами связи. потом сложные запросы писать? Если можно хопа, и в джейсон все кучей навалить!

    Ну вот и продолжайте радоваться дальше.

    Сама по себе дурацкая проблема проверки уникальности длинного текста решается элементарно, добавляется колонка с md5 от содержимого, и поиск делается по ней.
    Но ведь в таблицу эти данные складываются не только чтобы проверять их на уникальность. И собственно какая-то работа с этими данными все равно превратится в боль
    Ответ написан
    3 комментария
  • Как лучше сделать добавление корзины/избранного?

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

    ipatiev
    @ipatiev
    Потомок старинного рода Ипатьевых-Колотитьевых
    Нет, не влияет.
    Если хотите чтобы у вас нормально сохранялись тексты, а не рубились на половине, используйте utf8mb4
    про utf8 давно пора забыть
    Ответ написан
    Комментировать
  • Как агрегировать данные по элементам вложенного массива?

    ipatiev
    @ipatiev
    Потомок старинного рода Ипатьевых-Колотитьевых
    В цикле.
    Все операции над массивами производятся в цикле.

    Чтобы посчитать количество элементов, вам не нужно Node.js/Pandas/MS SQL,PostgreSQL и их диалекты/Mongo а так же SQL, JAVASCRIPT и MONGODB

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

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

    ipatiev
    @ipatiev
    Потомок старинного рода Ипатьевых-Колотитьевых
    null - это и есть "отсутствие данных".
    Надо не маяться дурью, а просто вставлять данные как есть.
    если вместо null надо вставить что-то еще, то использовать COALESCE
    Ответ написан
    Комментировать
  • Аналоги почты для домена (дешевле и/или бесплатно) вместо Gmail и Yandex?

    ipatiev
    @ipatiev
    Потомок старинного рода Ипатьевых-Колотитьевых
    Я поудалял все ящики и сделал их алиасами для двух оставшихся - то есть почта на них приходить будет. А три ящика бесплатно.
    Не для всех решение, но мне подходит, все равно почта только на прием нужна.
    Ответ написан
    Комментировать
  • Как из 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 строке нет символа «}», это означает, что сообщение об ошибке относится к какому-то другому коду, а совсем не к этому. То есть искать в нем ошибку бесполезно.
    Надо найти тот код, который вызывает эту ошибку, и искать проблему в нем.
    Ответ написан
    Комментировать
  • Можно ли с локального сервера отправить письмо под любым именем?

    ipatiev
    @ipatiev
    Потомок старинного рода Ипатьевых-Колотитьевых
    Можно.
    Но все нормальные почтовые сервера отправят его в помойку не глядя.
    Ответ написан
    4 комментария
  • Экранирование 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. Данные добавились, в одну базу, а результат смотрим в другой.

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

    ipatiev
    @ipatiev
    Потомок старинного рода Ипатьевых-Колотитьевых
    Приватная репа на гитхабе
    Ответ написан
    Комментировать
  • Как правильно распределять ответственность между классами?

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

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

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

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