Ответы пользователя по тегу PHP
  • Как отсортировать массив по дате в формате от и до?

    gzhegow
    @gzhegow
    aka "ОбнимиБизнесмена"
    Не понимаю, если хочешь просто по дате сортировать по убыванию, то функция

    $dates = [];
    for ($i = 0; $i < 10; $i++) {
        $dates[] = new DateTime('now +' . $i . 'days');
    }
    
    usort($dates,function ($a, $b) {
        return null
            ?? ( $b < $a ? -1 : null )
            ?? ( $b > $a ? 1 : null )
            ?? 0;
    });
    
    var_dump($dates);


    делает, что сказали.

    ====

    Если твоя задача сортировать массив по возрастанию РАЗНИЦЫ дат, то нужно так:

    $dates = [];
    for ($i = 0; $i < 10; $i++) {
        $dates[] = [
            new DateTime('now +' . $i . 'days'),
            new DateTime('now +' . $i+$i . 'days')
        ];
    }
    
    usort($dates,function ($a, $b) {
        $diffA = $a[1]->getTimestamp() - $a[0]->getTimestamp();
        $diffB = $b[1]->getTimestamp() - $b[0]->getTimestamp();
    	
        return null
            ?? ( $diffA < $diffB ? -1 : null )
            ?? ( $diffA > $diffB ? 1 : null )
            ?? 0;
    });
    
    var_dump($dates);


    Помнить, что на getTimestamp() влияет временная зона. То есть 2 часа по Гринвичу меньше чем 2 часа по Москве, это как бы понятно, просто здесь тоже это важно.

    ====

    Третий вариант, который "возможно" ты хотел получить здесь - как определить пересечение дат:

    # опционально, можно донастраивать с помощью знаков `<=` `>=`, чтоб получить "включая-исключая"
    # и оператора NOT, чтобы инвертировать.
    # можно играться с оператором OR вместо AND, но это уровень 2, тебе не надо
    # ещё есть кейз "вне моего промежутка", который можно получить AND двух имеющихся или NOT для "внутри промежутка"
    
    # дай промежутки, которые помещаются в мои рамки
    # '2022-01-02 00:00:00' < date_from < date_to < '2022-01-04 00:00:00'
    # |----------|
    #    |----|
    # AND `date_from` > '2022-01-02 00:00:00'
    # AND `date_to` < '2022-01-04 00:00:00'
    # вернуло бы [ '2022-01-03 00:00:00', '2022-01-03 00:00:00' ]
    
    # дай промежутки, которые пересекаются с моим только началом
    # '2022-01-02 00:00:00' < date_from < '2022-01-04 00:00:00' < date_to
    # |------|
    #     |------|
    # AND `date_from` > '2022-01-02 00:00:00'
    # AND `date_to` > '2022-01-04 00:00:00'
    # вернуло бы [ '2022-01-03 00:00:00', '2022-01-05 00:00:00' ]
    
    # дай промежутки, которые пересекаются с моим только концом
    # date_from < '2022-01-02 00:00:00' < date_to < '2022-01-04 00:00:00'
    #    |------|
    # |------|       
    # AND `date_from` < '2022-01-02 00:00:00'
    # AND `date_to` < '2022-01-04 00:00:00'
    # вернуло бы [ '2022-01-01 00:00:00', '2022-01-03 00:00:00' ]
    
    # дай промежутки, которые шире моих рамок (рамка внутри промежутка и потому пересечения нет, пересечение целиком)
    # date_from < '2022-01-02 00:00:00' < '2022-01-04 00:00:00' < date_to
    #    |----|
    # |----------|
    # AND `date_from` < '2022-01-02 00:00:00'
    # AND `date_to` > '2022-01-04 00:00:00'
    # вернуло бы [ '2022-01-01 00:00:00', '2022-01-05 00:00:00' ]


    Чаще всего задача звучит "найдите все пересечения сразу", чтобы убедится, что туда можно что-то еще добавить и оно не закосячит потом. Поэтому и начинают играться с OR чтобы не писать NOT ( AND / AND / AND / AND )

    Вот тут есть уровень 2 и 3 и тд.
    www.michurin.net/computer-science/boolean-logic.html
    Ответ написан
    1 комментарий
  • Почему не получаю Bearer токен?

    gzhegow
    @gzhegow
    aka "ОбнимиБизнесмена"
    Похоже, что CORS передают привет.

    Access-Control-Allow-Origin
    Access-Control-Allow-Headers
    Access-Control-Allow-Authorization

    Гуглим...

    А ещё некоторые хедеры могут быть схаваны фреймворком, а реквест такая штука, чтобы не копироваться очень любит переноситься из одного места (места, где пхп его парсит) в некий объект или класс фреймворка, исчезая оттуда, где был.

    ps. корсы проще всего тестировать в Firefox.
    Ответ написан
  • Как получить название устройства при get php?

    gzhegow
    @gzhegow
    aka "ОбнимиБизнесмена"
    Вы зачем-то отбрасываете идею "передать с фронта fingerprint и сохранить его в сессию".
    На клиенте доступ к устройству получить легче, чем гадать на сервере.
    Ответ написан
    Комментировать
  • Зачем задавать приватный модификатор доступа для свойств класса?

    gzhegow
    @gzhegow
    aka "ОбнимиБизнесмена"
    Я когда-то задал тот же самый вопрос и нашел на него ответ.

    Для начала "private/protected/public" это больше история про наследование, чем про "доступ" или про "капсуляцию". Тут просто эти три слова несколькой обязанностей выполняют.

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

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

    "защищенный" метод предполагает "внутренний функционал", который как правило работает с уже проверенными данными и выполняет некую работу, но что более важно - наследуется. То есть это "внутрянка которая является частью основной задачи класса" - настолько является, что если класс этот кто-то захочет поменять - вполне возможно, ему захочется поменять это действие но так, чтобы остальное то же работало. Разумеется стоит помнить о договоренностях разработчиков на уровне "ты нормальный, вообще?" - если класс возвращал квадрат, а после наследования начинает возвращать круг - кто-то может с этого потом изрядно удивиться. Про это принцип подстановки Лисков.

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

    Теперь про свойства.

    "Публичные" свойства как во всех языках нужны, чтобы просто к ним обращаться и вписывать туда значение. Плюсы как бы - обычная переменная, меньше кода писать. Минусы? Обьекты постоянны от функции к функции. Где-то на уровне 10м-20м кто-то всунет в этот обьект то, что ты бы не хотел там видеть и оно всунется, а ты потом офигеешь, что "а че, так можно было чтоли?" - да. То есть публичные свойства стоит использовать только в каких-то может одноразовых объектах, типа DTO/ValueObject паттерн, просто потому что от "защиты" там только число кода добавится, они просто как массивы только с именованными заранее полями. Удобно писать, редактор подсказки показывает. И все равно остается опасность того что выше написано, поэтому как бы предполагается что вот дто он такой, одноразовый, и пишут в него только в начале приложения, разбирая запрос на куски, запихнул что не надо - получай.

    "Защищенные/Приватные" свойства здесь выполняют почти ту же задачу, что и защищенные методы (про наследование). Дополнительная фишка - в защищенное свойство ты можешь методами написать КАК ИМЕННО ты кладешь туда данные или всобачить небольшую проверку. Не стоит увлекаться тысячей проверок - в коде утонешь, но проверку Типа - можно, почему нет. Раньше типизированных свойств не было, так это был вообще единственный способ убедится что в поле лежит нужного класса другой объект. Я вот раньше писал set()/get()/delete()/add()/put() и кучу всего пока не понял, что можно обобщить до двух set(?$items) и add($items), причем set() - вызовет add() и если туда null передать, то оно либо поставит по умолчанию либо очистит, то есть ещё и delete() выполняет когда нужно.

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

    Это не значит что есть норма "сколько", это значит что нужно понимать, что в свойствах большой обьем желательно не копить. Все поля имеющие "массив по-умолчанию" можно сделать методами, тогда вызов метода даст тебе данные в одной функции, а по завершению - их вычистит. А положить их в свойства и запомнить навсегда (это же удобно! а ещё быстро считывается!) - это печально.
    Ответ написан
    Комментировать
  • Как отправить multipart/form-data в Nyholm\Psr7?

    gzhegow
    @gzhegow
    aka "ОбнимиБизнесмена"
    Эм, вы что-то напутали.

    'multipart/form-data' - это формат запроса. Вы от клиента присылаете его на сервер.

    Отдавать 'multipart/form-data' это как просить сервер заполнить форму на компьютере пользователя.

    Там нет формы.

    То есть сам паттерн Psr7 это не про "сделай запрос куда-то". Это "разбери $_GET/$_POST/$_FILES" так, чтобы получились стандартные ServerRequestInterface с которыми потом работает приложение. То есть "создать на сервере multipart/form-data $request" будет что-то примерно ::createFromGlobals() без параметров, и оно само его создаст, если вы отправите на сервер форму.

    Создавать псевдо-реквест с мультипарт-формдата, не получив с клиента запрос с этим заголовком, может быть нужно было только самим разрабам библиотеки когда они её тестировали.

    Чтобы ваша задача стала реальностью её текст должен звучать примерно так: "Клиент с сайта отправляет слово `привет`, а я на сервере в этот момент подменяю слово на файл с именем `привет.txt` и делаю вид будто юзер отправил мне файл." Если вы хотите клиенту файл отдать - то это Content-Disposition: attachment, а не Content-Type: multipart/form-data.

    Если вы хотите отправить запрос - вам нужно использовать GuzzleHttp или curl, а не ServerRequestFactory, то есть Psr7 - это парсер входящего реквеста, а не генератор хттп запросов куда-то. Технически как-то можно их приравнять... но что получится вы уже видели.
    Ответ написан
    Комментировать
  • Как через jms/serializer десериализовать null?

    gzhegow
    @gzhegow
    aka "ОбнимиБизнесмена"
    Там два способа есть.

    Один - если перечитать документацию Symfony\Serializer (который расширяется уже нашим JMS) там есть настройка типа Allow Serialize Nulls что-то такое, когда-то искал. Есть еще парочка типа "предельный уровень вложенности" и тд.

    Но по мне симфонийский или другой сериалайзер из коробки такая себе игрушка. Обычно прошу полдня (а первый раз ушатал неделю) на его оборачивание в большое число обработчиков, ведь сериализация ИЗ json в данные должна проходить по имеющимся PhpDoc\TypedProperty, а сериализация обратно желательно по Yaml-файлам, которые вам легко редактировать и где легче задавать условия что выдавать и когда. Ну ларавелисты вот ресурсы плодят, чтобы указывать какие поля когда можно делать, а симфонисты Yaml файлы редактируют так легче.

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

    То есть к вопросу сериализации Null я бы подходил оч комплексно на тему создания MySerializer/MyDeserializer где проверял бы ифами "а мона или нуна".
    Ответ написан
    Комментировать
  • Почему simple_html_dom.php один сайт парсит, а другой нет?

    gzhegow
    @gzhegow
    aka "ОбнимиБизнесмена"
    d:\OpenServer>curl "https://www.maxidom.ru/catalog/smesiteli/filter/item_firm-is-505a006bf69e69c71d23b5ca06faa83d/apply/?repIDchanged=4&amount=100" -v
    
    *   Trying 95.213.244.197:443...
    * Connected to www.maxidom.ru (95.213.244.197) port 443 (#0)
    * schannel: disabled automatic use of client certificate
    * ALPN: offers http/1.1
    * ALPN: server accepted http/1.1
    > GET /catalog/smesiteli/filter/item_firm-is-505a006bf69e69c71d23b5ca06faa83d/apply/?repIDchanged=4&amount=100 HTTP/1.1
    > Host: www.maxidom.ru
    > User-Agent: curl/7.83.1
    > Accept: */*
    >
    * Mark bundle as not supporting multiuse
    < HTTP/1.1 302 Found
    < Server: nginx
    < Date: Mon, 15 Aug 2022 12:19:49 GMT
    < Content-Type: text/html; charset=UTF-8
    < Transfer-Encoding: chunked
    < Connection: keep-alive
    < X-Powered-By: PHP/7.1.33-44+0~20211119.61+debian10~1.gbp448fbe
    < P3P: policyref="/bitrix/p3p.xml", CP="NON DSP COR CUR ADM DEV PSA PSD OUR UNR BUS UNI COM NAV INT DEM STA"
    < X-Powered-CMS: Bitrix Site Manager (daa31dd015896c419c3750efb37325d9)
    < Set-Cookie: PHPSESSID=nWRt3aUxn56jtZd4ZrA1vkh81L5wtU3P; path=/; domain=maxidom.ru; HttpOnly
    < Expires: Thu, 19 Nov 1981 08:52:00 GMT
    < Cache-Control: no-store, no-cache, must-revalidate
    < Pragma: no-cache
    < Set-Cookie: MAXI_LOC_ID=4; expires=Wed, 14-Sep-2022 12:19:49 GMT; Max-Age=2592000; path=/
    < Set-Cookie: maxidom_SALE_UID=1945123973; expires=Thu, 10-Aug-2023 12:19:49 GMT; Max-Age=31104000; path=/; domain=maxidom.ru
    < Location: https://www.maxidom.ru/catalog/smesiteli/filter/item_firm-is-505a006bf69e69c71d23b5ca06faa83d/apply/index.php?amount=100
    <
    * Connection #0 to host www.maxidom.ru left intact


    У первого сайта - редирект стоит со старта.

    И хотя вы вроде поставили FOLLOW_LOCATION / true, но что-то пошло не так...

    Бывает, что надо заголовок юзерагента воткнуть, через него защиту делают максимально примитивную.
    Бывает, что нужно смотреть какие данные в Google Developer Console страница отсылает, чтобы получить в ответ верстку, там иногда верстка выдается только если user_auth_id требуется.
    Бывает, что там SSL и если не поставить SSL_VERIFY_PEER / false оно не загребает контент, т.е. пытается проверить подлинность и не может, т.к. на локале на винде сертификаты не настроены, а настраивать их ну немногие умеют, проще false поставить

    Много ситуаций.
    Ответ написан
    3 комментария
  • Как еще можно реализовать "внутреннее API" в веб-приложении, кроме как через ООП или HTTP?

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

    Добавлю, для пункта 2 мне существенно упростило это:
    https://qna.habr.com/q/655113#answer_1431141
    Ответ написан
    Комментировать
  • Почему не срабатывает регулярка?

    gzhegow
    @gzhegow
    aka "ОбнимиБизнесмена"
    пишите регулярки вот так

    preg_match('~' . preg_quote($text, '/') . '~u');
    // u - флажок для поддержки русского-арабского-китайского юникода


    Не все регулярки нужно писать так, но это позволяет меньше переживать за спецсимволы.

    Кроме того ваша задача предполагает парсинг html, лучше распакуйте simple_html_dom_1_9_1 и парсите им, он местами тащит то, что другие не тащат.
    Ответ написан
    6 комментариев
  • Как авторизовавшись на одном сайте в "сети сайтов", быть автоматически авторизованным и на других?

    gzhegow
    @gzhegow
    aka "ОбнимиБизнесмена"
    Два пути. Приложение может быть без сессии и с сессией.

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

    Если сессии нет - то есть такая штука JWT token и в ней есть audience/issued, который делает примерно то же самое (выдан для/выдан кем). Аудиенции это как раз сайты (точнее будет сказать - места), где этот токен будет приниматься, опять же - с общим сервером авторизации.

    JWT токен сделан для того, чтобы не хранить в БД все разрешения выданные всем юзерам, которых может быть за миллион. В базе хранятся только токены добавленные в черный список в силу того, что человек их сам обнулил сделав "logout" (выйди из системы) или "revoke" (переделав конкретный токен поновой, чтобы старый пока срок не кончится - не работал).

    Однако если вы захотите прям сделать как на гугле кнопку "разлогинится на всех устройствах" - то в базе будут хранится не сами токены, но их идентификаторы под каждое устройство. Тот самый last_logged_in, только для каждой мобилки в семье. С одной стороны это нивелирует преимущество "не хранить в базе каждого юзера", т.к. теперь в базе хранится не только каждый юзер, но и каждое его устройство, но останется преимущество, которое про то, что "если базу взломали, они получат только айдишники, а чтобы делать - нужен сам токен, которого там нет". Тогда можно будет нажать "офнуть всех" и все залпом добавятся в блэклист.
    Ответ написан
    Комментировать
  • Дают ли выигрыш ссылки на элементы массива и на поля объектов в PHP?

    gzhegow
    @gzhegow
    aka "ОбнимиБизнесмена"
    Имел опыт прохождения некоего теста, где обход какого-то там 100 тысяч вложенности массива должен был укладываться в какие-то миллисекунды. Долбался тогда долго, но помню что без ссылок не тащило. Там в итоге получился обход стеком или там очередью не помню уже, но смысл был в том, что вместо того, чтобы "добавлять в очередь" в определенном порядке старые значения менялись на новые избегая операции push()/unset() пытаясь на этом "сэкономить".

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

    У ссылок скорее другая полезная нагрузка.

    В пхп массив это не объект в каком-то смысле, а скаляр. При присваивании его он копируется, как строка.

    Бывает нужно получить по пути в массиве элемент, а потом поменять его, не соединяя нечто через $arr[ $a ][ $b ][ $c ], т.к. ваши $a,$b,$c представляют собой строку типа 'hello.foo.bar'. Вот тут удобно вернуть ссылку, воткнуть туда что-то новое, не занимаясь обходом снова и снова. Справедливости ради можно сделать:
    [ $a, $b, $c ] = explode('.', $varname);
    $arr[ $a ][ $b ][ $c ] = 1;

    Но если число уровней переменное - приехали

    Ещё ссылки неоценимо помогают с пхпшными замыканиями, которые как известно присваивают не скоуп функции их вызвавшей, а скоуп всего класса или вообще ничего. Передав через use(&$some) в него можно записывать изнутри замыкания, т.к. переменные окружающие внутри будут не видны.

    А еще при создании \Closure забыв указать static спереди этот обьект оказывается привязан к замыканию. И потом "совершенно случайно" кто-то вызывает вашу функцию в цикле, которая создает замыкания, та в свою очередь копирует туда обьект (вроде как привязывает ссылку! но внутренние массивы лежащие в protected $property так не думают, а стало быть клонирует), имеющий массив с войной-и-миром занимающий мегабайт, и откуда-то получается 100 мегабайт занятой памяти, потому как 100 колбэков было создано. То есть тут еще кое-что про сборщик мусора надо добавить, что к примеру он не может удалить из памяти обьекты ссылающиеся друг на друга и удалит их только когда наберется некое число их очень большое. Именно эта проблема там и играет. Что при клонировании объектов свойства содержащие скаляры - копируются. В этом свои плюсы, например не надо как JavaScript постоянно изобретать deepClone(), т.к. полезная нагрузка уже является копией, а конкретные обьекты можно перетыкать ручками, но чаще всего это сервисы и они общие для всех экземпляров. Но случайно можно там накопировать делов.

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

    gzhegow
    @gzhegow
    aka "ОбнимиБизнесмена"
    Мне что-то подсказывает, хотя я плоховато знаю теорию языка Си, что вы приравняли ссылку к указателю. В пхп к сожалению указателей нет. И при помощи $ref =& $this->func(); вы создаете переменную указывающую на эту ссылку, и потом можете её менять. Нельзя в пыхе "вернуть указатель".
    Ответ написан
  • Как убрать зависимость композера от версии?

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

    На сервере юзается тот который на локале отработал и lock свой записал и потому всегда нужный. А на локале оба есть.

    Точнее не так. У меня для каждой версии пхп есть композер 1 и 2 и ярлыки назвал composer8, composer73, composer74 и _composer8, _composer73, _composer74 - для версии композера 1.0 для совсем уж старых проектов
    Ответ написан
    Комментировать
  • Как посчитать количество совпадающих элементов в массиве?

    gzhegow
    @gzhegow
    aka "ОбнимиБизнесмена"
    $index = [];
    foreach ($items as $item) {
      $key = json_encode($item); // md5/crc32/spl_object_id/implode('.')/etc.
      $index[ $key ] = $index[ $key ] ?? 0;
      $index[ $key ]++;
    }
    var_dump($index); // { key => 1, key2 => 2, key3 => 1 }
    Ответ написан
    Комментировать
  • Как задать глобальные ограничения доступа к моделям при запросах?

    gzhegow
    @gzhegow
    aka "ОбнимиБизнесмена"
    Недавно делал похожую задачу, долго возился и в конце пришел к выводу, что если "все" или "большинство" имеет общую связь - то это две базы данных (разные заказчики, разные бд, устанавливаете отдельно, платят отдельно, бизнес очень любит такое, когда дважды платят за одну работу)

    Или одна таблица с морфом, где есть имя модели, имя родителя и айди, как с картинками. То есть доступ определяется по наличию морфа, а не проверке через связь. Один раз грузанул с моделями их морфы, а потом чекаешь isset(). По факту в логике вы все равно вытянете модель из БД, и проверив потом морф бросите 403 исключение, вместо того чтобы "Не тянуть совсем".

    Другой вопрос методы работающие с пачкой, нечто вроде "дай мне все документы, которые принадлежат мне в рамках такой-то компании". Там я думаю можно в одной функции написать whereHas() и не тянуть все записи, так же как вы бы писали вместо LEFT JOIN - обычный JOIN чтобы в выборку не попало то, что не должно там быть.

    Это редкий случай когда лучше обобщить, чем нормализовать. Такой же как и писать action_log в общую таблицу по проекту, или хранить картинки или загруженные файлы по моделям в одной таблице чем создавать под каждую модель. (я просто напомню, что если все таблицы вязать через общее звено (а вот морф это не общее звено, это виртуальная связь не имеющая внешнего ключа), то ваша доктрина будет плакать кровавыми слезами, потому что подразумевает DDD и работу с агрегатом - группой таблиц под задачу) - то есть для нормализованной базы лучше дублировать таблицы под логику, тогда как в этих случаях лучше их обобщать, т.к. контроль доступа штука касающаяся отдельной логики называемой "авторизация", а не каждого элемента логики "по чуть чуть".
    Ответ написан
    Комментировать
  • Как преобразовать 19-значное число в короткую буквенную строку?

    gzhegow
    @gzhegow
    aka "ОбнимиБизнесмена"
    Да! Как раз вчера сделал. А всё-таки волны ноосферы (чо?) существуют)) Раз мне пришла идея, значит кому-то тоже.

    https://ru.stackoverflow.com/a/1437277/195624

    Впрочем, если тебе именно уникальность проверять, то есть crc32. Обратно не декодируешь, но что это "оно" можно понять.
    Ответ написан
  • Как можно сделать обработчик всех ссылок в laravel?

    gzhegow
    @gzhegow
    aka "ОбнимиБизнесмена"
    Мидлварь это и есть обработчик после того как роут определился. С его помощью можно принудительно вернуть ответ 404 или еще какой другой.
    Ответ написан
    Комментировать
  • Почему не работает route::fallback?

    gzhegow
    @gzhegow
    aka "ОбнимиБизнесмена"
    Может мидлвар ->middleware('FrontDataset') ваш не проходит проверку?
    Фолбэк может быть в группе, но заставлять условную 404-ую проходить проверки - опасно. Велика вероятность, что на 404-ой нет достаточного числа инструкций, чтобы проверку пройти.

    А ещё он у вас в неймспейсе, хотя для колбэка это пофиг должно быть.

    Ну и остается какой-то лара прикол связанный с доменом, подразумевающий что ->domain()->fallback() по регулярке никогда не сработает потому что ->fallback() это НЕ регулярка.
    Ответ написан
    Комментировать
  • Почему Cron не влияет на работу сайта?

    gzhegow
    @gzhegow
    aka "ОбнимиБизнесмена"
    Ащущэння у одного там в Минске есть.

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

    Собственно так и отправляют рассылки, почты, емейлы и прочее. Делают карту сайта, производят парсинг других сайтов, что там ещё, делают задачи расчитанные на "недели" - это когда человек должен на мобиле через неделю кнопку нажать, а задача все еще открыта и ждет его. Называется "фоновая задача". Просто второй скрипт пхп запускается одновременно с первым.
    Ответ написан
  • Почему у некоторых сайтов удается получить информацию об 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 комментария