• Laravel vs WordPress?

    ThunderCat
    @ThunderCat Куратор тега PHP
    {PHP, MySql, HTML, JS, CSS} developer
    Если я выберу WordPress, то не выйдет мне это боком, если проект будет расти?
    Выйдет конечно, нет в вп ни нормальной архитектуры, ни гибкости, ни целостности. 90% плагинов и надстроек никем и никогда не тестировались нормально, ну там тесты, квалити контрол, кодестайл и вот это все.
    Все фреймворки же в основном:
    1) Гибкие и с нормальной архитектурой
    2) Покрыты тестами и удовлетворяют кодестайлу
    3) Весь новый функционал пишется поверх оттестированных компонент, если нужно что-то особенное - не надо думать как скрестить ежа с ужом, все можно сделать в едином стиле и без костылей.

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

    Совет - если это проект выстрелит/не выстрелит 50/50 - фигачьте мвп на вордпрессе, если взлетит - переписывайте. Худо-бедно оценить проект можно и на таком велосипеде. Дальше все равно надо будет писать нормальный проект.
    Ответ написан
    Комментировать
  • Насколько грамотно построено взаимодействие между фронтом и бэком?

    Robur
    @Robur
    Знаю больше чем это необходимо
    Сам подход нормальный, и смысл реакта никак не теряется. Более того, некоторые считают подобные вещи более прогрессивным подходом а фреймворки типа Gatsby.js этот подход развивают куда дальше чем описанное у вас.

    Грамотно это у вас сделано или нет - зависит от того как сделано.
    Если в window кладутся просто настройки типа языка и прочего - то тут вообще сложно что-то криво сделать.
    с условной загрузкой компонент в зависимости от роута на сервере тоже нет проблем если сделано хорошо
    Ответ написан
    1 комментарий
  • Насколько грамотно построено взаимодействие между фронтом и бэком?

    @disappearedstar
    Фронтенд-разработчик
    Реакт — это не фреймворк для SPA, а библиотека для создания интерфейсов. В крупных и/или старых веб-приложениях, особенно на этапе постепенного внедрения нового стека и перехода на SPA, вполне уместна и практикуется описанная вами схема, когда роутинг реализуется классически через многостраничность, а рендеринг происходит частично на сервере, а частично — на клиенте, причем дорисовываемые на клиенте куски интерфейса ("виджеты") могут быть как компонентами, так и самостоятельными реакт-приложениями (вместо реакта можно подставить любую другую библиотеку/фреймворк). Передавать данные через window тоже нормально, если эти данные уже были сформированы на сервере и использованы для серверного рендеринга.
    Ответ написан
    1 комментарий
  • Я правильно понимаю, что php и nodeJS на одном сервере, это какая-то ересь?

    deepblack
    @deepblack
    Совмещают ли php (apache) и node.js на одной машине? Можно ли так делать? Или это глупо?

    Совмещают, для разных сервисов (их может быть десятки-сотни на одной физической машине)
    Может быть что в одном проекте используются микросервисы на разных языках (помимо тех что указаны в вопросе),
    + Python, Golang, Ruby и т.д.
    В общем никаких особых ограничений нет, но разве что могут быть проблемы при поиске разработчиков на проект.
    Ответ написан
    Комментировать
  • Чем проще всего воспользоваться для HTMl to PDF?

    wkhtmltopdf
    Ответ написан
    Комментировать
  • Чем проще всего воспользоваться для HTMl to PDF?

    @KingstonKMS
    mPDF
    Ответ написан
    Комментировать
  • The property ... is not readable because it is typed "string". Но почему?

    AleksandrB
    @AleksandrB Автор вопроса
    Совсем недавно вывел "Hello world"
    Нашел. Для тех, кто столкнулся
    private ?string $slug = null;

    Причина заключается в том что разработчики языка считают плохой практикой присваивать по дефолту значение null к пустому свойству, которое они не будут поддерживать.
    Ответ написан
    2 комментария
  • Какой подход для валидатора правильней?

    Vamp
    @Vamp
    Архитектурно правильнее возвращать как в примере с Yii2. Использование исключений для управления потоком выполнения программы считается серьёзным антипаттерном.

    Например:
    1. Исключения в данном случае - просто более хитрая замена оператору GOTO. Надеюсь, не нужно объяснять почему GOTO тоже считается антипаттерном?
    2. Программы, написанные в таком стиле, становится сложно читать и понимать.
    3. Меньшая эффективность в рантайме, так как большинство современных компиляторов не оптимизированы для случаев использования исключений в качестве управляющей логики.

    Более подробно по ссылке.
    Ответ написан
    5 комментариев
  • Какой подход для валидатора правильней?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    Мне не равится ни тот ни другой подход.

    Исключение при валидации - это оксюморон.
    Исключение кидается кода функция не может выполнить свою работу. Проифнормировать о невалидности данных - это как раз функция функции валидации. Где тут исключительная ситуация?
    Вот для функции, скажем, сохранения данных, невалидные данные - это абсолютно законный повод кинуть исключение. Но для функции валидации - ни в коем случае.
    Функция проверки уникальности введенного логина не должна кидать исключение, если логин не уникальный.
    Исключение она должна кидать если БД недоступна.

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

    Можно применить технику разового чтения главной сущности (аккордеон) постранично, а для сопутствующей информации опрашивать исходя из полученного набора с идентификаторами id.
    Select ... from accordions
    INNER JOIN city ...
    Limit ?, ? /*смещение, количество*/

    Select cities.id, ... from dilery
    INNER JOIN city ...
    Where cities.id in (список получен ранее)

    И формируем результат на основе этих двух выборок.
    Советую почитать про Шаблон материализованного представления, который предлагает сделать это даже более оптимальным способом.
    В сочетании с кэшированием дает хорошие результаты.
    Ответ написан
    Комментировать
  • Для чего так делают?

    syamskoy
    @syamskoy
    Интерфейс нужен не для того, что бы вы не забыли добавить какой-то метод. Он нужен, что бы вы работали, с контрактами. Например:
    public function addToSwimmingPool(Swimming $animal): void
    {
        $this->pool[] = $animal;
    }

    Так вы гарантируете, что добавите в бассейн только плавающих животных.

    Без использования интерфейса, пришлось бы делать так:
    public function addToSwimmingPool($animal): void { ... }

    Тут вы могли добавить что угодно в массив. И потом где-нибудь программа бы сломалась, так как у переданных объектов нет нужных методов.

    public function addToSwimmingPool(Penguin $animal): void { ... }

    А так вы кроме пингвинов никого больше не добавите.
    Ответ написан
    Комментировать
  • Для чего так делают?

    @Nc_Soft
    Интерфейс ГАРАНТИРУЕТ наличие такого метода в классе.
    Ответ написан
    3 комментария
  • Как сделать, чтобы засчитывались уникальные просмотры?

    xmoonlight
    @xmoonlight
    https://sitecoder.blogspot.com
    Основной вариант:
    Только рега посетителей (читателей) через sms с фильтрацией доступа этого акка по IP (по региону оператора номера мобилы).

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

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

    Maksclub
    @Maksclub Куратор тега PHP
    maksfedorov.ru
    Юнит-тест:
    Юнит-тест невозможен в данном случае, тк нет этого самого юнита в виде чистой функции (без побочных эффектов). Тут сплошной сайд-эффект: отправка на SMTP, прослушивание HTTP, то есть особо не потестируешь юнитами.
    Объектом тестирования юнит-тестом служит или функция или объект. А у вас и нет ни функции/процедуры даже хотя бы.

    Это будет функциональный (если будете из кода вызывать) или приемочный (если свое приложение через HTTP дергать) в любом случае.

    Как по итогу все же протестировать:
    Такой функционал обычно тестируют так:
    • для начала настройки отправки почты переносят в конфиг
    • в тестовом окружении в конфиг подсовывают настройки своего SMTP сервера
    • поднимают фейковый почтовый сервер, например Mailhog на Go (очень легко ставится)
    • выполняют работу скрипта, чтобы почта ушла, почта летит на ваш подмененный сервер, и у него через АПИ проверяют, что письмо пришло


    Если возьмете Codeception, установите Mailhog на машину, где будут гоняться тесты, или докер-контейнер (вообще парой строк, например если в Gitlab CI гоняете), и поставите модуль Codeception + Mailhog. То легко все проделаете.
    Ответ написан
    2 комментария
  • Как совместить реляционную модель бд с ООП?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    Неужели сама идея реляционных бд с ООП несовместима?


    Ты весьма недалёк от истины.
    Некоторые сравнивают эту проблему с проигранной США войной во вьетнаме.

    Решение от Victhor подходит для единичных выборок, но как быть с коллекциями? Люди начинают изобретать разные стратегии подгрузки - lazy loading, eager loading. Вот Елоквент, например, собирает в кубышку все айди загруженных товаров и потом пуляет 1 запрос с IN (...) чтобы получить для них бренды, которые потом в цикле пришпандоривает к товарам.

    Но все это очень быстро начинает сказываться на производительности. И всё дальше затягивает нас в пучину Вьетнамской войны, или другими словами в кроличью нору Object-relational impedance mismatch - как по-научному называется озвученная тобой проблема. Дальше начинается совсем уж треш и угар, типа дико тормозащих коллекций в Доктрине или таких извращений, которыми занимался один мой знакомый - он плодил вьюхи в БД, поскольку его ОРМ умел работать только с одной таблицей.

    Или все же модифицируются в дальнейшем классы, переписыванием кода?


    В одном ты можешь быть уверен: такое легкое отображение, которое рисует тебе воображение при первом знакомстве с ORM - чтобы так хоба-хоба, и у нас записи из БД отобразились в объекты - увы, не существует. Да, приется переписывать, и много. И чем сложнее взаимосвязи, тем хуже будет работать автоматизация.

    И тут на первый план выходит организация ORM и становится очевидной превосходство стратегии Data Mapper, когда слой работы с БД полностью отвязывается от объекта бизнес-логики.

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

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

    И это мы сейчас говорим о read-моделях, и даже не трогали тему write models - то есть сохранения измененного объекта - со всеми гроздьями смежных объектов(!) - в БД!
    Ответ написан
    4 комментария
  • Правильное ли использование принципов DDD, и чем заменить Repository?

    @dimuska139
    Backend developer
    Вообще-то как раз Repository - это тот слой абстракции, который нужен, чтобы на уровне бизнес-логики (слой сервисов) абстрагироваться от способа хранения данных. То есть, очевидно, нужно использовать Repository.

    Контроллер должен работать только с сервисным слоем. Моделью (Entity) является тот класс, на который вы маппите пользователей, прочитанных из XML-файла. То есть в репозитории надо сделать метод, читающий XML, формирующий коллекцию из Entity (юзеры) и возвращающий ее. На уровне выше (в сервисном слое) надо сделать метод, который как раз вызывает этот метод репозитория. Методы сервиса в свою очередь надо дергать из контроллера, либо из класса консольной команды, если код кроном вызывается. То есть из контроллера дергать репозиторий не принято. А сервисный слой нужен, чтобы в нем держать всю бизнес-логику.
    Ответ написан
  • Как организовать обработку больших объемов данных?

    sergiks
    @sergiks Куратор тега PHP
    ♬♬
    Несколько не связанных идей:
    1. хранить каждую «последовательность» (набор) из 500000 (не важно, сколько) чисел как картинку с 1-битным цветом, 3873*3873px, чтобы покрыть диапазон 0..15e6. Будет 15 млн. таких картинок. Черный пиксель - число, белый - нет числа. Картинки можно накладывать и смотреть, насколько потемнело ) Но в цифре это делать неэффективно, вот если бы аналогом..
    2. хранить последовательность как бинарную строку, где включённые биты означают выбранное число. 15e6 бит примерно 1875e3 байт =~1.9Mb на набор. 1875e3 * 15e6 = 28125e9 байт =~28Тб
    3. хранить как бинарный файл по 3 байта (24 бита) на число. 0–15 млн прекрасно уместятся: 224 = 16 777 216. См. php функции pack() / unpack(). Один набор 500000 * 3 = 1.5Мб, 15млн наборов 22.5Тб
    4. Не хранить всё. Полное покрытие диапазона 0..15 млн. идеально подобранными диапазонами по 500 тыс. потребует всего 30 таких диапазонов.
    5. Гипотеза. Если все выборки действительно случайны, можно брать любые N, они окажутся хуже «настоящего» максимума лишь незначительно.
    6. «Расчеты одной последовательности идут долго порядка 3-х минут» 180 секунд * 15e6 = 27e8 секунд, это почти 86 лет. А вы за несколько дней собирались как-то?

    Ответ написан
    1 комментарий
  • Как найти похожие ПО ЦВЕТУ товары по изображению?

    xmoonlight
    @xmoonlight
    https://sitecoder.blogspot.com
    https://github.com/jenssegers/imagehash
    https://github.com/xwiz/phash

    Ищите минимальное расстояние Хэмминга и после - уже на них ищите отношения цветов пикселей (RED25%/TOTAL, RED50%/TOTAL, ..., GREEN25%/TOTAL, GREEN50%/TOTAL,....): каждого цветового сегмента одного канала к общему количеству пикселей.
    Цветовой сегмент - это процент по цветовому каналу.
    Самые близкие дроби нужного Вам цвета - это и будет то, что Вам нужно: похожие с конкретным цветом.

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

    Уменьшить кол-во цветов: здесь и см. 1-й коммент!
    PS: пока - можно без НС всё сделать.
    Ответ написан
    2 комментария
  • Как найти похожие ПО ЦВЕТУ товары по изображению?

    @freelion93
    По расписанным тобою шагам алгоритм следующий:

    1) Картиночки обрабатываем в бэкэнде на Python, там очень много библиотек для машинного зрения, обучения. Можно задействовать Deep Learning и строить нейронку по мере наполнения базы с классификацией.

    2) Привязываем красивый фронтенд с формочкой для заливки изображения юзера, которое отправляем нейронке в бэкэнд и она его распознает. Выдаст класс изображения и картиночки с тем же классом. Результат шлем обратно фронтенду.

    Подробно описано тут: https://medium.com/@innarticle/how-to-create-image...
    Ответ написан
    2 комментария
  • Как защитить пользовательские файлы?

    xmoonlight
    @xmoonlight
    https://sitecoder.blogspot.com
    1. Открытым ключом сервера шифруем файл на фронтенде перед непосредственной отправкой.
    2. При просмотре файла (скачивании) - отдаём через внутреннее API, которое расшифроввывает файл закрытым ключом, но к коду этого API (+закрытому ключу) имеет доступ только один доверенный человек.
    3. Каждый администратор - получает свой токен доступа к этому API, определяющий доступ к просмотру конкретных файлов (по клиентам, группам и т.д.).
    Ответ написан