• Как убрать смещение страницы влево при появлении полосы прокрутки?

    Pongo
    @Pongo
    При помощи calc(100vw - 100%) можно вычислить ширину скроллбара (а если он не отображается, то будет 0). Идея: при помощи отрицательного margin-right увеличить ширину <html> на эту ширину. При этом появляется горизонтальная полоса прокрутки — ее скрываем.

    html {
      overflow-x: hidden;
      margin-right: calc(-1 * (100vw - 100%));
    }

    Пример. Нажатие кнопки "change min-height" скрывает\отображает скроллбар.
    Ответ написан
    10 комментариев
  • Где и как лучше прехватывать/обрабатывать исключения?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    Главная вещь, которую надо понимать про исключения, это то что они бывают двух основных видов.
    После этого вся обработка становится совершенно естественной и очевидной.

    - Error exceptions, или по простому говоря - ошибки. Обычные ошибки при выполнении программы. Обычно код бросает их сам. Решение "обрабатывать все ошибки через set_exception_handler" будет вполне логичным.
    - Business logic exceptions - это не ошибка в строгом понимании этого слова, а скорее нормальное поведение программы. Ситуация исключительная, но только для бизнес-логики. Их всегда кидает программист.

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

    - Error exceptions почти никогда не ловятся через try-catch, по крайней мере на месте. За исключением редких исключительных ситуаций обработка ошибок производится в единой точке, обработчике ошибок
    - Business logic exceptions всегда ловятся через try-catch

    Отсюда мы видим, что

    - //PDOException при коннекте (эммм... я понимаю что пример, но блин, new PDO в конструкторе репы, серьёзно?ладно, мы сейчас не об этом) - это однозначно ошибка
    - //PDOException в запросе - это тоже ошибка, тут два раза думать не надо
    - условно пустое имя. Ну вот здесь мы уже переходим в область бизнес-логики. Коду тут без разницы, пустое имя, или полное. Это важно нам - программисту, пользователю.

    Но тут есть один, блин, тонкий момент.
    Валидация, по сути, пытается разорваться между всеми слоями приложения.
    С одной стороны, это функция Сущности (которую ошибочно называют моделью) - проверять валидность своих данных.
    С другой - если нам надо донести результаты валидации до пользователя, то как быть с переводами? Тащить в модель переводчик, серьёзно? Ну ок, ладно, возвращаем ключи для перевода. Хотя тоже как-то...
    Но вот проверка емейла на уникальность. Её-то где делать?
    В Сущности? И тащить в нее соединение с БД?
    На уровне БД? А где ловить тогда исключение? В сервисе? И ломиться через несколько уровней абстракции к сырому PDOException? Не вариант.
    Или, к примеру, для модели естественно проверять каждое поле отдельно, и кидать исключение. А для пользовательского интерфейса это неприемлемо - надо выдавать все ошибки валидации скопом, а не скармливать по одной.
    Вопросы...

    Но "где валидировать данные" - это отдельная тема, которая не относится напрямую к вопросу "где ловить ошибки".

    В данном случае я предлагаю оставить Сущность Юзер без валидации, а всю валидацию делать в сервисе.

    Хотя опять же - в современных фреймворках валидацию (Не будем показывать пальцем, но это был Ларавель) вообще делают еще до запуска контроллера, в миддлвари. Это кстати спорное решение, которое нарушает целостность модели. Если мы обращаемся к модели через другую точку входа, не контроллер, а, к примеру, создаем юзера через командную строку, то нам нужна точно такая же валидация. Запускать команды через мидлварь? В сущности, это мысль... Но всё равно, мы в итоге бизнес-логику размазываем между моделью и точками входа в неё, а это костыль.
    И при всём при этом оставлять Сущность Юзер совсем без валидации тоже как-то не комильфо... А если оставлять - то получится по сути дублирование кода.
    Вопросы, вопросы...

    Но вернемся к нашим баранам, в смысле юзерам.

    Начнем с того, что проверка имени на равенство пустой строке или нулю - это какой-то детский лепет (и кстати, почему ноль нельзя? вот у Маска ребеночка зовут X Æ A-12 - почему у кого-то не может быть имя "0.0"?).

    Отдельно побурчу насчет empty. Вообще, это один из самых сложных операторов, на нем спотыкаются все поголовно. В частности,
    function f($name){
        if (empty($name))...

    - это бессмыслица. Звучит, в переводе на русский, немного шизофренически: "пусть у нас будет переменная $name. Если у нас нет переменной $name...". Ну как нет, если мы только что ее в функцию передали?
    empty() проверяет переменную на существование И "пустоту". И в данном случае первая проверка будет бессмысленной. Никогда не надо писать бессмысленный код.
    Поэтому логичнее будет написать просто if(!$name). Хотя по нынешним временам это тоже говнокод. Что мы имеем здесь в виду? Имя не может быть пустой строкой? Пустым массивом? Нулём? null? false? А true или заполненный массив - это, получается, хорошее, годное имя?
    Лучше все-таки четче определять свои претензии. К примеру, проверять длину строки.

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

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

    class ValidationError extends Exception{ ... };
     
    class User
    {
        private string $name;
    
        public function __construct(string $name)
        {
            $this->name = $name;
        }
    }
    
    class UserRepository
    {
        public function __construct(PDO $pdo)
        {
            $this->builder = $pdo;
        }
        public function add(User $user): User
        {
            $saved = $this->builder->query('INSERT INTO users (name) VALUES ("user")'); //PDOException
        }
    }
    
    class UserSerivce
    {
        private UserRepository $repository;
        private Validator $validator;
    
        public function new(array $data): User
        {
            $rules = [...] ;
            $errors = $this->validator->validate($data, $rules);
            if ($errors) {
                throw new ValidationException("", $errors);
            }
            $user = new User($data['name']); // в принципе, сучность может здесь бросить своё ValidationException
            return $this->repository->add($user);
        }
    }
    
    class UserController
    {
        private UserSerivce $service;
    
        public function store(array $data)
        {
            try {
                $user = $this->service->new($data);
            catch (ValidationError $e) {
                // рассказываем юзеру что он дурак
            }
            return redirect()->to('/' . $user->id);
        }
    }


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

    Как можно заметить, вот весь этот длинный и путанный текст посвящен исключительно ошибкам бизнес-логики.
    Поскольку с ошибками кода всё куда проще - единый хендлер тупо их обрабатывает в одном месте, как описано в статье по ссылке @Spartak-2205
    За исключением редких случаев, когда они ловятся по месту. Когда ошибка некритичная, или есть сценарий обработки - например, попробовать выполнить то же действие еще раз.
    Ответ написан
    3 комментария
  • Почему Vue рендерит компонент вне родительского блока?

    0xD34F
    @0xD34F Куратор тега Vue.js
    Особенности парсинга DOM-шаблона:

    Некоторые HTML-элементы, такие как <ul>, <ol>, <table> и <select> имеют ограничения на то, какие элементы могут отображаться внутри них, или например элементы, такие как <li>, <tr> и <option> могут появляться только внутри других определённых элементов.

    Это приведёт к проблемам при использовании компонентов с элементами, которые имеют такие ограничения. Например:

    <table>
      <blog-post-row></blog-post-row>
    </table>

    Пользовательский компонент <blog-post-row> будет поднят выше, так как считается недопустимым содержимым, вызывая ошибки в итоговой отрисовке. К счастью, специальный атрибут is предоставляет решение этой проблемы:

    <table>
      <tr is="blog-post-row"></tr>
    </table>
    Ответ написан
    Комментировать
  • Почему не загружаются стили для моб. устройств и в device mode?

    alsopub
    @alsopub
    budcentre.com.ua/design/bud_1_2/css/style.css - 404 файл не найден.
    И остальные стили, js, картинки с похожим префиксом тоже 404.
    Видимо у вас для мобильных и десктопных браузеров прописаны разные стили и скрипты.
    Ответ написан
    1 комментарий