• Когда каскадное обновление это плохо?

    @Akina
    Сетевой и системный админ, SQL-программист.
    Когда каскадное обновление это плохо?

    Каскадное обновление - в большинстве случаев это... глупо.

    Вспомним, что это вообще такое.

    Имеется связь, реализованная внешним ключом. Некое поле (в общем случае - выражение) основной таблицы, уникально индексированное, является значением, на которое ссылается некое поле (или выражение) подчинённой таблицы (возможно, и той же самой).

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

    Что же есть каскадное обновление? Это изменение связанного значения в подчинённой таблице, если изменяется значение основной таблицы. Ну то есть если изменяется (вспоминаем сказанное выше) значение первичного ключа или поля, объявленного уникальным. В основной таблице. Ага...

    Ну то, что изменение/корректировка значения поля первичного ключа есть bad practice (читай - дурь голимая), хорошо известно, обосновано и весьма логично. Нет, реально возможны ситуации, когда такая операция оправдана и имеет смысл - но такая ситуация абсолютно всегда одноразовая, и есть составная часть административного обслуживания. А если подобная надобность возникла на уровне пользователя, в рабочем процессе - то это гарантия наличия серьёзной ошибки в проектировании БД.

    Практически всё то же относится и к корректировке просто уникального поля. За исключением случая, когда выполняется каскадное изменение значения поля, которое в основной таблице получило значение NULL. То есть когда выполняемая операция по смыслу является не обновлением, а "мягким удалением" основной записи с каскадным удалением всех подчинённых. Правда, на вопрос, как отличить мягко каскадно-удалённые подчинённые записи от мягко явно-удалённых, и как определить, с какой основной записью была связана мягко удалённая подчинённая, не залезая в журнал или бэкап, ответа никто не даст. А получается, что даже в случае исключения всё делается через "универсальный интерфейс", то есть косяк в проектировании структуры имеется и в этом случае.

    Резюмирую. Если каскадное обновление необходимо, оно скорее всего маскирует недостатки и ошибки проектирования. А плохо это или хорошо - прикрывать дырку костылём,- решайте сами.
    Ответ написан
    Комментировать
  • Как тестировать запросы и ответы из базы данных через phpunit?

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

    Если говорить про "запросы к БД", то для таких тестов "массив с данными" использовать просто глупо. Это получится какой-то формальный тест: "проверяем, что метод возвращает массив из трех строк - и тут же возвращаем этот самый массив". В чем смысл? Если вы тестируете запрос к БД, то и надо тестировать запрос к БД. По-другому никак.

    Здесь я отвлекусь, и порассуждаю на тему того, что на самом деле тестирование - это гораздо более трудоёмкая задача, чем обычно считается. И как следствие, большая часть тестов - это такая вот туфта. Либо тест заранее возвращает нужные данные, либо тестирует один-два кейса. А вариантов неправильных входящих данных ведь может быть огромное количество. То есть по-хорошему на такой заведомо сложный (и принципиально неделимый!) метод нужно десятка два тестов.

    И сюда же использование для тестов БД другой системы. Например основная БД MySQL, а для тестов используется Sqlite. Тут сразу можно сказать, что это профанация. Различие даже в какой-то одной настройке БД может повлиять на результаты запроса (и теста как следствие) - а тут и вовсе используется совсем другая БД.

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


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

    Здесь нелишне будет напомнить название доклада с одной из последних конференций по пхп. Дословно не помню, но что-то вроде "Делайте методы как можно короче. Ваши тесты скажут вам спасибо." Собственно, именно при тестировании очень быстро начинаешь понимать удобство атомарных (то есть выполняющих какую-то одну простую операцию) методов. А без тестов пройдёт довольно много времени, пока не понадобится этот длинный метод отрефакторить, и по итогам менять кучу кода, который его вызывает.

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

    vhood
    @vhood
    Не забывайте отмечать решения
    Здесь Вы принимаете type
    public function makeRequest(array $args, string $type) {
    Здесь выполняете логику в зависимости от typeif($type === "source1") {

    Для каждого type нужно создать класс, который будет выполнять логику, описанную в его блоке if.
    пример

    class SpecificTypeApiService implemets ApiServiceInterface
    {
        public function send()
       {
    //код ниже просто скопирован, стоит вынести что-то в параметры, что-то в конструктор и сделать код более элегантным
    //можно сделать абстрактный класс и делегировать ему общий для разных type (сервисов) функционал
        $proxiesArr = array('72.37.217.3:4145', '174.77.111.196:4145');
              
              $randProx = array_rand($proxiesArr, 1);
              
              $proxyIp = $proxiesArr[$randProx];
            
    //      $proxyIp = '174.77.111.196:4145';
            $url1 = $args[0] . $args[1];
                $headers = [
                'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.105 YaBrowser/21.3.3.230 Yowser/2.5 Safari/537.36'
                ];
    
                $curl = curl_init();
    
            curl_setopt($curl, CURLOPT_PROXY, $proxyIp);
            curl_setopt($curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS4);
            curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
            curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); 
            curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
            curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
            curl_setopt($curl, CURLOPT_VERBOSE, 1); 
            curl_setopt($curl, CURLOPT_POST, false);
            curl_setopt($curl, CURLOPT_URL, $url1);
    
            $result = curl_exec($curl);
    
            if(curl_exec($curl) === false)
            {
            echo 'Ошибка curl: ' . curl_error($curl);
            } else {
            echo 'Операция завершена без каких-либо ошибок';
            }
    
            return $result;
       }
    }


    После, с помощью DI и полиморфизма, отрефакторить существующий код следующим образом:

    Здесь Вы принимаете сервис вместо type
    public function makeRequest(array $args, ApiServiceInterface $apiService) {

    Здесь выполняете логику, но выполнение делегируете сервису$apiService->send();

    Стоит получше подумать над именами классов, переменных и функций.
    Ответ написан
    Комментировать
  • Как правильно передать строку из js в php при помощи ajax?

    delphinpro
    @delphinpro Куратор тега JavaScript
    frontend developer
    Ответ написан
    Комментировать
  • Почему ajax выполняется по очереди?

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    Вангую - на бэке PHP и сессии. Причём, открываются сессии в начале скрипта, а закрываются никогда, то есть по завершении скрипта.
    Тогда пока работает скрипт, файл сессии держится открытым и второй скрипт в той же сессии будет ждать освобождения файла. Файл сессии надо освобождать как можно раньше. session_start, считали нужные данные и сразу же session_write_close. Если надо что-то изменить в сессионных данных в процессе работы скрипта, то снова открыть сессию, записать изменения, закрыть.
    Ответ написан
    Комментировать
  • Как обойти ошибку CORS при получении картинки из cdn facebook?

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    Запрашивать сторонние ресурсы через свой бэк, больше никак.
    Ответ написан
    3 комментария
  • Как сделать деобфускацию кода?

    delphinpro
    @delphinpro Куратор тега JavaScript
    frontend developer
    Сначала меняем eval в конце крипта на console.log
    Вставляем это в консоль и выполняем.
    Результат копируем
    Ищем какой-нибудь деобфускатор, например этот https://de4js.bloggerbyte.net/
    Прогоняем на авто режиме
    Получаем относительно читабельный код:
    spoiler
    var _0x225ac5 = _0x3b87;
    (function (_0xe5e38d, _0x53a189) {
        var _0x21d761 = _0x3b87,
            _0x215dc9 = _0xe5e38d();
        while (!![]) {
            try {
                var _0x5db276 = -parseInt(_0x21d761(0x115)) / 0x1 * (-parseInt(_0x21d761(0x106)) / 0x2) + parseInt(_0x21d761(0x108)) / 0x3 + parseInt(_0x21d761(0x105)) / 0x4 * (-parseInt(_0x21d761(0x10a)) / 0x5) + -parseInt(_0x21d761(0x10b)) / 0x6 * (parseInt(_0x21d761(0x10c)) / 0x7) + parseInt(_0x21d761(0x10f)) / 0x8 * (-parseInt(_0x21d761(0x10d)) / 0x9) + -parseInt(_0x21d761(0x113)) / 0xa * (-parseInt(_0x21d761(0x104)) / 0xb) + parseInt(_0x21d761(0x101)) / 0xc * (-parseInt(_0x21d761(0x110)) / 0xd);
                if (_0x5db276 === _0x53a189) break;
                else _0x215dc9['push'](_0x215dc9['shift']())
            } catch (_0x1ceac6) {
                _0x215dc9['push'](_0x215dc9['shift']())
            }
        }
    }(_0x484e, 0x602bd));
    var _$_d181 = [_0x225ac5(0x112), _0x225ac5(0x114), 'forEach', _0x225ac5(0x102), _0x225ac5(0x10e), 'setMusicVolume', _0x225ac5(0x103), 'setSoundVolume', _0x225ac5(0x109), _0x225ac5(0x107), _0x225ac5(0x111), 'DialogManager'];
    
    function muteMedia(_0x2c5074) {
        _0x2c5074[_$_d181[0x0]] = !![], _0x2c5074[_$_d181[0x1]]()
    }
    
    function mutePageMedia() {
        document[_$_d181[0x4]](_$_d181[0x3])[_$_d181[0x2]](_0x181f2a => {
            return muteMedia(_0x181f2a)
        })
    }
    
    function _0x484e() {
        var _0x2277b4 = ['pause', '1841bupQJr', '1463244jlRnjn', 'video, audio', 'SoundManager', '7150yaDhrN', '4YptQSm', '302jBoPrk', '_mainDlgs', '1577490CYDCQW', 'buyAuto', '1159445mEuzmn', '30sfQSkF', '398776gggCvH', '261zTciOl', 'querySelectorAll', '92176gOWIYG', '13YWZNlF', '_instance', 'muted', '8660XjUZgW'];
        _0x484e = function () {
            return _0x2277b4
        };
        return _0x484e()
    }
    mutePageMedia();
    
    function wait(_0x5db71f) {
        return new Promise(_0x250182 => {
            return setTimeout(_0x250182, _0x5db71f)
        })
    }
    
    function _0x3b87(_0x4ea049, _0x3f6347) {
        var _0x484eaf = _0x484e();
        return _0x3b87 = function (_0x3b87f9, _0x5cdb65) {
            _0x3b87f9 = _0x3b87f9 - 0x101;
            var _0x1d0f03 = _0x484eaf[_0x3b87f9];
            return _0x1d0f03
        }, _0x3b87(_0x4ea049, _0x3f6347)
    }
    async function mainLoop() {
        Laya[_$_d181[0x6]][_$_d181[0x5]](0x0), Laya[_$_d181[0x6]][_$_d181[0x7]](0x0), await wait(0x3e8), window[_$_d181[0xb]][_$_d181[0xa]][_$_d181[0x9]][0x0][_$_d181[0x8]]()
    }
    mainLoop();


    Осталось открыть в IDE и провести рефакторинг, переименовав функции и переменные, и дав им адекватные имена.
    Ответ написан
    6 комментариев
  • Как преобразовать число вида 20240617114532 в дату-время?

    @SunTechnik
    Вам должно быть виднее, что там за формат времени у Вас, но, на первый взгляд, это выглядит как объединение без пробелов:
    Год месяц число часы минуты секунды.
    Соответственно Ваш запрос легко превращается в интервал (или два условия больше - меньше)
    Ответ написан
    1 комментарий
  • Большое кол-во записей в секунду в MySQL. Как читать последний порядковый номер столбца и добавлять к нему +1 при записи?

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    Какой-то бред.
    1. Составной ключ по автоинкрементному полю и обычному смысла не имеет, поскольку автоинкрементное поле id всегда уникально, то добавление к нем sessid ничего, кроме торможения, не добавит.
    2. Делать какую-то отдельную проверку на уникальность result внутри sessid смысла не имеет. Достаточно сделать уникальный составной ключ (sessid, result) и использовать INSERT IGNORE.
    3. Отдельное поле serialnumb абсолютно не нужно. Выборку всегда можно отсортировать через ORDER BY id и пронумеровать через оконные функции.
    Ответ написан
    5 комментариев
  • Как сделать чтобы при прокрутке нав меню прилипало к верхнему краю экрана?

    @karminski
    Senior React.JS Developer
    Вообще-то прилипание гораздо проще сделать стандартным свойством CSS
    https://developer.mozilla.org/en-US/docs/Web/CSS/p...
    И не выдумывать велосипед
    Ответ написан
    Комментировать
  • Как узнать, сколько дней осталось до Нового Года?

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    echo (new DateTimeImmutable('first day of January next year'))
        ->diff(new DateTimeImmutable())
        ->format('Осталось дней: %a');
    // Осталось дней: 151
    Ответ написан
    2 комментария
  • Выбор программы или ЯП для создания приложения по обработке данных?

    Делать это всё на чистом экселе - умрёшь.

    Это очень пахнет отраслевым решением - такие редко делают бесплатные.
    Скорее всего какое-то специализированное решение для ресторанов уже имеет функции для работы с технологическими картами и складом (r_keeper и подобное, например)
    В ту же сторону - 1С, тем более что в этом соцучреждении уже наверняка 1С где-то используется.
    Ответ написан
    Комментировать
  • Как отловить событие нажатия - комбинация клавиш?

    delphinpro
    @delphinpro Куратор тега JavaScript
    frontend developer
    Распечатайте событие keydown в консоли. Вы там увидите помимо кода клавиши ещё поля shiftKey, ctrlKey имеющие булево значение, которые отображают, нажата ли соответствующая клавиша.
    Ответ написан
    Комментировать
  • При обновлении страницы данные отправляются бесконечно раз в бд?

    alexey-m-ukolov
    @alexey-m-ukolov Куратор тега PHP
    Чтобы этого не происходило, нужно после успешного добавления куда-то редиректить пользователя (это может быть даже та же страница). Тогда браузер «забудет» введённые данные и можно будет обновлять страницу без вреда.
    Ответ написан
    Комментировать
  • Curl смог, а злосчастный fetch (firefox) не может?

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    no-cors это вообще из другой оперы. Эта опция позволяет выполнить только простой запрос (HEAD, GET, POST) с ограниченным набором заголовков (Accept, Accept-Language, Content-Language, Content-Type и Range), но не даёт JS доступа к свойствам Response, то есть телу и заголовкам ответа.

    Сама политика CORS контролируется браузером и не даёт делать cross-origin запросы, если сервер, к которому сделан запрос, не возвращает явного разрешения на это в заголовках ответа. Для обхода надо делать запрос через свой бэкенд, который выполняет в этом случае роль прокси для внешнего ресурса.
    Ответ написан
    Комментировать
  • Раздражает ли авторизация тех, кто следит заходит на мой Pet-проект?

    sergey-gornostaev
    @sergey-gornostaev
    Седой и строгий
    В таких случаях обычно регистрация и авторизация делаются, но где-нибудь пишется, что можно воспользоваться демонстрационным пользователем с логином demo и паролем demo.
    Ответ написан
    Комментировать
  • Как узнать, на каком движке работает сайт?

    @Refguser
    Решения для бизнеса: от создания ИМ до...
    хотелось бы частично повторить его под свои услуги.

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

    Вопрос по этому сайту.

    На этом сайте нет ничего сверхъестественного. Сделать такое можно на чём угодно.

    А что касается его движка там прямо на главной самоуверенно написано
    ojY9aAs.jpeg
    (что весьма спорно и вообще не компетентно)
    Ответ написан
    7 комментариев
  • Ошибка Caused by: Exception 'PDOException' with message 'could not find driver'?

    alexey-m-ukolov
    @alexey-m-ukolov Куратор тега PHP
    Нужно в контейнер установить и/или включить расширения pdo-pgsql и pgsql. Ну и не забыть, что у FPM и CLI режимов в PHP разные php.ini используются - включать нужно в правильном.
    Ответ написан
    1 комментарий
  • Как увеличить производительность проекта на python?

    все упирается в бд, на ум сразу пришло вынести эту часть в микросервис
    Какой ещё микросервис? Микросервис, который делает что?

    В-нулевых, нужно конкретизировать что значит "упирается в БД". Тормозят какие-то конкретные запросы? СУБД не хватает ресурсов? Слишком медленный диск? Или, может, под "упирается в БД" вы понимаете всю бизнес-логику приложения, которую вы называете "берет из бд нужные данные" (и тогда становится понятно про микросервис)?
    Во-первых, нужно вынести СУБД на отдельную машину, желательно на голое железо (если речь про реальный хайлоад, а не про кривой код и конфиги).
    В-третьих, под это железо нужно СУБД корректно сконфигурировать.
    В-четвёртых, нужно добавить кэширование.
    В-пятых, нужно проверить алгоритмы и пофиксить узкие места (на последнем месте, потому что это самое трудоёмкое).

    Я понимаю, что python и django не самые быстрые инструменты (мягко скажем)
    Я вас уверяю, что проблема в вашей компетенции (мягко скажем), а не в инструментах. Есть достаточно проектов, написанных на Джанго, которые вывозят большие нагрузки.
    Вы, в принципе, правильно сделали, что попытались поначалу закидать проблему железом - оно обычно дешевле, чем время разработчиков. Но параллельно надо и оптимизацией заниматься, и это требует системности, которой в вопросе не очень-то видно. Ну и компетенций разных - если тормозят алгоритмы - это одно, если конкретные SQL-запросы - это другое, если СУБД задыхается в принципе - это третье.
    Ответ написан
    5 комментариев
  • Почему возникает Ошибка синтаксического анализа XML в браузере firefox?

    sfi0zy
    @sfi0zy
    Creative frontend developer
    Между фактами
    Как видно, на первой позиции в первой строке находится {

    и
    Ошибка синтаксического анализа XML

    есть противоречие. То ли речь идет про XML, то ли про JSON. Надо определиться. Вполне вероятно, что у вас сервер левые заголовки отдает и браузер думает, что там XML, а на самом деле там JSON. Отсюда и ошибка.
    Ответ написан
    Комментировать