• Где писать логику работы с БД?

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

    Однако, лично я считаю этот паттерн вредным, потому что он намешивает всё в одну кучу. Это моё субъективное мнение, и я вам его не навязываю. Я бы отделил мух от котлет, и оставил бы структуру чистой, т.е. только данные и какие-то методы, которые работают конкретно с этими данными из структуры, а взаимодействие с базой данных организовал бы через паттерн проектирования Repository. Т.е. мы делаем уже отдельную структуру ProductRepository, которая содержит в себе методы, принимающие и отдающие структуру Product, и уже в этих методах реализуем вызов базы данных.

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

    package models
    
    type Product struct {
    	ID    int    `json:"id"`
    	Title string `json:"title"` //Название
    	Price int    `json:"price"` //Цена
    }
    
    type ProductGetter interface {
        GetAll() ([]Product, error)
        GetByID(id int) (Product, error)
    }
    
    type ProductCreator interface {
        Create(product Product) (Product, error)   
    }
    
    type ProductUpdater interface {
        Update(product Product) (Product, error)
    }
    
    type ProductDeleter interface {
        Delete(id int) error
    }
    
    type ProductRepository interface {
        ProductGetter
        ProductCreator
        ProductUpdater
    }
    Ответ написан
    4 комментария
  • Какие технологии использовать для создания веб-сайта на go?

    Судя по описанию задачи, вам вполне подойдёт довольно мощный генератор статических сайтов Hugo. https://gohugo.io/

    Однако, придётся обучить заказчика этим пользоваться, там не всё так просто. Поэтому, если заказчик не очень сильно настаивает на выборе технологии, то берите WordPress, не ошибётесь, сэкономите ещё и нервы при общении с заказчиком
    Ответ написан
    Комментировать
  • Получил заказ на первый сайт от знакомых, выбираю бэкенд систему - cms либо python, что в связи с этим посоветуете?

    Язык программирования, фреймворки, CMS и т.д. - это только лишь инструменты для выполнения главной задачи: решить бизнес-проблему заказчика.
    С этим пониманием сделаем вывод, что выбирать инструмент нужно наиболее подходящий к задаче, но так же надо учитывать и то, насколько хорошо вы владеете тем или иным инструментом. Но всё же научиться пользоваться молотком гораздо быстрее и проще, чем мучиться, забивая гвоздь микроскопом.
    А при слове "визитка" мой опыт громогласно кричит WordPress!
    Ответ написан
  • Что делать, если unexpected end, но код раньше работал?

    У вас открывающих тегов "<?php" 28 штук, а закрывающих "?>" - 29 штук. Один из ваших открывающих тегов укороченный "<?" (строка 155).  Я не знаю, какая у вас сейчас версия PHP и какая настройка по поводу коротких тегов, но рекомендую короткие открывающие теги не использовать.

    Плюс рекомендую исправить ошибку, два раза закрываете один и тот же тег
    668a9eff0f49b708574679.png

    А еще всегда попробуйте везде добавить пробел перед вопросом в закрывающей конструкции "?>".
    Очень часто именно это является проблемой
    Ответ написан
    6 комментариев
  • А возможно ли сделать свой дублирующий хостинг-сервер?

    Для надёжности вам нужно 3 сервера:
    1 - ваш VPS
    2 - ваш домашний сервак
    3 - Load balancer, который будет настроен таким образом, чтобы направлять трафик на сервер 1, но если он лёг, то направлять его на сервер 2.

    Чтобы не покупать отдельный сервер под Load balancer, можете посмотреть в сторону специальных сервисов. Например Cloudflare: https://developers.cloudflare.com/load-balancing/
    Ответ написан
  • Из-за чего инкрементация в for и while срабатывает по разному?

    Обратите внимание на конструкцию for.
    Вы не замечаете, что выражения между скобками разделены не запятой, как, например, в аргументах функции, а точкой с запятой?

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

    Уяснив этот момент, можно пойти в документацию, прочитать там все, а особенно обратить внимание на табличку, где расписано, когда именно выполняется каждая составная часть цикла for. И тогда вам всё станет гораздо понятнее.
    https://learn.javascript.ru/while-for

    Советы:
    1. Всегда читайте документацию, если вам что-то не понятно в конструкциях языка. Не туториалы от балбесов с Ютуба, а документацию. И желательно оригинальную на английском, потому что переводчики иногда такие же балбесы.

    2. Не используйте никаких циклов, кроме for. Он очень мощный и позволяет реализовать функциональность и while и do-while. Так вы убережёте себя от таких ситуаций. Я за много лет работы понял, что большое количество конструкций языка скорее вредно, чем полезно.
    Ответ написан
    2 комментария
  • Как эффективнее всего вести создание продукта?

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

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

    - Если приложение, в котором вы сравниваете производительность, написано для Винды и только потом портировано на Linux, то вы можете увидеть даже падение производительности. И то же самое наоборот: если приложение или сервис изначально сделаны для Linux, то тут может быть разница уже в его сторону. Типичный пример - Docker

    - Производительность хорошо оптимизированных приложений, которые выжимают все соки из CPU/GPU будет примерно одинакова.

    - Gnome, который стоит у вас в Ubuntu в качестве окружения - тормозящая и жрущая все ресурсы какашка. Если вы установите какое-то легковесное окружение или даже просто какой-то Window manager, вот тут вы заметите явный прирост в отзывчивости всего и вся.

    - И, наконец, главный источник производительеости - это работа с памятью. Если вы замените Gnome на лёгкое окружение, то расход памяти значительно уменьшится. На Linux обычно нет встроенной телеметрии, рекламы и остального шпионского мусора, как в Винде. Это тоже экономит память. И вот, когда на Винде наступит момент забраться в swap, на Linux останется ещё много свободной памяти. В этот момент Винда начнёт лагать, а Linux продолжит летать.
    Ответ написан
    4 комментария
  • Как маппить результат запроса бд в структуры со вложенностями Golang?

    - Я считаю, что свой кастомный маппер - это отличное решение. Чтобы быть уверенней, обязательно напишите тесты. Как unit, так и интеграционные, например, с помощью testcontainers.

    - Можете вместо pgx посмотреть в сторону sqlc. У него совершенно другой подход. Вы пишете запрос со всеми джойнами, а он вам автоматически генерирует код со всеми структурами и функциями. Правда, там по джойнам практически отсутствует документация, но уж погуглите.

    - Ну, и если совсем сложно... то... может одним глазком глянуть в сторону ORM? Я никому не расскажу...
    Ответ написан
    5 комментариев
  • Почему не срабатывает ссылка подтверждения регистрации в Symfony 6?

    private VerifyEmailHelperInterface $verifyEmailHelper,


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

    Судя по запятой в конце строчки, свойство $verifyEmailHelper объявляется сразу в конструкторе. А "Constructor property promotion" появился только в версии PHP 8.0

    Поэтому, если версия PHP ниже, появляется подобная ошибка.
    Ответ написан
    1 комментарий
  • Переход с MD5 на SHA256 что нужно сделать чтобы работало)?

    Согласен с обоими ответившими. Дополню, как конкретно я бы сделал.

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

    Можно, например, для нового хеша завести новое поле в базе с дефолтным null.

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

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

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

    Да, и не удаляя сразу данные из старого поля, мы всегда сохраняем возможность вернуться на старую схему, если вдруг обнаружили какую-то дыру в безопасности нашего нового метода.
    Ответ написан
  • Как добавить php5.6 в ubuntu 16.04.07?

    Зачем все эти мучения в 2024 году, когда можно один раз разобраться в том, что такое Docker, и навсегда забыть о подобной головной боли...

    https://hub.docker.com/layers/library/php/5.6-apac...
    Ответ написан
    2 комментария
  • Как устранить утечку памяти при множественных соединениях в net/http Golang?

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

    var client = &http.Client{
        Timeout: time.Millisecond * 100,
    }
    
    func scan(ip string) (error, string, string, string) {
        resp, err := client.Get("http://" + ip)
        // Здесь сразу желательно обработать ошибку ...
        
        // Закрываем соединение в конце выполнения
        // функции в любом случае,
        // даже если где-то возникнет ошибка
        defer resp.Body.Close()
    
        // Закрытие неиспользуемых соединений
        // Нужно ли это теперь?
        // client.CloseIdleConnections()
    
        // Проблема могла быть тут
        // if err != nil {
        //     return err, "", "", ""
        // }
    
        headers := buildHeaders(resp.Header)
        body, _ := io.ReadAll(resp.Body)
    
        // и это нам уже особо не нужно
        // resp.Body.Close()
    
        return err, headers, string(body), resp.Status
    }
    Ответ написан
    3 комментария
  • Как выровнять по высоте заголовки в карточках товаров?

    В карточке элементы flex выравниваем книзу. Однако при помощи "магического" margin-bottom выравниваем изображение и заголовок против основного выравнивания контента, а именно кверху. Таким образом часть элементов карточки льнёт кверху, а часть книзу. Между ними будет свободное место. В результате мы получаем необходимый результат - иллюзию одинаковой высоты заголовков.



    Саму сетку карточек выровняете сами, я не заморачивался, сосредоточившись только на самой карточке
    Ответ написан
    Комментировать
  • Запросы soap в инфоклинику на php?

    Когда я вижу слово SOAP в задаче для PHP, меня инстинктивно передёргивает. Ненавижу и саму идею SOAP, и, особенно, её идиотскую реализацию в PHP.

    Лично для себя нашёл решение: если мне нужно только несколько конкретных запросов от какого-то SOAP сервиса, я просто беру и делаю запросы при помощи curl и чистого XML. И создание XML запроса, и потом парсинг XML ответа, для меня проще, быстрее, приятнее и надёжнее, чем работа с дурацким SoapClient

    Вот вам пример работы с SOAP через curl
    https://stackoverflow.com/questions/7120586/soap-r...

    Т.е. берём программу SoapUI, подключаемся к их апихе, копируем оттуда примеры XML запроса и ответа для наших нужд, и пишем curl запрос по этим шаблонам.

    Кстати, есть инструменты, которые позволяют сгенерировать целый пакет для работы с определенным SOAP API по его wsdl адресу. Там и классы запросов и классы ответов будут сгенерированы, и всё, чтобы делать запросы.
    Можете попробовать, но я недолюбливаю такие инструменты.
    https://github.com/WsdlToPhp/PackageGenerator
    Ответ написан
  • Как добавить отношения "многие-ко-многим" между таблицами из разных баз данных?

    Если вы разделяете проект на микросервисы, но связываете при этом их данные, то вы просто делаете распределённый монолит. А когда вы ещё и базу разрываете на два куска, при этом пытаясь сохранить между ними традиционные связи, как внутри одной базы данных, то вы:
    1. Не решаете абсолютно ни одной из задач микросервисов, т к. сервисы остаются жёстко связанными. Всё можно было бы решить просто при помощи "Clean architecture", DDD и т.д.
    2. Вы добавляете себе невероятное количество головной боли, связанной с самой микросервисной архитектурой, но и плюс все прелести из п.1.
    3. И тогда нафига козе баян?

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

    Оно вам надо?
    Ответ написан
    Комментировать
  • Как сделать авторизацию по двум таблицам в Symfony?

    Разные категории пользователей в Symfony лучше всего организовать при помощи ролей.

    Основная таблица users будет содержать всех ваших пользователей, это проще всего. Там же и будет поле с ролями.

    Для дополнительных полей другой категории пользователей лучше всего создать отдельную таблицу, которая будет связана с основной через связь one-to-one либо one-to-many по id пользователя (посмотрите уроки по Doctrine).

    Однако, если пользователей с этими дополнительными полями будет подавляющее большинство, то можно не усложнять, а смело создавать эти поля в основной таблице users.

    Очень советую досмотреть полностью уроки с symfonycasts.com. Они великолепны, и там точно всё необходимое должно быть.
    Ответ написан
    2 комментария
  • Как убрать отступ?

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

    Добавляем в начало и в конец родительского блока невидимый контент нулевой высоты при помощи ::after и ::before. При этом идеальным значением свойства display этого невидимого контента будет table, т.к. оно работает именно так, как нам надо, а именно, имеет нулевую высоту по умолчанию.



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



    Ну, и на самый крайний случай, если уж и предыдущие два не устроят, то старый добрый float: left; никто не отменял ))))



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

    Ответ написан
    Комментировать
  • Как замаскировать переменную внутри контейнера?

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

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

    Поэтому, сейчас всё чаще используются специальные сервисы по хранению секретов.
    Я вам рекомендую посмотреть, например, в сторону Hashicorp Vault и его Dynamic Secrets:
    https://www.hashicorp.com/products/vault

    Вот статья об интеграции в Gitlab:
    https://docs.gitlab.com/ee/ci/examples/authenticat...

    Видео о том, что это такое, и как это работает:
    https://youtu.be/VYfl-DpZ5wM?si=SutHlBsLe70qCIVm
    На русском: https://youtu.be/-HIy89Vyobg?si=O4e8AL1SSCm8ImV1
    Ответ написан
    1 комментарий