• Почему у некоторых сайтов удается получить информацию об SSL, а у некоторых - нет? Как это исправить?

    gzhegow
    @gzhegow
    aka "ОбнимиБизнесмена"

    SSL {#3
    +domain: "beton-gatchina.ru"
    +validFrom: "2022-Jul-14"
    +validTo: "2023-Aug-15"
    +issuer: "GlobalSign nv-sa"
    +validity: "372 days"
    +validitytot: "396 days"
    +crtValRemaining: 1692115953
    }


    Вот так нада:
    <?php
    $get = stream_context_create([
        "ssl" => [
            'capture_peer_cert'       => true,
            'capture_peer_cert_chain' => true,
            'verify_peer'             => false,
        ],
    ]);


    А в скрипте вот так:
    <?php
    $get = stream_context_create([
        "ssl" => [
            'capture_peer_cert'       => true,
            // 'capture_peer_cert_chain' => true,
            // 'verify_peer'             => false,
        ],
    ]);


    Это настройки ext-openssl, которая скомпилена под винду с SSL настройками от линукса, она сертификаты ищет /usr/local/ssl/, а в винде нет таких папок. Настроить как-то можно, а нужно?

    dd(openssl_get_cert_locations());

    array:8 [
      "default_cert_file" => "C:\usr\local\ssl/cert.pem"
      "default_cert_file_env" => "SSL_CERT_FILE"
      "default_cert_dir" => "C:\usr\local\ssl/certs"
      "default_cert_dir_env" => "SSL_CERT_DIR"
      "default_private_dir" => "C:\usr\local\ssl/private"
      "default_default_cert_area" => "C:\usr\local\ssl"
      "ini_cafile" => "d:/openserver/userdata/config/cacert.pem"
      "ini_capath" => ""
    ]


    А пока просто вырубаем verify_peer.
    Ответ написан
    3 комментария
  • Как реализовать алгоритм вывода дробной части числа в двоичной системе счисления на языке си?

    gzhegow
    @gzhegow
    aka "ОбнимиБизнесмена"
    На Си не подскажу, но ты без труда перепишешь код ниже.

    "mb_{что-то}" в пхп - работа с мультибайтовыми строками, UTF-8.
    "bc{что-то}" в пхп - работа с числами как со строками без float потерь

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

    Тесты:

    <?php
    
    $res = _base_convert_floor(100, '0ABCDEFGHIJKLMNOPQRSTUVWXYZ', '01');
    $res2 = _base_convert_floor($res, '01', '0ABCDEFGHIJKLMNOPQRSTUVWXYZ', 0);
    var_dump($res); // string(1) "D"
    var_dump($res2); // string(3) "100"
    
    $res = _base_convert_frac('.75', '01', '0123456789');
    $res2 = _base_convert_frac($res, '0123456789', '01');
    var_dump($res); // string(2) ".11"
    var_dump($res2); // string(2) ".75"
    
    $res = _base_convert('-10.75', '01', '0123456789');
    $res2 = _base_convert($res, '0123456789', '01');
    var_dump($res); // string(7) "-1010.11"
    var_dump($res2); // string(5) "-10.75"
    
    $res = _base_convert_floor('КУКУЁПТА', '0123456789', 'АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ');
    $res2 = _base_convert_floor($res, 'АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ', '0123456789');
    var_dump($res); // string(1) "495086673543"
    var_dump($res2); // string(1) "КУКУЁПТА"
    
    // @gzhegow > бонус, колонка "как в экселе"
    $res = _base_convert_floor(27, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', '0123456789', -1);
    $res2 = _base_convert_floor($res, '0123456789', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 0, -1);
    var_dump($res); // string(2) "AA"
    var_dump($res2); // string(2) "27"


    Исходник:

    <?php
    
    function _base_convert_floor($floor,
        string $baseCharsTo = null, string $baseCharsFrom = '0123456789',
        int $baseShiftTo = 0, int $baseShiftFrom = 0
    ) : string
    {
        $floor = strval($floor);
    
        $baseTo = mb_strlen($baseCharsTo);
        $baseFrom = mb_strlen($baseCharsFrom);
    
        if (! $len = mb_strlen($floor)) return '';
        if ($baseTo < 2) throw new \InvalidArgumentException('Conversion assume `baseCharsTo` to be at least 2 letters: ' . $baseCharsTo);
        if ($baseFrom < 2) throw new \InvalidArgumentException('Conversion assume `baseCharsFrom` to be at least 2 letters: ' . $baseCharsFrom);
    
        $baseCharsFromIndex = array_flip(mb_str_split($baseCharsFrom));
    
        for ( $i = 0; $i < $len; $i++ ) {
            if (! isset($baseCharsFromIndex[ mb_substr($floor, $i, 1) ])) {
                throw new \InvalidArgumentException('The `floor` contains char outside `baseCharsFrom`: ' . $floor[ $i ]);
            }
        }
    
        $baseChars10 = '0123456789';
    
        if ($baseCharsFrom === $baseCharsTo) {
            return $floor;
    
        } elseif ($baseCharsFrom === $baseChars10) {
            $result = [];
    
            $div = $floor;
            if (0 > bccomp(bcadd($div, $baseShiftTo, 0), 0, 0)) {
                throw new \RuntimeException('Unable to convert cause of `baseShiftTo`: ' . $div);
            }
    
            do {
                $div = bcadd($div, $baseShiftTo, 0);
    
                $mod = bcmod($div, $baseTo, 0);
                $div = bcdiv($div, $baseTo, 0);
    
                $result[] = mb_substr($baseCharsTo, (int) $mod, 1);
            } while ( bccomp($div, 0, 1) );
    
            $result = implode('', array_reverse($result));
    
        } elseif ($baseCharsTo === $baseChars10) {
            $result = '0';
    
            for ( $i = 1; $i <= $len; $i++ ) {
                $idx = $baseCharsFromIndex[ mb_substr($floor, $i - 1, 1) ];
                $idx = bcsub($idx, $baseShiftFrom, 0);
    
                $pow = bcpow($baseFrom, $len - $i);
                $sum = bcmul($idx, $pow, 0);
    
                $result = bcadd($result, $sum, 0);
            }
    
        } else {
            $result = $floor;
            $result = _base_convert_floor($result, $baseChars10, $baseCharsFrom, 0, $baseShiftFrom);
            $result = _base_convert_floor($result, $baseCharsTo, $baseChars10, $baseShiftTo, 0);
        }
    
        return $result;
    }
    
    function _base_convert_frac(string $frac,
        string $baseCharsTo = null, string $baseCharsFrom = '0123456789',
        int $scale = null
    ) : string
    {
        $frac = ltrim($frac, '.');
    
        $baseTo = mb_strlen($baseCharsTo);
        $baseFrom = mb_strlen($baseCharsFrom);
    
        if (! $len = mb_strlen($frac)) return '';
        if ($baseTo < 2) throw new \InvalidArgumentException('Conversion assume `baseCharsTo` to be at least 2 letters: ' . $baseCharsTo);
        if ($baseFrom < 2) throw new \InvalidArgumentException('Conversion assume `baseCharsFrom` to be at least 2 letters: ' . $baseCharsFrom);
    
        $baseCharsFromIndex = array_flip(mb_str_split($baseCharsFrom));
    
        for ( $i = 0; $i < $len; $i++ ) {
            if (! isset($baseCharsFromIndex[ mb_substr($frac, $i, 1) ])) {
                throw new \InvalidArgumentException('The `frac` contains char outside `baseCharsFrom`: ' . $frac[ $i ]);
            }
        }
    
        $scale = $scale ?? $len;
        $scale = max($scale, 0);
    
        $baseChars10 = '0123456789';
    
        if ($baseCharsFrom === $baseCharsTo) {
            return $frac;
    
        } elseif ($baseCharsFrom === $baseChars10) {
            $result = [];
    
            $mul = bcadd('0.' . $frac, 0, $scale);
    
            $limit = $scale;
            while ( $limit-- ) {
                $mul = bcmul($mul, $baseTo, $scale);
                $floor = bcadd($mul, 0, 0);
    
                $mul = bcsub($mul, $floor, $scale);
    
                $result[] = mb_substr($baseCharsTo, (int) $floor, 1);
    
                if (0 === bccomp($mul, 0, $scale)) break;
            }
    
            $result = implode('', $result);
    
        } elseif ($baseCharsTo === $baseChars10) {
            $result = '0';
    
            for ( $i = 1; $i <= $len; $i++ ) {
                $idx = $baseCharsFromIndex[ mb_substr($frac, $i - 1, 1) ];
    
                $pow = bcpow($baseFrom, -$i, $scale);
                $sum = bcmul($idx, $pow, $scale);
    
                $result = bcadd($result, $sum, $scale);
            }
    
            $result = explode('.', $result, 2)[ 1 ] ?? '0';
    
        } else {
            $result = $frac;
            $result = _base_convert_frac($result, $baseChars10, $baseCharsFrom);
            $result = _base_convert_frac($result, $baseCharsTo, $baseChars10);
        }
    
        return '.' . $result;
    }
    
    function _base_convert($num,
        string $baseCharsTo = null, string $baseCharsFrom = '0123456789',
        int $scale = null,
        int $baseShiftTo = 0, int $baseShiftFrom = 0
    )
    {
        $isNegative = 0 === mb_strpos($num, '-');
    
        $numAbs = ltrim($num, '-');
        [ $numFloor, $numFrac ] = explode('.', $numAbs, 2) + [ '0', '' ];
    
        $scale = $scale ?? mb_strlen($numFrac);
    
        $result = [];
        if (mb_strlen($numFloor)) $result[] = _base_convert_floor($numFloor, $baseCharsTo, $baseCharsFrom, $baseShiftTo, $baseShiftFrom);
        if (mb_strlen($numFrac)) $result[] = _base_convert_frac($numFrac, $baseCharsTo, $baseCharsFrom, $scale);
    
        $result = implode('', $result);
    
        if ($isNegative) {
            $result = '-' . $result;
        }
    
        return $result;
    }
    Ответ написан
    Комментировать
  • Как изменить текст кнопки?

    gzhegow
    @gzhegow
    aka "ОбнимиБизнесмена"
    public function __construct($site_id, $text)

    Читать как "на вход пришло site_id и текст". Откуда пришло? Щелкаем в phpstorm правой кнопкой на __construct, там "Find usages" и смотрим, где создается. Туда переходим. Повторяем пока не найдешь.
    Ответ написан
  • В базу данных не отправляются данные которые введены в форме, что делать?

    gzhegow
    @gzhegow
    aka "ОбнимиБизнесмена"
    У него цикла не видно.
    Я думаю его проблема в том, что он не сделал id поле auto_increment, и спрятал ошибки mysql. В итоге ничего не пишется, хотя там ошибка что "айди уже есть". (Судя по тому что он говорит появляется запись с id = 0, если поле auto_increment - 0 невозможно)
    Ответ написан
  • Каково нормальное значение memory_limit (PHP как модуля Apache) для современных скриптов?

    gzhegow
    @gzhegow
    aka "ОбнимиБизнесмена"
    Мои веб-сайты (index.php) вкладываются в 32мегабайт.
    Пережималки и отдавалки картинок в 16мегабайт (glide.php).
    Консольные парсеры и работающие с "большими" данными - в 256мб (console.php).
    Ответ написан
    Комментировать
  • Как лучше организовать замену текста в строке?

    gzhegow
    @gzhegow
    aka "ОбнимиБизнесмена"
    <?php
    
    $words = [
      [ 'ABCDEF', 'textA' ], // 1
      [ 'GHJKL', 'textB' ], // 2
      [ 'MNOP', 'textC' ], // 3
      [ 'ABCDEF', 'textD' ], // 4
    ];
    
    $result = $str = 'Текст, ещё текст ABCDEF ещё текст текст GHJKL -- много текста MNOP и напоследок снова ABCDEF конец';
    
    // 4 -> 3 -> 2 -> 1 (array_pop)
    while ([ $word, $replacement ] = array_pop($words)) {
      // @gzhegow > do you need 'mb_' ? is it UTF-8 text?
      if (false !== ($pos = mb_strrpos($result, $word))) { // ищем номер первой буквы совпадения с конца строки в начало
        $result = ''
          . mb_substr($result, 0, $pos) // до первой буквы
          . $replacement // замена
          . mb_substr($result, $pos + mb_strlen($word)) // после последней буквы
        ;
      }
    }
    
    var_dump($result);
    
    // string(155) "Текст, ещё текст textA ещё текст текст textB -- много текста textC и напоследок снова textD конец"
    Ответ написан
    Комментировать
  • Как получить на PHP информацию о сервере Майнкрафт?

    gzhegow
    @gzhegow
    aka "ОбнимиБизнесмена"
    Сначала Wireshark и слушать соединение.
    Зайти в игру.
    Cворачиваем, смотрим Wireshark пакеты, которые игра по интернету от нас отправила туда.
    Копируем данные.
    Делаем скрипт с сокетом. // fsock_open // listen
    Отсылаем копию. // send
    Получаем ответ. // while (listen)

    Я так в GTA5 RP делал, чтобы персонаж сам копал рудники, пока я в детском садике.
    Ответ написан
    Комментировать
  • Есть ли бесплатный хостинг для скриптов?

    gzhegow
    @gzhegow
    aka "ОбнимиБизнесмена"
    Либо ваш компьютер с настроенным No-IP DUC и вебсервером на порту (но есть провайдеры которые любят деньги так же как и вы и блокируют такой расклад), либо если скрипт не требует php - можно даже на github-pages заливать.

    А вообще для "демонстрации" работы существуют различные js-fiddle, где можно посмотреть результат скрипта после отработки.
    Ответ написан
    Комментировать
  • Как отсортировать массив php внутри js кода?

    gzhegow
    @gzhegow
    aka "ОбнимиБизнесмена"
    AUser0, верно

    v_eropov,

    Вы пытаетесь выдать с сервера сразу HTML, и поэтому у вас проблемы получаются.
    Если уж решили делать через асинхронный (ajax) запрос - то да, выдавайте в json, кладите его в переменную, сортируйте, и рисуйте верстку уже на javascript.

    И да, вам придется строить все дивы из яваскрипта и это не короткий код. Кто-то предпочитает это делать, используя js фреймворки, типа vue/react, я предпочитаю изначально из php выдать (так было еще когда не было vue/react, а был только handlebars)
    <template id="mytemplate">
      <div>
        <div>{{var1}}</div>
        <div>{{var2}}</div>
      </div>
    </template>


    Потом селектором этот элемент найти, и копировать его столько-то раз, делая

    html.replace('{{var1}}', data.var1);
    Ответ написан
    1 комментарий
  • Как правильно фильтровать значения json с помощью whereJsonContains в laravel?

    gzhegow
    @gzhegow
    aka "ОбнимиБизнесмена"
    Для безопасности твоей головушки сообщу - если оно выглядит "как-то сложновато", то лучше не надо, найди способ обойтись. Даже если ты сжав зубы добъешь фильтрацию по JSON-у в РЕЛЯЦИОННОЙ (созданной чтобы всё, что ищется было в РАЗНЫХ полях) - это потом кто-то не сможет прочитать, поредактировать и вообще исправить если захочет изменить.

    Всё что ищешь положи рядом в поля (создай колонку, пробежись циклом) и пользуйся обычными селектами. А json храни как будто это не знаю... картинка. Просто куча данных которые как положил, так и достал.
    Ответ написан
    7 комментариев
  • Как отправить заголовки в отложенной задаче?

    gzhegow
    @gzhegow
    aka "ОбнимиБизнесмена"
    Используйте пожалуйста ext-curl для пхп, библиотеки написанные разработчиками фреймворков тестируются в ограниченном числе ситуаций, скорее всего ваша не была протестирована. Пока они исправят - можно пару месяцев подождать, но "за чей счет будет банкет". То есть в правильном обществе так и происходит - дается разработчику намек, что надо исправить, он - исправляет, вы ждете. В этом обществе если вы ждете - вы теряете работу. А он ничего. Используйте то, что простое, возможно требующее больше кода, но по крайней мере оно работает.

    Чем меньше "надежных" газзлов и хттп фасадов, работающих так, как запланировали, но вы не знаете кто и когда - тем спокойнее будет жить.
    Ответ написан
    Комментировать
  • Как средствами PHP логировать ссылки входа на сайт со всеми UTM метками?

    gzhegow
    @gzhegow
    aka "ОбнимиБизнесмена"
    Прошу не делать глупостей, и использовать какую-то систему статистики для подсчета.
    Запись каждого запроса на ПХП приведет к большим проблемам, чем метрика.

    Чтобы их минимизировать - как минимум придется подключать редис, потому что скорость записи в БД или файл недостаточна даже при потоке клиентов в 1000 человек. Говорю потому что как-то имел дело с сайтом, который просто считает счетчик просмотров без аналитики и метрики.

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

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

    gzhegow
    @gzhegow
    aka "ОбнимиБизнесмена"
    О, моя тема.

    Храним каждое дерево в двух массивах.

    // нужен чтобы обходить и выводить... и удалять. Когда ты в много потоков работаешь парсером например этот массив может быть бешенных размеров, а для сохранения тебе нужно только одна ветка. Вот с помощью этого можно вычистить лишнее, оставив только одну ветку.
    
    $tree = [
      // parent_id => children
      '' => [ 1, 2, 3 ],
      1 => [ 4, 5 ],
      2 => [ 6 ]
    ];
    
    // нужен чтоб сохранять чилды в разных функциях и потом находить "прошлый"
    $parents = [
      1 => '',
      2 => '',
      3 => '',
      4 => 1,
      5 => 1,
      6 => 2
    ];


    Это дело обходится либо рекурсией (что медленнее), либо стеком (что быстрее).

    $stack = [ [ null, 0 ] ]; // null при проверке ключа станет пустой строкой, "рутом" дерева
    while ([ $parent, $level ] = array_pop($stack)) {
      // выводим текущий элемент и минусами отодвигаем от левого края или... хз в твой массив добавляем например
      echo str_repeat('--', $level) . ' ' . $parent . PHP_EOL;
    
      $children = $tree[ $parent ] ?? [];
      
      end($children); // да, да, в обратном порядке закидываем
      while (null !== key($children)) {
        $stack[] = [ current($children), $level + 1 ];
        prev($children);
      }
    }


    Этот код обходит дерево в глубину, то есть элементы в стек будут попадать таким образом null-1-2-3-4-5-6, хотя если бы ты обходил это форичем то они бы попали в виде null-1-4-5-2-6-3 (сначала бы вывелись все первые уровни, потом все вторые, потом третьи)

    То есть строить "вложенное" дерево никогда не нужно. Всегда можно обойтись двумя уровнями "родитель-потомок". Существует МНОГО фронтендеров, уверенных что деревья должны быть вложенные. Книжку им в руки.

    Вложенные деревья нужны во время самой программы когда ты один обьект ссылаешь на другой по цепочке, потому что тебе лень строить индекс для работы с этим и обьекты прям генерируются. Хотя построить такой массив не знаю что может быть проще.
    Ответ написан
    Комментировать
  • Какие подводные камни есть в том, чтобы просто подавить вывод "Trying to get property 'someProp' of non-object" через error_reporting?

    gzhegow
    @gzhegow
    aka "ОбнимиБизнесмена"
    Подводные камни "отсутствует parent, нельзя сохранить child, полскрипта не сработало, половина сохранилась, теперь надо руками вычищать что корявое, а что нет"

    =====

    В новой пхп именно из этой проблемы (а точнее стонах по поводу неё) ввели оператор "?->" который вернет NULL если нету, но это про "сразу писать правильно" - а так тоже не бывает. Чаще всего надо "разобраться почему не работает", а не весь старый код перелопатить.

    До этого ещё втиралось что NullObject Pattern нужно использовать - то есть любой объект может иметь __get()/__set() и если поля нет - вернет Null, или например если в свойстве должен быть обьект - то когда там NULL туда закидывается обьект с пустыми свойствами, чтоб все работало так же просто всегда NULL отдавало. Кое-кто взял на вооружение - например NullCache() который работает как кеш, но ничего не делает, хотя возвращает всё так же, как будто работает.

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

    К примеру обьект Car может не иметь поля "fifth-wheel".
    Делаем так (new CarDecorator(new Car()))->fifth_wheel где уже есть поле или она умеет возвращать NULL если поля нет.
    Ответ написан
    4 комментария
  • Как организовать получение данных из общего объекта в файлах seeder и factory?

    gzhegow
    @gzhegow
    aka "ОбнимиБизнесмена"
    Я константы в модели использую.

    Class Car {
      const ENUM_FUEL_PETROL = 'petrol';
      const ENUM_FUEL_DIESEL = 'diesel';
      const THE_ENUM_FUEL_LIST = [
        self::ENUM_FUEL_PETROL => true,
        self::ENUM_FUEL_DIESEL => true,
      ];
    }


    Но там уже Enum-ы ввели.

    Но если список стран или валют, которых много и черт пойми откуда берется - то просто сидер после наката миграций запускать.
    Ответ написан
    Комментировать
  • Ошибка CORS в yii2, как исправить?

    gzhegow
    @gzhegow
    aka "ОбнимиБизнесмена"
    Ошибки CORS лучше исправлять вокруг фреймворка чем внутри него. К сожалению, я не подскажу как исправить её конкретно в Yii, но ошибка Cors комплексная и заключается чаще всего в том, что браузер увидев код ошибки не отображает запрос в консоли разработчика (Firefox кстати - отображает). То есть правильно - это убедится что Response выдаваемый из фреймворка даже в случае ошибки отсылает заголовки типа cross-origin, а браузер в свою очередь даже при ошибке делает resolve() вместо reject() и позволяет вам посмотреть текст ошибки.
    Ответ написан
    Комментировать
  • Как правильно выстраивать архитектуру метода контроллера на laravel?

    gzhegow
    @gzhegow
    aka "ОбнимиБизнесмена"
    Знакомая боль давняя.
    Принцип следующий - 1) исходные данные 2) превращение в обьект, 3) проверка (валидация) обьекта, 4) передача обьекта в какое-то действие, 5) проверка результата (если нужна) и 6) генерация респонса.

    Исходные данные. Смотрим что за фрейм. Лара. Умеет в инжекцию в метод контроллера и биндинг обьектов, если написать правильно. Можно сразу на вход писать MyActionRequest (сделать как в документации), в итоге первой строкой будет $myActionRequest->validate(), которая еще и выкинет 422 если что-то не так.

    В чем минус ларавельного реквеста? Он представляет собой как бы ВЕСЬ реквест. Это тоже самое что передавать $_GET по программе, что немного странно.

    Рекомендуется сделать свой обьект ДТО. Это по сути твой же реквест, только в нем поля все заранее описаны, голый класс без методов - одни свойства. После валидации ты свои данные из GET/POST/LaravelRequest ручками втыкаешь в поля ДТО и этот заполненный ДТО можешь дальше кидать как "точно проверенная пачка данных" и не боятся каждый раз "а что если что-то не так" - оно точно так, потому что ты уже проверял.

    Попадать в какой-то другой класс ДТО может целиком если это кусок бизнес-части программы или по одному полю / массиву полей если это какой-то кусок ядра или глобалки. Пример ядро - класс Money, который переводит там валюты знач и позволяет их переключать. Туда ваш MyActionDTO будет странно кидать, а вот string $money или PHPMoney/Money- пжалста. А вот в обьект например MyCatalog кинуть MyActionDto уже не так уже и плохо.

    Вот это ваше действие может быть просто SQL запросом. Category::query()->find() это тоже действие, а почему нет. Рекомендуют конечно запросы выбрасывать в "тип классов" (папка, такая же как "модели") репозиторий чтоб потом когда поломается чего не везде править а в одном месте, но тут тоже, пока помните, что где можно не париться, и потом - увлечетесь обобщением поймаете прикол когда не понятно какую половину запроса в контроллер, а какую - в репозиторий. Стоит помнить что мы пишем задачу под задание, задание представляет собой контроллер, а остальной код ему помогает. Поэтому частности в экшон, похожести - в отдельный класс.

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

    Потом пошли в Handler.php написали отлов исключений в целом по программе и их запись куда-то, в базу, в кеш или на удаленный логгер-анализатор, чтобы везде не писать try catch а просто писать throw и знать что оно "хоть как-то но отрисуется" и куда надо запишется.

    public function destroy(Request $request, $id) // или MyDestroyRequest если юзер что-то еще передает
        {
            $request->validate(); // оно под капотом ещё и авторизацию проверит и 422 само выбросит
    
            // ... верно тут можно проверять политику, но в принципе если реквест наследовать то в ларе помоему их можно и в реквест код перенести и первый метод еще и это сделает
          
            $dto = new MyDestroyDto($request->valid()); // там внутри пишем что куда, хотя можно и здесь
    
            $myDomainService = new MyDomainService(); // или new MyCoreService();
            $status = $myDomainService->doSomething($dto); // или $result = $myCoreService->convert($dto->money);
    
            if ($status === 'ok') return $this->jsonDone('@api.msg.ok_message', 200); // вот метод jsonDone в базовом (абстрактном*) контроллере или, например, в трейте, напиши
            return $this->jsonFail('@api.err.error_message', 500); // собаки в тексте для наглядности, трехуровневый ключ перевода из файла lang, по собаке просто можно определить текст уже проходил через переводчик или нет. три уровня нужны, чтобы когда много переводов скапливается их можно было подключать частями. Первый уровень - где подключать (api, catalog, social), второй - что (msg, err, label, placeholder, title, h1)
        }
    Ответ написан
    1 комментарий
  • Как избавиться от try-catch в контроллерах?

    gzhegow
    @gzhegow
    aka "ОбнимиБизнесмена"
    сделать мидлвар/слушатель, который вокруг контроллера, но просто его в коде не видно, он как правило часть фреймворка. или в index.php обернуть require что-то в try catch в одном единственном месте

    try catch это же "поставить следилку, закрыть следилку, что делать с отслеживаемым". Не пиши их и их не будет. Респонсы ифами генерируй "if (! $content) return new JsonResponse();". А то что вы хотите эксепшен выбросить как JSON это не про конкретный трайкетч, это про "обработка ошибок в рамке папки с контроллерами по имени api/v1/"
    Ответ написан
    4 комментария
  • Как указать дефолтную бд в ларавель?

    gzhegow
    @gzhegow
    aka "ОбнимиБизнесмена"
    В каждом современном фрейме в корне проекта лежат файлы .env, собственно из них функция env() и сосет. Эта штука удобно помогает сделать несколько .env файлов для локала, для теста и сервера и подключать один из них в зависимости от режима сайта. Ставишь там "staging" и он подрубает staging env.

    Конфиги нужны для тех вещей, что не указаны в .env, каких-то узких настроек которые не меняются от "хостинга к хостингу"
    Ответ написан
    Комментировать
  • Как сделать так, чтобы выводилось не id, а url (ЧПУ)?

    gzhegow
    @gzhegow
    aka "ОбнимиБизнесмена"
    RewriteEngine on
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^ index.php


    <?php 
    // index.php
    var_dump($_SERVER['REQUEST_URI']); // do some, explode, implode, select by `slug`, if ($selected) then require file.php;
    Ответ написан
    Комментировать