• Почему не назначаются разрешения на папку в volume-е?

    rqdkmndh
    @rqdkmndh
    Web-разработчик
    Изменение прав доступа к папке в Dockerfile с помощью RUN chmod не действует на тома (volumes), примонтированные при помощи инструкции volumes в docker-compose.yml. Это связано с тем, что тома подключаются после выполнения всех команд указанных в Dockerfile, и их содержимое не изменяется в процессе построения образа, что означает, что фактические данные тома и права доступа управляются внешним хостом.

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

    Если же настройка прав доступа должна выполняться внутри контейнера (например, при инициализации или запуске), вы можете использовать команду entrypoint или command в docker-compose.yml для запуска скрипта, который будет устанавливать нужные права доступа при запуске контейнера каждый раз. Пример такого скрипта:
    # Dockerfile
    ...
    
    # Установка прав доступа в скрипте инициализации
    COPY ./set-permissions.sh /usr/local/bin/set-permissions.sh
    RUN chmod +x /usr/local/bin/set-permissions.sh
    
    # Запуск скрипта при старте контейнера
    ENTRYPOINT ["set-permissions.sh"]
    CMD ["apache2-foreground"]

    bash:
    # set-permissions.sh
    #!/bin/bash
    chmod o+w /app/web/uploads
    chmod o+w /app/web/uploads/result
    exec "$@"

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

    ThunderCat
    @ThunderCat Куратор тега PHP
    {PHP, MySql, HTML, JS, CSS} developer
    1) Тело хтмл письма, как и любой подвид иксмл, должно начинаться с оперделяющих тегов, у вас же тупо табличка отправляется.
    2) Заниматься мастурбациейфигней с отправкой через mail() в 21 веке как минимум стыдно, как максимум чревато проблемами при отладке и смене функциональности, не говоря уже о том что отправка хтмл контента и приложений становится задачей со звездочкой.
    3) Все легко решается переходом на нормальную библиотеку отправки почты, пхпмэйлер/свифтмэйлер и их многочисленные аналоги.
    Ответ написан
    3 комментария
  • Почему не записывает в бд?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Не очень понятно, что имеется в виду под "подключением", но будем считать что речь про добавление данных в БД. Это может присходить по трем причинам:
    1. Код добавления вообще не вызывался.
    2. При добавлении произошла ошибка.
    3. Данные добавились в одну базу, а результат смотрим в другой.

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

    <?php
    # Настройка ошибок
    # Для локального сервера
    ini_set('display_errors', 1);
    # Всегда
    error_reporting(E_ALL);
    mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);

    Добавив этот код, надо запустить свой скрипт еще раз и смотреть, ошибки, которые он выведет.

    Плюс обязательно прочесть статью https://habr.com/ru/articles/662523/
    Ответ написан
    5 комментариев
  • Как правильно подходить к возвращаемым типам функциях php?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    Хорошие вопросы.
    Разумеется, увеличивать количество запросов к БД ради красивой типизации - это абсолютно не вариант.

    Как можно увидеть, в приведенной цитате написано не однозначно, а "скорее всего".
    И поэтому надо конечно стараться, чтобы функция возвращала какое-то одно значение, но не делать этого любой ценой. Поэтому getUserDataFromDatabase вполне может возвращать array|false, а getUserIdFromDatabase - int|false, хотя я бы с ней не заморочивался, первой вполне достаточно. А userIsPresentInDb вообще не нужна, вместо неё можно использовать одну их предыдущих.

    Другое дело, что нужного результата можно добиться и другим способом.
    Ведь вполне можно вернуть пустой массив. И таким образом формально соблюсти типизацию.

    return $result ?: []; // дёшево и сердито

    Но это будет всё равно не очень красиво. В одной стороны - да, для проверки, вернула ли функция непустое значение, такой вариант вполне сгодится. Но с другой стороны все равно как-то неаккуратненько. Ведь мы на самом деле ждём не абы какой массив, а вполне определённый, с конкретным набором полей. То есть, если эта функция вернет массив вида [0, 42, 100500], то это будет явно не то, что нам нужно, но при этом типизация и слова поперёк не скажет.

    Если думать от типизации, то функция getUserDataFromDatabase, возвращающая какой-то абстрактный массив - это нонсенс, бессмыслица. Эта функция должна возвращать юзера. Поэтому в идеале надо придумать способ указать, что функция возвращает не абстрактный, а конкретный массив определенного формата. Тем более, что такой способ как раз есть, ведь типизованный массив - это же объект! И для данного случая даже специальный паттерн есть - ValueObject (хотя в случае с пользователем лучше будет все-таки делать полноценный класс, содержащий не только данные, но и методы, например auth(), который сравнивает хэш пароля с введенным).

    Соответственно, в идеале функция должна возвращать объект, представляющий пользователя.

    И уже в этом объекте поле id может либо либо быть нулём, либо иметь какое-то положительное значение. Или даже объект может содержать отдельное свойство, заполнен/не заполнен.

    И вот в этом случае типизация заиграет совсем новыми красками, и будет использоваться на 100%
    function getUserFromDb( int $userId ) : UserObject {
            return $result ? UserObject::fillFromArray($result) : new UserObject();
    };
    $user = getUserFromDb();
    if (!$user->id) {
        // нинашли :'(
    }


    Но опять же, как пишет ниже Сергей delphinpro, зависит от задачи.
    И решив проблему правильной типизации значения, которое функция вернет, если нашла пользователя, можно вернуться к вопросу о том, что возвращать, если функция ничего не нашла. И в этом случае вполне подходящим вариантом будет вернуть null
    function getUserFromDb( int $userId ) : ?UserObject {
        return $result ? UserObject::fillFromArray($result) : null;
    };
    
    if ($user = getUserFromDb()) {
        // нашли :)
    }
    Ответ написан
    6 комментариев
  • На чем сделать самый простой сайт?

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

    @kot999
    Backend software engineer
    phpStorm + docker, в современном мире отпала необходимость в сборках (типа xampp или denver), все прекрасно заводится и переносится в docker, очень приближенно к production окружению
    Ответ написан
    3 комментария
  • Docker для проекта одиночки - стоит ли играть свеч и почему он лучше OpenServer'а?

    intro94
    @intro94
    PHP Backend Developer
    Ларадок выкиньте сразу. Оно не очень гибкое, имхо. Погуглите docker-compose и соберите свой конфиг — оно здорово облегчит вам жизнь.

    Лично я работаю с ларкой под докером онли. Неважно какая система, хоть линукс. Это очень удобный инструмент как минимум для разработки. Особенно когда проектов много и на разных версиях пхп и не только (хоть это и не по вас пока что), очень помогает не засорять систему.

    На проде лично я использую только натив, без докера. А во время разработки у себя локально — докер. Мои сотрудники в большинстве своём так же. Среди знакомых в других компаниях то же самое, правда у некоторых и на проде докер или кубер.
    Ответ написан
    2 комментария
  • Почему не работает редирект на предыдущую страницу?

    @AUser0
    Чем больше знаю, тем лучше понимаю, как мало знаю.
    В вашем PHP-скрипте после echo $url_lin; уже никакой header("Location: $url_lin"); не будет работать. Ну включите уже вывод ошибок PHP, что ли: error_reporting(E_ALL);.
    Ответ написан
    Комментировать