• Почему у практически идентичных условий разная скорость проверки?

    не мастер в пайтоне, но допускаю что (if nums[j] ==) может быть решено ещё до того, как посчитается разность по типу отсечения пустых или неверных данных
  • Какие используются практики для отладки кода в проекте, построенном на микросервисах в Docker контейнерах?

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

    Я предпочитаю обернуть кусок кода в главном index файле, чтобы с помощью гет можно было пост запрос сэмулировать указав $GET['method'] = 'POST', потому как в браузере сие будет работать и в браузере его же удобно и смотреть. Если авторизация - есть для браузера приблуда ModHeaders, позволяет вручную указать заголовки, которых там не было и помнит их, пока не выключишь.

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

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

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

    На самом деле было б удобно, чтоб пых-разрабы выпустили какую-то функцию вроде zval_func_callback и zval_func_return_callback, чтобы можно было запускать при вызове/конце любой функции и там буквально с помощью статической переменной и проверки ЕСЛИ считать время начала-конца, но это не ежедневная задача так что пофиг.
  • Как соединить две модели в коллекции?

    В вашем случае получилось смешать сервис, собирающий информацию, и объект, содержащий информацию, и получилось нечто среднее не делающее не то и не другое.

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

    Помните, ООП это не "правильный код", ООП - это способ описать происходящее в программе на человеческом языке. В вашем случае становится непонятно как оно работает, хотя с точки зрения компьютера оно работает. Вы сделали на ООП то, с чем ООП борется - с невозможностью описать процесс, происходящий в коде.
  • Можно ли через .htaccess сократить id get запроса сайт.ru/profile.php?id=2 до сайт.ru/id2?

    да, ваш скрипт ожидает, что пользователь, нажав на ссылку (перейдя на страницу), передаст параметр id=цифра.

    в вашем .htaccess вы пишите RewriteRule где указываете, что "все ссылки начинающиеся на /id(\d+) ведут на profile.php?id=$1 [L,NC,QSA], где L - означает "последний", NC - "не учитывать регистр", QSA - "не потерять другие параметры get запроса, если они были"
  • Не работает whereIn если данных больше 700,почему так?

    Столкнулся недавно.

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

    Решается как Дмитрий написал - писать подзапросы. Причем если писать их через

    ->whereIn('field', $query) или ->whereIn('field', function ($query) {})

    то потом нет возможности использовать

    $query->chunk(500, function ($models) {});

    (т.к. косячит ensureOrderby() из-за alias для таблицы, а ещё и лимит не может быть применен к whereIn $subquery в некоторых версиях БД)

    Для этого можно так:

    $sql = $subQuery->toSql();
    
    $query
      ->from("table as t")
      ->join(
        "($sql) as sub",
        function ($join) use ($subQuery) {
          $join->on('t.field', '=', 'sub.field2)
          $join->addBinding($subQuery->getBindings());
        }
      );
  • Нужно ли использовать interface?

    Ипатьев, пс. я бы рад узнать способ обучения, в котором я могу писать короче, но пока не знаю, существует ли он, тем более что посмотреть инфо-повестку - там такое, что "разные кожаные ублюдки" это очень вежливая форма.
  • Нужно ли использовать interface?

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

    Если бы могли заставить книги адаптироваться к мозгу ученика, книга бы показывала одно и то же разными словами.
  • Как из одного развернутного через docker-compose Django проекта подключиться к базе данных другого так же развернутого Django проекта?

    Что-то мне кажется так не задумывалось. Вроде docker-compose это про "сборку проекта", а не про "подымите 10 проектов на базе композа и потом соедините их вместе"... Либо они не в сети и у них разные адреса, либо они в проекте и у них разные порты, поднять десять проектов, которые друг о друге не знают, но имеющие полностью одинаковые конфигурации, чтобы их потом соединять, через виртуальную сеть, о которой они все знают... жестко. Не знаю как это сделать :(

    Нагуглилось что-то:
    How to link two Docker compose?
    - Create an external network with docker network create <network name>
    - In each of your docker-compose. yml configure the default network to use your externally created network with the networks top-level key.
    - You can use either the service name or container name to connect between containers.


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

    lexstile,

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

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

    предусматривается сессия. не в смысле прям вот пхп сессия, а некое временное хранилище, куда положим "последний файл залитый юзером"

    лучше файлы класть по
    uploads/1970-01-01/{user_id}/{form}/{field}/{original_name}_{uniqid()}.{extension}
    , пока не привязана модель
    (user_id может быть 0, если не авторизован, но так редко бывает, чтобы кто-то позволял хранить чужие фотки анонимусам, это же все таки диск с ограниченным (платным) местом и вероятный ddos)

    Файлам добавляется постфикс uniqid(), чтобы три загрузки файла не вызвали коллизию с теми, что есть уже
    Соответственно удаление старых для этой формы-поля производится через "поставили новую...хмм. старая была? да. удаляем" и "запросили старую. была? да. устарела? да. удаляем"

    После того как форма одобрена, если мы делаем не личный архив пользователя, а админку для других записей, то перекладываем фотку вот сюда например
    storage/{model_name}/{model_id}/{original_name}_{uniqid()}.{extension}


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

    Временные хранилища достаточно легко делать играясь с Symfony\Cache компонентом. Не уверен правда что там можно получить "список устаревших", но попробовать стоит. Потому как для картинок "устарело" означает "удалить файл", а не просто "забыть поле".

    Чтобы точно быть уверенным, что пользователь не поменял фотку в форме, а в сессии в этой лежит ещё старая - с формой передается md5 картинки, которая высчитана яваскриптом на клиенте. Этот же md5 передается и на сервер вместе с картинкой при нажатии "применить картинку". Если тот что в форме и тот что прошлый раз отсылался совпадают - значит та же картинка, сабмитим форму и чистим "последнюю загруженную".

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

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

    Формы вообще зло, даже если на компьютерные игры посмотришь - очень во многих пользовательские интерфейсы очень корявые, потому что писать эти формы, их внешний вид и тд. хоть и легче, чем 3d, но все равно боль...
  • Как из одного развернутного через docker-compose Django проекта подключиться к базе данных другого так же развернутого Django проекта?

    Я не увидел у вас определения второго сервера базы данных.
    Один сервер вы заводите, потом через networks их соединяете в виртуальную сеть, к нему подключаетесь. Нет второго сервера баз данных - нечего и писать.

    Если речь о второй бд на первом сервере, то нужно скорее всего вот это менять:

    'NAME': os.environ.get('POSTGRES_NAME'),

    это похоже на имя базы данных внутри сервера HOST на порту PORT.
  • Как работает padding hack?

    Блин, прикольно, не знал)

    <div class="wrapper"><div class="box"></div></div>
    
    .wrapper {
      width: 500px;
    }
    .box {
      background: red;
      height: 0;
      padding-bottom: 56.25%;
      width: 300px;
    }
  • Как вызывать динамический метод класса как статический в PHP?

    CaptainJustness, вот свой делать хотя и можно было, но не стоит, я уже через это проходил, неблагодарное дело. Все что вам нужно это установить пакет illuminate/database в свой проект, чтобы пользоваться БД лары в любом проекте. Второе, что вероятно скоро пригодится - класс отложенного выполнения запросов. Писать свой такой же может быть нужно лишь в целях обучения, потому что сделать свою обертку для БД совсем непросто, и поддерживать потом десяток баз данных с разными особенностями SQL - это больно, лучше использовать уже просто PHP PDO, где очень скилловые дяди давно прошли через тысячи приколов.

    В вашем примере вы делаете extends. Вы сейчас на этапе, когда считаете, что взять методы можно только наследованием. Взять ещё можно "композицией"

    class ModelService {
      protected $modelHelp;
    
      public function __construct(ModelHelp $modelHelp) {
        $this->modelHelp = $modelHelp;  
      }
    
      public function test() {
        echo 'It\'s OK';
      }
    
      public static function __callStatic($method, $parameters) {
        return $this->modelHelp->$method(...$parameters);
      }
    }


    Выглядит как будто одно и то же, но в отличии от extends это позволяет во первых несколько функционалов "подкидывать на вход", во вторых если ожидать не ModelHelp, а ModelHelpInterface, то можно позже написать другой ModelHelp, чтобы подменить первый не затрагивая код этого класса.

    То что я говорил - наследование нужно строго там где оно нужно. К примеру есть у вас BaseModel и есть Model, которая наследует BaseModel. И здесь будет один уровень и никогда не пригодится второй. Где базовая модель действительно описывает поведение "по-умолчанию", а конкретная - делает что-то иначе. Пытаясь воткнуть наследование везде - вы захотев это переписать - снова заставите себя наследоваться и в конце уткнетесь в то, что функции повторяются, и нужно наследовать "два сразу", а так не работает. Поэтому наследование это про "базовый + реальный", а не про "исполнитель-обертка".

    Второе что в вашем примере написано.

    class ModelHelp {
      public static function test() {
        static::getInstance()->test();
      }
      public static function getInstance()
      {
        return new Model;
      }
    }


    Давайте логически подумаем что оно делает. Вы пишете static::getInstance() что означает "эй, ModelHelp, дай мне свой экземпляр". Но вместо своего экземпляра вы просите экземпляр вообще другого класса Model, который связан с первым только вашей задумкой, любой это читающий будет чесать голову "боже, как он умудрился это придумать" - т.к. оно "нелогично" или "непоследовательно".

    getIntance() дословно означает "дай экземпляр".

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

    class ModelHelp {
      public static function getInstance()
      {
        return static::$instances[ static::class ] = static::$instances[ static::class ]
          ?? new static();
      }
      protected static $instances = [];
    }


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

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

    class ModelFactory {
      protected $di;
    
      public function __construct(\Psr\Container\ContainerInterface $di = null) {
        $this->di = $di;
      }
    
      public function newModelService()
      {
        return new ModelService(); // а если ларавельный контейнер, то $this->di->make(ModelService::class);
      }
    
      public function getModelService()
      {
         return isset($this->di) && $this->di->has($name = ModelService::class)
           ? $this->di->get($name)
           :  $this->newModelService();
      }
    
      public static function getInstance()
      {
        return static::$instances[ static::class ] = static::$instances[ static::class ]
          ?? new static(); // вот здесь оно создаст фабрику БЕЗ контейнера, а нам то надо с, поэтому...
      }
    
      public static function withInstance(?ModelFactory $factory)
      {
        static::$instances[ static::class ] = $factory;
      }
    }
    
    class ModelService {
      public function test() {
        echo 'test';
      }
    }
    
    class ModelFacade {
      public static function __callStatic($method, $arguments)
      {
        // и здесь тоже будут проблемы, но это правильное "решение"
        // есть функции возвращающие void, там нельзя ставить спереди return
        // есть функции работающие со ссылкой на входе, и там нельзя использовать магию
        // есть функции возвращающие генератор и там нужно делать yield from вместо return
        // есть функции возвращающие генератор и работающие по ссылке, там надо делать foreach ($gen) { yield $ref; }
        return ModelFactory::getInstance()->getModelService()->{$method}(...$arguments);
      }
    }


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

    В итоге вы пишите:

    $container = new Container;
    $factory = new ModelFactory($container);
    ModelFactory::withInstance($factory); // указали что наш экземпляр теперь "основной"
    ModelFacade::test(); // и получаете 'test';


    Хотя в последнем методе под капотом сначала возьмется существующая фабрика, потом проверится в контейнере наш сервис если он там был, если нет - фабрика создаст новый, вернет его, и выполнин на тем действие test()
  • В чем заключается проблема haystack/needle PHP?

    Излюбленная тактика политиков - взлетать на реактивной струе ушата фекалий которую они изрыгают.

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

    Здесь есть определенные штуки, которые стоило бы выпустить патчами:
    array_filter(explode(',', $string))
    array_reduce(array_map(array_map($array)))


    точно проигрывает по читаемости и числу кода:

    string.split(',').filter()
    array.map().map().reduce()


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

    Просто иногда разрабы языка очень любят спрыгивать

    то на "голосование за изменения в следующей версии" (то есть чтобы протолкнуть надо собрать брагу, а это почти невозможно, не будучи блоггером)

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

    так что файлик с парой доработок и тебе не страшны ни бури ни ветер.
  • Как пишут обмен данными (сетевой движок) для компьютерных игр?

    gzhegow
    @gzhegow Автор вопроса
    Одиночка Айс, там тоже есть специалисты, хорошо умеющие в вебсокет и асинхронку. Лучше чем "запустить в параллельке обработку строк" и кое-кто на js даже игры делал, вполне себе 3д, правда в браузерах.