Ответы пользователя по тегу PHP
  • Переход на mongoDB?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    Раньше использовал mysql, и до сих пор все нравилось, как не понадобилась иерархическая структура.


    Казалось бы, причем тут mongodb. Мускуль json умеет (хоть и не так удобно), и подозреваю что речь все же идет о графах. В этом случае стоит графовую БД брать (Neo4j например).

    Словом уточните свою задачу.

    А вот как их получать?! Не смог найти свойства и метода.


    Читаем документацию.
    Ответ написан
  • PSR-7 что должен реализовывать метод?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    Checks if a header exists by the given case-insensitive name.


    Проверяет наличие заголовка по имени без учета регистра.

    метод проверяет не то, был ли выставлен данный заголовок, а допустимость имени заголовка. Так ли это?


    Видимо нет)
    Ответ написан
  • Что почитать об архитектуре приложений и фреймворков на php?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    В целом сразу вас расстрою, то что вы хотите нельзя "разобрать" за пару месяцев. На это уйдет пару тройку лет. И книги которые стоит по этой теме прочитать имеет смысл перечитывать. Ну и практика практика практика.

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

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

    но совершенно не имею представления о правильной архитектуре приложений на php


    "Правильно" не бывает, все зависит от задачи. "Правильная" архитектура является:

    - понятной - то есть можно быстро разобраться. Это как читабельность кода (читать совершенный код Макконела) так и в принципе декомпозиция системы, разделение ответственности и т.д. (микросервисы, гексагональная архитектура). Тут можно посоветовать почитать Эрика Эванса.
    - удобной в изменениях (продумать все нереально, а сталобыть проще сделать так что бы адаптироваться под изменения в требованиях можно было эффективнее).
    - Тестируемой - то есть вы можете проверить работоспособность системы на различных уровнях. Тут стоит смотреть в сторону TDD или практик с той же идеей (сначала формулируем как работает и как мы это проверим а потом уже делаем).

    Вот и все. Далее уже есть принципы SOLID (читать Роберта Мартина), GRASP (Крэйг Ларман), GoF (лучше тут почитать head first design patterns или даже начать с Мэта Зандстры, у него помимо паттернов еще про процессы мельком рассказано).

    Ну и смысла в этом всем нет если вы еще до конца не осознали что есть инкапсуляция и полиморфизм. Многие могут рассказать что значат эти термины, но на практике эти знания они не могут применить (чаще всего страдает инкапсуляция)

    или написании чего-то своего с нуля на чистом php


    Такое решение может принимать только разработчик у которого уже есть за плечами хотя бы пяток лет опыта работы с различными (не одним) фреймворком и языками. В противном случае вы только будете заниматься бесполезным велосипедостроительством.

    идеально было бы вообще подробно расписанное сравнение внутреннего устройства нескольких фреймворков


    Берете Symfony или Zend и вперед. Все остальные фреймворки "проще". То есть скрывают больше от разработчика. После них уже можно брать что угодно.

    p.s. еще прочитайте тут: www.phptherightway.com
    Ответ написан
  • Почему добавления пространства имен "провоцирует" warning?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    потому что нет такого класса больше. Его полное имя - "myproject\Foo"
    Ответ написан
  • Зачем тестировать код?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    Что тут тестировать и зачем? в случае неудачи получим исключение. Названия колонок мы знаем. Данные в контроллере валидируются.


    вы должны проверять корректность работы системы. Всего-то. Причем с оглядкой не только на "сейчас" (тут мы и руками можем проверить быстро) но еще с оглядкой на будущее. Если вы планируете этот код выкинуть - тестировать его нет смысла. Вы на автоматизацию тестирования убьете больше времени чем проверите руками.

    С другой стороны, если это лишь вершина айсберга, то имеет смысл написать простенький автотестик, который проверяет корректность работы. Так, если мы будем вносить какие-то изменения, например будем добавлять комменты, мы будем уверены на 90% что ничего не сломали. Почему не на 100%? потому что невозможно покрыть все тестовые сценарии да и это не выгодно. Проверяем мы обычно самые вероятные сценарии.

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

    Но такой тест отрабатывает относительно долго. Представьте себе что вы пишите что-то посложнее. И у вас уже 100 различных тестовых сценариев для одого кусочка системы. В итоге этот маленький кусочек будет тестироваться больше минуты, и мы успеем заскучать. Для того что бы упростить - мы дробим этот кусочек еще и еще пока не находятся такие куски, которые мы можем проверить удобно и быстро. Например если вопрос в корректности валидации данных - мы можем тестировать только контроллер, а если вопрос в каких-то бизнес правилах отдельных - мы можем и их отдельно вынести и тестировать. Это будут интеграционные тесты.

    В конечном счете мы можем раздробить все до уровня отдельных маленьких модулей, по сути классов, и тестировать их отдельно. Это будет юнит тесты.

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

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

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    Смысл в том, чтобы делать отложенные job-ы без помощи cron-а, т.е. замена cron-а чем-то более удобным...


    beanstalkd

    по поводу resque можете попробовать вот это: https://github.com/mjphaynes/php-resque - он посвежее.
    Ответ написан
  • Как сделать строчный калькулятор?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    Вам нужно разбирать строку на лексемы регуляркой (что бы отделить числа от операторов). Результатом должно быть что-то такое:

    ['10', '+', '10', '*', '2', '+', '10']

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

    ['10', '10', '10', '2', '*', '+', '+']

    ну и далее мы уже можем выполнить выражение. Примеры подобного есть в сети.
    Ответ написан
  • Как рекурсивно удалить файлы и папки с веб-сервера?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    RecursiveIteratorIterator + RecursiveDirectoryIterator

    $files = new RecursiveIteratorIterator(
        new RecursiveDirectoryIterator($dir, RecursiveDirectoryIterator::SKIP_DOTS),
        RecursiveIteratorIterator::CHILD_FIRST
    );
    
    foreach ($files as $fileinfo) {
        $todo = ($fileinfo->isDir() ? 'rmdir' : 'unlink');
        $todo($fileinfo->getRealPath());
    }
    
    rmdir($dir);
    Ответ написан
  • Нужен ли MAMP или его аналог на ubuntu desktop?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    на ubuntu desktop?


    Нет. apt-get install php7 и вперед к сверешниям.
    Ответ написан
  • Как сжимать изображения прямо при загрузке на сервер?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    чисто теоритически это возможно, особенно с появлением web assembly и возможностью использовать готовые библиотеки для оптимизации графики. Сейчас это весьма затруднительно.

    Есть очень простой способ - aws s3 + aws lambda для загрузки файлов и обработке оных по загрузке на сервер.
    Ответ написан
  • Как должен быть реализован middleware?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    function app(Request $request) : Response {
        return new Response(200, "This is app response");
    }
    
    function myMiddleware(Request $request, callable $next) {
        $response = $next();
        $response->headers->add('Content-Type', 'text/html');
    
        return $response;
    }


    Это общий принцип. Декорация. Смотреть шаблон проектирования "адаптер" и "декоратор".

    updated

    упростим наше приложение до одной простой функции - handle, которая принимает запрос, и должна вернуть ответ. Это то как работает WEB и все вроде должно быть тут просто. Детали реализации функции нас не интересует. Внутри мы можем как-то в базу залесть, или еще чего сделать, это совершенно не важно. Нас интересуют аргумент и результат работы этой функции.

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

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

    function prettyErrorsMiddleware(Request $request, callable $next) : Response
    {
         // пробуем получить ответ от следующей функции в цепочке
         try {
              return $next($request); 
         } catch (Throwable $e) {
              // в случае необработанной ошибки, ловим ее
              // и формируем новый ответ с красивой версией этой ошибки
              return renderPrettyError($e);
         }
    }


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

    Поскольку речь идет о PHP мидлвэры можно сделать объектами:

    class PrettyErrorsMiddleware implements RequestHandler
    {
         private $errorRenderer;
         private $next;
    
         public function __construct(ErrorRenderer $errorRenderer, RequestHandler $next)
         {
                $this->errorRenderer = $errorRenderer;
                $this->next = $next;
         }
         public function handle(Request $request) : Response
         {
                // пробуем получить ответ от следующей функции в цепочке
                try {
                    return $this->next($request); 
                } catch (Throwable $e) {
                      // в случае необработанной ошибки, ловим ее
                      // и формируем новый ответ с красивой версией этой ошибки
                      return $this->errorRenderer->render($e);
                 }
          }
    }


    Мы так же можем прервать вызов цепочки наших функций. Например, мы можем сделать мидлвэр который занимается аутентификацией:

    function authentificatedEndpoint(Request $request, callable $next) : Response
    {
        // если мы не передали в запросе информацию о том кто мы и что мы
        // или эта информация не является правдой
        if (!$request->headers->has('X-Authorization') || !isAuthentificated($request->headers->get('X-Authorization'))) {
             // возвращаем ошибку 
             return new Response("You are not autnentificated!", 401);
        }
    
        // все хорошо, можно идти дальше по цепочке.
        return $next($request);
    }


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

    Примерами таких вещей могут быть аутентификация, маршрутизация, CORS, логирование, кеширование, да что угодно! Вот небольшой список того что уже написано: https://github.com/oscarotero/psr7-middlewares#ava...
    Ответ написан
  • Как динамически поменяеть имя класса?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    разве что так.
    <?php
    use My_Ugly_Class_name as PrettyName;


    В вашем случае не стоит менять имена классов. Как минимум если нет тестов.
    Ответ написан
  • Как удалить неявные дубли в массиве php?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    $strings = ['лист осиновый', 'осиновый лист'];
    
    $result = array_unique(array_map(function($str) {
        $arr = mb_split('\s', $word);
        sort($arr);
    
        return implode(' ', $arr);
    }, $strings));


    но это не финальный вариант конечно так как меняется порядок слов.
    Ответ написан
  • Почему анонимные функции называются еще и лямбда функциями?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    Ну как бы в переводе на английский это 3 разных термина те как так получилось что это одно и тоже в php да и наверно в других языках?


    Это три разных термина.

    - Анонимная функция - функция без имени, что логично, то есть у нее нет идентификатора.
    - Лямбды - по сути синоним анонимной функции. Название получило из-за особенностей обозначения оной: 879d4ef555fb7da171253262dbe57013.png (пруф)
    - Замыкание - это частный случай анонимной функции, которая импортирует (то есть имеет доступ) переменные из внешней области видимости. В PHP замыкание можно получить только явно прописав `use` у анонимной функции.
    Ответ написан
  • Как узнать размер (кол-во занимаемых байт) объекта в PHP?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    В PHP есть что-либо аналогичное для определения размера объекта?


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

    Вариант же с memory_get_usage как предлагается выше тоже не будет работать по причине того, что внутри интерприатора все куда сложнее. Для примера:

    class Foo {
        private $bar;
        public function __construct(string $bar) {
           $this->bar = $bar;
        }
    }
    
    $start = memory_get_usage();
    $a = new Foo('test1');
    $middle = memory_get_usage();
    $b = new Foo('longer value');
    $end = memory_get_usage();
    
    echo $middle - $start, PHP_EOL; // 56
    echo $end - $middle, PHP_EOL;  // 56


    Собственно логично что раз у нас размер значений разный то и размер интансов должен быть разным. Не забываем так же что между забором потребления памяти у нас есть так же накладные расходы на ссылку на объект + переменную. Так же не забываем что php выделяет память блоками....

    словом - возможности точно подсчитать размер инстанса в памяти PHP не предоставляет.
    Ответ написан
  • Как правильно орагнизовать API c использованием REST и SOLID при частичном обновлении сущности?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    Действие update для сущности в рамках REST должно выполняться при помощи PUT запроса.


    Фотография пользователя вполне может быть еще одним ресурсом.

    Выполнять один и тот же запрос на оба действия


    Звучит стремно.

    Добавить параметр action к запросу?


    Не restful. Больше на RPC похоже.

    Создать на сервере классы для управления файловыми операциями и формировать запросы вида /user/4/image/?


    users/4/photos или что-то в этом духе.
    Ответ написан
  • PHP регулярка для json?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    Если все что есть в файле это var datajs = {} - достаточно убрать var datajs = и у вас получится JSON, который уже можно разобрать обычным json_decode.
    Ответ написан
  • Статика или функции?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    Глобальное состояние - это плохо. Но вот только вещи типа валидации, обрезки картинок и т.д. не имеют состояния. У вас один вход и один выход.

    Потому функций для этого достаточно.

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

    Ну и ооочень редко нужно хранить статическое состояние. Например сингелтоны полезны когда вам нужно работать с ком портом и вам смертельно важно что бы небыло ни единой возможности создать два экземпляра класса для работы с оным.
    Ответ написан
  • Lazy load для доменного объекта как реализовать?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    Или возможно есть более кашерное решение?


    Прокси объекты.

    https://github.com/Ocramius/ProxyManager

    Например так делает доктрина.
    Ответ написан