Ответы пользователя по тегу PHP
  • Как понять следующие строки(для знающих Zend)?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    php.net/manual/ru/language.namespaces.importing.php

    Как я понимаю use Application\Controller\BaseAdminController заменяется теперь на BaseController


    Нет, мы просто создаем элиас на BaseAdminController с тем именем который нам хочется. Далее читаем документацию по PHP. Zend тут вообще не причем.
    Ответ написан
  • Как реализуется кэширование поиска?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    Как решаются подобные проблемы в серьёзных проектах?


    Никак. Оптимизируют сам поиск, используя денормализацию данных что бы максимально упростить поиск и сделать его как можно менее напряжным для сервера. Ну и что бы "сократить" количество запросов используют "приемы" вроде throttle/debounce на клиенте, что бы не на каждый кник мышкой слать запрос, а когда пользователь не проявлял активности, к примеру секунду.

    Частично эту проблему можно решить HTTP кешированием. То есть все парамеры поиска ходят в queryString а значит по одному URI мы можем иметь нужную страницу/данные. Однако вармат такого кэша будет занимать много времени, а сложность инвалидации будет так высока, что нужно 10 раз подумать прежде чем решаться на такое.
    Ответ написан
  • Как отсортировать массив по нескольким параметрам?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    Давайте разбираться.

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

    $arr = [
        'a1' => 2,
        'a2' => 1,
        'a4' => 5,
        'a3' => 5,
        'a5' => 7
    ];
    
    ksort($arr);
    arsort($arr);
    
    var_dump($arr == [
        'a5' => 7,
        'a3' => 5,
        'a4' => 5,
        'a1' => 2,
        'a2' => 1,
    ]); // true


    На вскидку не смог придумать ситуаций когда arsort сделает лишние перестановки.
    Ответ написан
  • Как через PHP выводить неограниченную вложенность элементов в массиве?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    Проблема состоит в том, как всё это обрабатывать.


    Не совсем так. У вас сейчас проблема с формализацией задачи, что должно выходить в итоге.

    А вот если этих уровней может быть бесконечно много -- уже проблема.


    Курите в сторону графов и поиска в ширину.
    Ответ написан
  • Как из роутера передать данные дальше?

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

    После обработки его ответ можно передать уже в само приложение:


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

    Но в этом случае если путей по сайту много довольно объемный код получается с перечислением всех вариантов роутинга.


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

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

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    Хм... роутер? В целом за "загрузку классов" отвечает автозагрузчик (например тот который генерит composer). Вам же нужно просто отдельный объект, который находит кого вызывать.

    p.s. посмотрите реализации популярных роутеров.
    Ответ написан
  • Логирование при микросервисной архитектуре?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    Каждый микросервис живет своей жизнью. Если мы отправили запрос от микросервиса A к микросервису B, а тот отправил запрос на C, микросервису A глубоко плевать что пошло не так. Он не знает ничего о C и знать ничего не должен.

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

    Но в логи сообщения будут ложиться каждым сервисом независимо. Возможность трекать цепочки ошибок есть, а далее можно агрегатором логов просто слать сообщения той команде, которая занимается тем или иным сервисом.
    Ответ написан
  • Как идёт взаимодействие между PHP/MySQL/Apache?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    то я вовсе не понимаю зачем нужен Apache (говорю именно о нём, т.к. ни о чем другом не слышал).


    Гуглим про HTTP

    Сейчас геморрой есть, чтобы поставить всё это и сконфигурировать, надо разбираться.


    Вам сейчас достаточно тупо php поставить. php.net/manual/ru/features.commandline.webserver.php Apache вам не нужен.
    Ответ написан
  • Это и есть полиморфизм?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    Нет.

    Полиморфизм, как следует из названия, это когда что-то маскируется под что-то другое. Это свойство системы типов языка на котором вы пишите, он может позволять вам делать вещи, маскирующие свой внешний вид ("названия") но все же это не та же вещь. Ну и стоит заметить что у полиморфизма есть еще разные виды. Например:

    Параметрический полиморфизм. Это когда мы можем написать один код, с одним набором имен, которые работает с разными типами аргументов. Пример - шаблоны из C++ или дженерики в Java. То есть "имена" методов одинаковые, потому что они в одном экземпляре. Реализация одна, одно поведение. А вот аргументы могут отличаться.

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

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

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

    Ну и еще есть одно серьезное ограничение. Если мы хотим заменить в системе объект какого-то типа на объект подтипа (грубо говоря наследника), то система не должна сломаться. То есть "другое" поведение нашего подтипа должно быть совместимо в плане интерфейса с базовым типом. Об этом можно почитать загуглил "Принцип подстановки Барбары Лисков".

    Ad-hoc полиморфизм - это пожалуй самый интересный вид полиморфизма с которым можно долго холиварить. По сути при этом виде полиморфизма, у нас одинаковые имена, а поведение зависит от входящих аргументов. Пример - перегрузка методов в C++. Интересен этот вид полиморфизма в основном тем, что он не является "настоящим".

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

    Среди PHP-разработчиков немало тех, кто мечтает увидеть в этом языке с динамической системой типов честную перегрузку методов как например в Java или C++. Просто так, потому что if-ы это плохо и лучше уж пусть они будут неявные на уровне компилятора/рантайма.

    Полиморфизм с приведением типов - еще один вид "не настоящего" полиморфизма. Мы "эмулируем" полиморфизм за счет того, что на уровне рантайма языка происходят касты действительного в желаемое. Например в PHP мы можем выставить у функции тайпхинтинг string, и можем внутри иметь одно и то же поведение для всех входящих аргументов. Передать же в качестве аргумента мы можем все что можно скастить в строку.

    Собственно, это очень похоже на параметрический полиморфизм по смыслу, но далеко не так гибко и не дает того контроля за системой.
    Ответ написан
  • Где найти паттерны "правильных" частей системы?

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


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

    Большие проекты начинают проектировать с более высокого уровня. Сначала принимают решение о том, какое разделение на слои у нас будет (для проектов со сроками жизни ~10+ лет имеет смысл позагоняться и вводить гексагональную архитектуру, для проектов со сроками жизни <= строк поддержки фреймворка можно не сильно париться), какие компоненты можно выделить, а уже потом дробить эти большие компоненты на компоненты поменьше.

    Затем уже приступать к проектированию каждого отдельного компонента на уровне классов.

    Так же если у нас сложная предметная область - проектируют модель предметной области. Обычно тут "паттерны" сами собой получаются тупо при снижении связанности между объектами.

    > Собственно вопрос: существует ли сборник всех этих лучших практик?

    вне контекста не бывает лучших практик, есть просто практики. В этом плане можно например Фаулера почитать, он очень качественно описывает практики, их плюсы и минусы.

    В целом же я бы рекомендовал вам познакомиться поближе с принципами SOLID и GRASP. Последнее мало кто знает, но понимание, например, что такое высокое зацепление, сильно влияет на то, как вы будете проектировать систему.
    Ответ написан
  • PHP Abstract Registry или методы __set() and __get(), как лучше реализовать глобальную переменную?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    Какой вариант предпочтительнее? Страшно ли объявление как в первом варианте? Или как лучше поступить?


    Настоятельно рекомендую вам отказаться от идеи использования глобальных переменных. Оно вам не нужно.

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

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

    Затем мы это состояние из контроллера скармливаем в шаблонизатор какой и получаем view. Замечу что view в контексте вопроса это просто пассивное отображение данных на HTTP.

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

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    Ведь в любом случае мы получаем глобальное состояние


    А глобальное состояние что? Правильно, плохо. У меня тут недалеко есть один небольшой проектик под iOS где ребята решили повесилиться, и сделали сингелтон с сотней публичных свойств. И вся система работает с этим глобальным состоянием плодя побочные эффекты. Инкапсуляция? не, не слышали.

    Какой смысл использовать именно singleton?


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

    В PHP, где не не особо популярна идея многопоточного программирования, и процветает "умирающая" модель выполнения, в сингелтонах вообще нет смысла. И используют их потому что... внимание... хотят иметь глобальный доступ к различной фигне, в том числе организация глобального состояния.
    Ответ написан
  • Как правильно сделать аутентификацию на php?

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


    Не забывайте, что в фреймворках это все сделано с одним расчетом - покрыть 95% возможных юзкейсов. А в связи с этим реализация чуточку сложнее. Так же не стоит забывать, что все это "должно" работать на php5.4+, а, например password api появился только в 5.5, а хэширование пароля это целая наука.

    Давайте разложим задачу на под задачи:

    Нам нужно проверить введенные пользователем данных. Это может быть пара идентификатор + какой-то секретный ключь (email + пароль если проще), а может это просто секретный ключ (токен), или JWT токен... словом вариантов тут много, но нам пока нужна пара старых добрых email + пароль.

    Для этого в PHP есть весьма простая в использовании апишка для работы с паролями: password api. Используйте только ее (или что-то что ее под копотом использует) ибо это самый безопасный и надежный способ работы с паролями в PHP. Обязательно прочитайте этот раздел документации.

    В очень простом случае (коих большинство) вам при регистрации нужно просто загнать строчку в password_hash и получить на выход новую строчку, которая пишется в базу. При логине мы забираем пользователя с указанным email и проверяем введенный пароль через функцию password_verify.

    После того как мы убедились что пользователь не выдает себя за другого, мы можем создать сессию. В самом простом случае мы просто создаем сессию с ID юзера и... собственно все. идентификатор сессии будет записан в http-only куку и все здорово. Правда при работе с сессиями в PHP нужно помнить про CSRF атаки, от которых нужно защищаться (что умеют практически все фреймворки из коробки).

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

    p.s. поскольку этот вопрос весьма щепетильный, и ля того что бы сделать все это "безопасным" нужно порядком опыта, я рекомендую вам разобраться с фреймворками или готовыми популярными библиотеками.
    Ответ написан
  • Для каких целей используется директория upload/?

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

    upload - загружать

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

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    function getPathTree(string $path) : array
    {
        $paths = [$path];
        while('/' !== $path=dirname($path)) {
             $paths[] = $path; 
        }
        return array_reverse($paths);
    }
    Ответ написан
  • Как найти пересечение массивов?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    $ids1 = array_column($result1, 'id');
    $ids2 = array_column($result2, 'id');
    // ...
    $idsn = array_column($resultn, 'id');
    
    $intersection = array_intersect($ids1, $ids2, ..., $idsn);


    Или если упростить:

    $ids = array_intersect(
        ...array_map(function(array $collection) {
             return array_column($collection, 'id');
        }, $results)
    );


    updated:

    $result = null;
    foreach($sql_queries as $sql_query) {
      $query_result =  $wpdb->get_results($sql_query);
      $ids = array_column($query_result, 'id');
      if (null === $result) { 
          $result = $ids; 
      } else {
          $result = array_intersect(
                $result, $ids
          );
      }
      $result = array_merge($result, $query_result);
    }
    Ответ написан
  • Как правильно реализовать фасад?

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


    Это не фасад, это service locator, глобальный доступ к зависимостям. Не делайте так, используйте IoC, например PHP-DI. Даже в laravel потихоньку от этой сатаны отказываются.

    Фасад - это когда мы берем несколько интерфейсов, и строим над ними один попроще.
    Ответ написан
  • Parse error: syntax error, unexpected $end php?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    отформатируйте код и вы обнаружите пропажу.
    Ответ написан
  • А нужны ли нам FrameWorks?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    который будет в будущем сильно обрастать ( куча фич )


    на личном сайте, где ежедневно будет высокая нагрузка трафика и собственных фич


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

    2) "высокая нагрузка" - понятие относительное. В подавляющем большинстве проектов докупить еще парочку серверов выходит дешевле (время деньги). Если бы вас так парил вопрос производительности то вы бы выбирали язык программирования другой. А так, даже с laravel и другими весьма жирными фреймворками можно спокойно добиться времени обработки запроса <100ms

    3) Вместо того что бы пилить фичи, вы хотите делать свой фреймворк (так или иначе у вас сформируются свои прослойки для работы с базой, свои абстракции над HTTP и т.д.). В принципе можно использовать готовые компоненты но это нужно делать когда вы вырастите из фреймворков (то есть после так лет 5-ти использования готовых, причем желательно не одного фреймворка).

    Далее делайте выбор сами. Это ваш личный проект и все риски вы берете на себя.
    Ответ написан
  • Как работают URL запросы?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    Сначала

    википедия: HTTP

    потом

    гугл: objective-c отправить http запрос
    Ответ написан