Ответы пользователя по тегу PHP
  • Что может содержать DTO?

    @Vitsliputsli
    1) Цель использования DTO - это передать данные между двумя подсистемами. Причем, либо между ними нельзя передать поведение, либо мы хотим, чтобы они были независимы, а передача поведения увеличит зацепление.
    2) DTO - это специфика Java, там, объединить разнородные данные можно только в объекте. Поэтому был введен данный механизм - объект с искусственным ограничением, только данные и никакого поведения. Но, php не Java, здесь разнородные данные можно легко объединить в обычном массиве. Вы можете, конечно, массив завернуть в объект, но смысла в этом нет, т.к. мы передаем данные между независимыми подсистемами, ни одна из них не должна быть зацеплена на объекты другой.
    3) Как уже написали, сам DTO и механизм его формирующий - это разные вещи, подсистемы могут вообще на разных языках быть написаны, и все будет прекрасно работать, т.к. мы передаем только данные, а не поведение. Если же хочется туда запихнуть валидацию или иное поведение, стоит задуматься, а зачем здесь DTO? Не проще ли тогда сразу передавать полноценный объект.
    Ответ написан
    Комментировать
  • Почему условие не выполеяется?

    @Vitsliputsli
    empty($var) - это "синтаксический сахар", т.е. это краткая запись следующей конструкции:
    !isset($var) || $var == false
    т.е. кроме того же самого isset, там еще и сравнение с false, причем с преобразованием типов
    Ответ написан
    Комментировать
  • Зачем дублировать сеттер и геттер?

    @Vitsliputsli
    Если уж говорить об едином методе, то скорее так:
    function getSetAge(?int $age=null): int
    {
        if (!is_null($age)) {
            $this->age = $age;
        }
        return $this->age;
    }}

    Но, мы уже не сможем записать null, а получать значение, которые мы только что записали и вовсе не нужно.
    Даже так не делают, потому что, это логически совершенно разные операции и гораздо удобнее их разнести по разным методам. Если вы думаете, что упрощение - это меньше символов, то это не так. Упрощение - это разнесение независимых частей, а складывание всего в одну кучу только ухудшает чтение.
    Не говоря уже о том, что использование геттеров-сеттеров не очень хорошая практика, методы должны нести смысловую нагрузку, а не просто менять внутренние свойства, иначе это ничем не лучше публичных свойств. Хотя и тут тоже нужно без фанатизма.
    Ответ написан
    Комментировать
  • Как из текстового файла вывести 15 случайных строк?

    @Vitsliputsli
    Накидал вариант для поиска случайных строк в очень больших файлах. Это не совсем оптимально для конкртеного случая автора, но может быть будет кому-то интересно в других случаях.
    $fileName = '1.csv';
    $lineLength = 1024;
    $linesCount = 15;
    
    $handle = fopen($fileName, "r");
    $fileSize = filesize($fileName);
    $data = [];
    if ($fileSize !== 0) {
       for ($num = 1; $num <= $linesCount; $num++) {
           $rand = rand(0, $fileSize);
           fseek($handle, $rand);
           $firstPointer = null;
           do {
               fgets($handle); // trash
               $pointer = ftell($handle);
               if ($pointer === $fileSize) {
                   fseek($handle, 0);
                   $pointer = 0;
               }
               if ($pointer === $firstPointer) { // loop detect
                   continue 2;
               }
               $firstPointer = $firstPointer ?? $pointer;
           } while (array_key_exists($pointer, $data));
           $data[$pointer] = fgets($handle);
       }
    }
    ksort($data); // sort by order in file
    var_dump($data);

    Я здесь не делал защиты от ошибок файловых функций, в этом случае результат может быть неожиданным. Для защиты нужно обернуть все файловые функции и при ошибке выкидывать Exception, а не эти тупые php-шные false. Ну и помнить про ограничение длины строки в $lineLength.
    Ответ написан
    Комментировать
  • Можно ли взаимодействовать с функцией файла, не подключая ее?

    @Vitsliputsli
    Нет, нельзя.
    C# компилируемый язык, когда создаете новый файл, IDE подключает его в проект. При сборке файлы проекта известны и будут использоваться. PHP интерпретируемый язык, вы можете запустить на исполнение любой файл php, но он не имеет никакого понятия, что там было в IDE, поэтому использование require обязательно. На практике используют автолоадеры, стандартом в PHP считается автолоадер composer.
    Ответ написан
    Комментировать
  • Что не так в коде (можете сделать краткое код ревью)?

    @Vitsliputsli
    Про форматирование, конечно, верно пишут, но если про него забыть (очень оно не стандартное, но я бы не сказал, что прям какое-то нечитабельное), то просто беглым взглядом:
    1) Нет ООП (а это сейчас обязательный стандарт), попытка выдать за ООП набор статических классов делает только хуже, пишите уж лучше честно процедурно.
    2) SQL-инъекции! Да и весь блок работы с СУБД чтото ужасное. Куча бесполезного, реконнекты при каждом запросе...
    3) ТТУК, если конечно вообще подразумевался mvc, и контроллер это index.php.
    4) Вместо автолоадера просто подключение всего и вся. Хотя по факту в php сейчас стандарт - composer.
    Ответ написан
  • Какой есть быстрый способ сравнить многомерный массив?

    @Vitsliputsli
    Если весь массив умещается в память это уже хорошо. Как оптимизировать:
    1) Создайте массивы не ассоциативные, а с обычными числовыми ключами. Лучше так и хранить, будет отдельно массив url и массив cnt, связь по числовому ключу.
    2) Храните отсортированный массив, и используйте по нему, например, бинарный поиск.
    3) Дополнительно можно использовать массив фиксированной длины из SPL, а не стандартный на хеш-таблицах, на таких объемах от него будет толк.
    Ответ написан
    Комментировать
  • Почему PHP кэширует содержимое скрипта при запуске из sudo?

    @Vitsliputsli
    У вас включен файловый кеш (в том числе для cli), но отключена проверка валидности кеша (validate_timestamps). Поэтому пока вы вручную не сбросите кеш, он будет продолжать работать.
    Что касается sudo, при первом запуске скрипта, вы сделали это через sudo, был создан файл кеша от root, с правами запрещающими чтение другими пользователями. При запуске без sudo php не может его прочитать и записать (хрен его знает, почему он не кидает ошибку), в итоге sudo php работает с файловым кешем, а php от пользователя нет.
    Ответ написан
    Комментировать
  • Как улучшить код, который проверяет наличие элемента в массиве и его значение?

    @Vitsliputsli
    Не нужно ничего сокращать. Код вполне краток и понятен. Дальнейшие сокращения лишь ухудшат читаемость.
    Но если хочется поговнокодить можно взять empty.
    Ответ написан
    5 комментариев
  • Почему неправильно изменяется текст php?

    @Vitsliputsli
    ... выглядит примерно так: 01
    То есть 0 не убирается, как то исправить?

    А вы пробовали локализовать проблему? Т.е. посмотреть отдельные участки кода. Например, так:
    echo sprintf('%02d',1);
    И решить, если вам не нужны ведущие нули, зачем вы их требуете выводить?
    Ответ написан
    3 комментария
  • Хороша ли архитектура моего кода? Информация цепляется по API?

    @Vitsliputsli
    Все public, все доступно извне, нет сокрытия.
    Прям сам объект куда-то лезет по api, забирает данные, которые сам и предоставляет, обрабатывает ответ, явное нарушение SRP.
    Ответ написан
    Комментировать
  • Что быстрее поиск по файлу JSON в PHP или в базе посредством MySQL?

    @Vitsliputsli
    Если это обычный вопрос, что лучше, то храните в БД. Если реально пытаетесь выиграть несколько миллисекунд, то положите это все в redis.
    В принципе, хранение в массиве php скорее всего тоже будет достаточно быстрым, при условии использования php-fpm и без json.
    Если нужен поиск подстроки в строке, то на таких объемах тоже вполне быстро будет работать. На больших придется рассматривать, что-то вроде Elastic, т.к. СУБД это делают плохо, а MySQL очень плохо.
    Ответ написан
    Комментировать
  • Как правильно сделать типизацию объектов?

    @Vitsliputsli
    Вы можете воспользоваться контравариантностью (php>=7.4), т.е. указать в абстрактном классе родительский класс для User:
    abstract protected function mapToArray(Model $object ): array;
    
    ...
    
    class User extends Model

    Либо ввести DTO, чтобы mapper брал данные из него и вообще никак не обращался к бизнесовым сущностям.
    Ответ написан
    6 комментариев
  • Как в регулярных выражениях php заменить только символ?

    @Vitsliputsli
    Зачем здесь регулярка?
    str_replace(['*','x'],'R','2*10*30 2x10x30');

    Регулярка будет выглядить так: /\*|x/

    Если же, замена нужно только для конструкций из 3 чисел соединенных * или x, то можно написать так:
    preg_filter('/(\d+)[*x](\d+)[*x](\d+)/', '${1}R${2}R${3}', '2*10*30 2x10x30')
    Ответ написан
    2 комментария
  • Почему не работает curl в цикле?

    @Vitsliputsli
    У вас и во внешнем и во внутреннем цикле используется одна и та же переменная.
    Ответ написан
    Комментировать
  • Вопросы по архитектуре проекта: service layer и action domain responder?

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

    Сервисный слой или модели в MVC - это не класс, не объект. Это код отвечающий за доменную логику, там никто Single Responsibility не отменял, делите сущности по их ответственности, и создавайте столько классов, сколько необходимо.

    И вопрос, а чем же всё таки являются actions? Это больше контроллеры одного действия, или больше сервисы одного действия? Поскольку в сети мнения на этот счёт расходятся.

    Очевидно, что actions - это обычные контроллеры. Вообще, ADR - это тот же MVC, с абсолютно таким же делением на controller-action, model-domain, view-responder. Автор ADR утверждает, что там связи более правильные. Но в отличиях ADR от MVC, автор приписывает MVC какие-то ужасы, типа вьюха при желании лезет в модели что-то там запрашивает и т.п., чего в MVC нет и никогда не было. Такое ощущение, что автор ADR просто открыл для себя как правильно пользоваться MVC.
    Ответ написан
    Комментировать
  • Непонятное поведение chdir в php. Что не так?

    @Vitsliputsli
    Chdir возвращает ответ, по которому можно определить отработало это или нет. Когда не срабатывает, то в лог кидается ошибка с описанием причины.
    Соответственно, вопрос, на фига гадать, если нужно читать лог.
    Ответ написан
    Комментировать
  • Как посчитать разницу между датами без года в PHP?

    @Vitsliputsli
    А как вы собираетесь считать дни между датами, без указания года? Или вы забыли, что есть високосные года?
    Укажите текущий год для дня рождения, и сравните с текущей датой. Если результат отрицательный, то берите следующий год для дня рождения.
    Ответ написан
    Комментировать
  • Как с помощью функции array_slice удалить значение из массива?

    @Vitsliputsli
    array_slice ничего не удаляет, он дает срез массива, поэтому такая формулировка не очень корректна. Исходя из этого, вы не сможете удалить элементы внутри существующего массива, и единственный вариант - это создание нового массива с выбранными значениям.
    $numbers = [
        '123',
        '124',
        '125',
        '111',
        '222',
        '566',
        '777',
    ];
    
    $cleanNumbers = [];
    foreach ($numbers as $key=>$number) {
        // не нужно делать универсальным поиск нужных значений, т.к. он слишком специфичен, поэтому так:
        if ($number[0]===$number[1] && $number[1]===$number[2]) {
            // здесь проще было бы написать $cleanNumbers[] = $number;
            $cleanNumbers[] = array_slice($numbers, $key, 1); 
            // а если нужно все таки удаление, то достаточно unset($numbers[$i]) с противоположным условием
        }
    }
    var_dump($cleanNumbers);

    В итоге, на кой здесь array_slice - мне совершенно не понятно.
    Ответ написан
  • Как запретить запуск скрипта по крону больше 1 раза?

    @Vitsliputsli
    Используйте mutex. Он либо есть в вашем фремворке, либо сделайте сами. Варианты: файловый - реализуется с помощью flock (это такая команда в php, а не внешняя утилита как в другом ответе), в БД - если файловый делать нельзя, например, при нескольких инстансах приложения.
    Ответ написан
    Комментировать