• Как в phpstorm + git сделать частичную фиксацию файла?

    @AndryG Автор вопроса
    Разобрался. В окне кода каждый измененный кусок кода можно привязать к разному changeList. Когда будем комитить changeList, то увидим что типа "только 3 изменения из 5"
    Ответ написан
  • Как правильнее сделать такой функционал?

    @AndryG
    Основная фишка задачи в том, что вы указали даты, разбили прямую времени на диапазоны и прокомментировали лишь часть из них. А еще есть другие диапазоны. Например, между 17 часов 31 дек и 0 часов 1 янв, который в задаче не указан и если не указать на него ЗАКРЫТО, то так дойдем до диапазона по умолчанию и получим ОТКРЫТО.

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

    код
    <?php
    
    header('Content-type: text/plain');
    
    ?>31 Декабря с 8:00 до 17:00
      1 Января выходной день
      Со 2 января по 8 Января 10:00 до 23:00
      9 Января с 11:00 до 23:00
    
    <?
    $dtList = [
          ['12/31', '12/31', false, [['08:00', '17:00', true]]], // открыто
          ['01/01', '01/02', false, []], // закрыто (пустой диапазон времени)
          ['01/02', '01/08', false, [['10:00', '23:00', true]]],
          ['01/09', '01/09', false, [['11:00', '23:00', true]]],
          ['01/01', '12/31', true, [['06:00', '08:00', false]]],
    ];
    
    $dt = new dt('2020-12-28');
    $finish = (new dt('2021-01-14'))->getTimestamp();
    
    do {
        $res = false;
        foreach ($dtList as [$a1, $b1, $def, $subList]) {
            $a1 = $dt->_clone($a1);
            $b1 = $dt->_clone($b1);
            if (h::testTimeRange($dt, $a1, $b1)) {
                foreach($subList as [$a2, $b2, $c2]){
                    $a2 = $dt->_clone($a2);
                    $b2 = $dt->_clone($b2);
                    if (h::testTimeRange($dt, $a2, $b2)) {
                      $res = $c2;
                      break 2; // выход с обоих циклов
                    }
                }
                $res = $def; // первый уровень сработал, а второй не имеет подх. диапазона, значит значение по умолчанию для перв. уровня
                break;
            }
        }
        echo "\n ", $dt->format(), $res ? ' open' : ' close';
        $dt->modify('+'.rand(1, 1).' hour');
    } while ($dt->getTimestamp() < $finish);


    результат
    31 Декабря с 8:00 до 17:00
    1 Января выходной день
    Со 2 января по 8 Января 10:00 до 23:00
    9 Января с 11:00 до 23:00

    28.12.2020 00:00 open
    28.12.2020 03:00 open
    28.12.2020 05:00 open
    28.12.2020 08:00 open
    28.12.2020 09:00 open
    28.12.2020 11:00 open
    28.12.2020 12:00 open
    28.12.2020 13:00 open
    28.12.2020 15:00 open
    28.12.2020 16:00 open
    28.12.2020 18:00 open
    28.12.2020 19:00 open
    28.12.2020 20:00 open
    28.12.2020 23:00 open
    29.12.2020 02:00 open
    29.12.2020 05:00 open
    29.12.2020 06:00 close
    29.12.2020 09:00 open
    29.12.2020 12:00 open
    29.12.2020 15:00 open
    29.12.2020 17:00 open
    29.12.2020 20:00 open
    29.12.2020 22:00 open
    29.12.2020 23:00 open
    30.12.2020 02:00 open
    30.12.2020 03:00 open
    30.12.2020 06:00 close
    30.12.2020 07:00 close
    30.12.2020 10:00 open
    30.12.2020 12:00 open
    30.12.2020 15:00 open
    30.12.2020 17:00 open
    30.12.2020 19:00 open
    30.12.2020 20:00 open
    30.12.2020 23:00 open
    31.12.2020 02:00 close
    31.12.2020 05:00 close
    31.12.2020 07:00 close
    31.12.2020 09:00 close
    31.12.2020 10:00 close
    31.12.2020 13:00 close
    31.12.2020 16:00 close
    31.12.2020 19:00 close
    31.12.2020 20:00 close
    31.12.2020 23:00 close
    01.01.2021 01:00 close
    01.01.2021 02:00 close
    01.01.2021 03:00 close
    01.01.2021 04:00 close
    01.01.2021 06:00 close
    01.01.2021 09:00 close
    01.01.2021 10:00 close
    01.01.2021 11:00 close
    01.01.2021 12:00 close
    01.01.2021 13:00 close
    01.01.2021 15:00 close
    01.01.2021 16:00 close
    01.01.2021 18:00 close
    01.01.2021 20:00 close
    01.01.2021 23:00 close
    02.01.2021 00:00 close
    02.01.2021 03:00 close
    02.01.2021 06:00 close
    02.01.2021 07:00 close
    02.01.2021 10:00 open
    02.01.2021 11:00 open
    02.01.2021 12:00 open
    02.01.2021 13:00 open
    02.01.2021 14:00 open
    02.01.2021 15:00 open
    02.01.2021 16:00 open
    02.01.2021 17:00 open
    02.01.2021 18:00 open
    02.01.2021 20:00 open
    02.01.2021 23:00 close
    03.01.2021 02:00 close
    03.01.2021 04:00 close
    03.01.2021 07:00 close
    03.01.2021 10:00 open
    03.01.2021 12:00 open
    03.01.2021 13:00 open
    03.01.2021 16:00 open
    03.01.2021 17:00 open
    03.01.2021 20:00 open
    03.01.2021 22:00 open
    03.01.2021 23:00 close
    04.01.2021 00:00 close
    04.01.2021 02:00 close
    04.01.2021 05:00 close
    04.01.2021 06:00 close
    04.01.2021 09:00 close
    04.01.2021 12:00 open
    04.01.2021 13:00 open
    04.01.2021 14:00 open
    04.01.2021 15:00 open
    04.01.2021 17:00 open
    04.01.2021 19:00 open
    04.01.2021 22:00 open
    04.01.2021 23:00 close
    05.01.2021 01:00 close
    05.01.2021 02:00 close
    05.01.2021 05:00 close
    05.01.2021 06:00 close
    05.01.2021 08:00 close
    05.01.2021 10:00 open
    05.01.2021 11:00 open
    05.01.2021 14:00 open
    05.01.2021 16:00 open
    05.01.2021 17:00 open
    05.01.2021 20:00 open
    05.01.2021 23:00 close
    06.01.2021 01:00 close
    06.01.2021 03:00 close
    06.01.2021 04:00 close
    06.01.2021 05:00 close
    06.01.2021 08:00 close
    06.01.2021 09:00 close
    06.01.2021 11:00 open
    06.01.2021 13:00 open
    06.01.2021 15:00 open
    06.01.2021 18:00 open
    06.01.2021 20:00 open
    06.01.2021 22:00 open
    07.01.2021 00:00 close
    07.01.2021 01:00 close
    07.01.2021 02:00 close
    07.01.2021 03:00 close
    07.01.2021 06:00 close
    07.01.2021 07:00 close
    07.01.2021 09:00 close
    07.01.2021 10:00 open
    07.01.2021 13:00 open
    07.01.2021 14:00 open
    07.01.2021 16:00 open
    07.01.2021 17:00 open
    07.01.2021 20:00 open
    07.01.2021 23:00 close
    08.01.2021 01:00 open
    08.01.2021 02:00 open
    08.01.2021 04:00 open
    08.01.2021 05:00 open
    08.01.2021 07:00 close
    08.01.2021 09:00 open
    08.01.2021 11:00 open
    08.01.2021 14:00 open
    08.01.2021 17:00 open
    08.01.2021 20:00 open
    08.01.2021 23:00 open
    09.01.2021 00:00 open
    09.01.2021 01:00 open
    09.01.2021 02:00 open
    09.01.2021 05:00 open
    09.01.2021 07:00 close
    09.01.2021 10:00 open
    09.01.2021 12:00 open
    09.01.2021 14:00 open
    09.01.2021 17:00 open
    09.01.2021 20:00 open
    09.01.2021 22:00 open
    09.01.2021 23:00 open
    10.01.2021 01:00 open
    10.01.2021 04:00 open
    10.01.2021 05:00 open
    10.01.2021 07:00 close
    10.01.2021 10:00 open
    10.01.2021 12:00 open
    10.01.2021 14:00 open
    10.01.2021 17:00 open
    10.01.2021 19:00 open
    10.01.2021 20:00 open
    10.01.2021 23:00 open


    класс dt
    <?php
    class dt extends DateTime{
    
      /** Формат отображения даты-времени по умолчанию в игре */
      const F_DEFAULT = 'd.m.Y H:i';
    
      /**
      * Создает
      *
      * @param mixed $time
      * @param DateTimeZone $timezone
      */
      public static function createRand($time = null, DateTimeZone $timezone = null){
        $time = preg_replace_callback('@/(\d+)-(\d+)/@', function($m){
             return (string)h::rand($m[1], $m[2]);
          }, $time);
        return new self($time, $timezone);
      }
    
      /**
      * $time допускает указание нескольких доп. параметров для modify() через разделитель |
      *
      * @param mixed $time
      * @param DateTimeZone $timezone
      * @return DateTime
      */
      public function __construct($time = null, DateTimeZone $timezone = null){
        $time = explode('|', $time);
        parent::__construct($time[0], $timezone);
        while($s = next($time)){
          $this->modify($s);
        }
      }
    
      /**
      * Вывод даты согласно формату
      *
      * @param string Мо умолчнию будет общепринятый в игре вариант F_DEFAULT
      * @return string
      */
      public function format($format = null){
        return parent::format(is_null($format) ? self::F_DEFAULT : $format);
      }
    
      /**
      * Клонирует текущий объект.
      * @return dt
      */
      public function _clone($modify = null){
        $res = clone $this;
        if(!is_null($modify)){
          $res->modify($modify);
        }
        return $res;
      }
    
      public function __toString(){
        return $this->format();
      }
    
    }
    Ответ написан
  • Как сохранять дроби в int?

    @AndryG
    Вы пользуетесь неявными преобразованиями СУБД и интерпретатора.
    php отбрасывает дробную часть, mysql приводит к целому арифметически - так решили их создатели.

    Переведите mysql в strict_mode, если уж и правда шизанутый, получите ошибку типа и займитесь приведением типов самомстоятельно.
    Ответ написан
  • Почему в интеркасса при отмене платежа он засчитывается?

    @AndryG
    $payStatus = trim($_POST['ik_inv_st']); -- больше переменная в коде не встречается


    Вам присылают уведомление о изменении статуса платежа, а вы игнорируете этот статус и выдаюете плюшки клиентам.

    Что за игра? Любопытно глянуть на сервер :)
    Ответ написан
  • Как сделать sql select по дате?

    @AndryG
    Сдается мне, что, запихнув поле в функцию приведения типа либо даты, вы убили использование индекса по полю.

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

    where  UpdateDate >= :date and UpdateDate < date_add(:date, interval 1 day)
    -- :date - полночь необходимой даты
    Ответ написан
  • Как организовать "виртуальные" папки?

    @AndryG
    Типа так: Главная папка -> Вложенная папка -> Вложенная во вложенную и т.д.


    это называется "хлебные крошки" - каждое название папки является ссылкой на страницу с содержанием папки.

    Список родителей добыть серией запросов либо рекурcивным
    Ответ написан
  • Как открыть публичный доступ к git-репозиторию в частной локальной сети?

    @AndryG
    Как открыть публичный доступ к git-репозиторию в частной локальной сети?
    Требуется удаленно обновлять репозиторий во внутренней локальной сети из облачного сервиса.

    Это только я не понимаю, где репозиторий, где облако и где юзер: в облаке или репозитории :)
    Ответ написан
  • Стоит ли разделять 1 общий запрос на несколько маленьких?

    @AndryG
    А если добавить перечень частей, которые просят вернуть?
    дай мне:
    * автомобиль
    * запчасти
    * сервисные центры
    * утилизация
    * все отделы
    Юзер может выбрать, какие данные запросить в одном запросе: один, два или всё
    Ответ написан
  • Как вычесть значение в bd через php?

    @AndryG
    Напишите триггер post delete, где запросом изменяйте значение поля в дугой таблице. Без структуры таблиц конкретнее ответ не получить.
    Ответ написан
  • Браузер не загружает файлы, пишет No 'Access-Control-Allow-Origin. Что делать?

    @AndryG
    Парсер выполняется в браузере? Значит надо вникать в междоменные запросы, а там безопасности вагон и тележка. Конкретно про CORS в вики описано вполне доходчиво, что и как. Заголовка "Access-Control-Allow-Origin" на жертве нет, значит остается JSONP, который вам тоже не поможет.

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

    @AndryG
    Я в коде для таких задач имею скриптик лет 10 назад написанный:
    public static function execAsDeamon($script,$params = null){
        $tmp = '';
        foreach((array)$params as $k=>$v){
          if(empty($k)){
            continue;
          }
          $tmp .= ' -'.$k.'='.$v;
        }
        $tmp = g::options('core.php-cli-starter', 'php').' '.$script.' '.srv::$HOST_TYPE.$tmp.' > /dev/null &';
        exec($tmp);
      }


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

    Само собой, в логике приложения есть предохранитель от многократного запуска демона.
    Ответ написан
  • Как определить страну прокси, убрать Китайские прокси и полностью перезаписать файл финальным результатом?

    @AndryG
    Как сделать, чтоб он не добавлял новые результаты после старых результатов, а полностью перезаписывал файл: socks5_valid.txt новыми результатами ?


    file_put_contents ($filename, $s."\r\n", FILE_APPEND);

    Убрать параметр FILE_APPEND
    Ответ написан
  • Как правильно написать запрос к БД?

    @AndryG
    Если я правильно понял вот это все нагромождение id :)

    select 
     a.userId,
     sum(k1.val * k2.val * k3.val) points 
    from aciv a
     join users on u.userId = a.userId  -- эта строка вроде как и не нужна, если нут других ограничений по users
     join kof k1 on a.kof1 = k1.id
     join kof k2 on a.kof2 = k2.id
     join kof k3 on a.kof3 = k3.id
    group by a.userId
    order by 2 desc
    limit 5


    Запрос будет тяжелый, ибо без пересчета всех данных нужные не определить.
    Ответ написан
  • Прогресс бар php?

    @AndryG
    str_pad вам в помощь. Не запутайтесь в округлениях.

    str_pad — Дополняет строку другой строкой до заданной длины

    Попробую на пальцах:

    length = 50 штук
    val = 35 %
    первыми выводим звездочек в количестве ceil(50 * 35 / 100)
    str_pad(res, ceil(50 * 35 / 100), '*')
    А потом добавляем точками до 50
    str_pad(res, 50, '.')

    В вопросе стоило упомянуть, что вас интересует консольная версия (или text/plain)
    Ответ написан
  • Вывод MYSQLI с INNER JOIN и GROUP BY + ORDER. Как?

    @AndryG
    Нужно сделать просто: взять ID из TAB1, сделать JOIN с TAB2, и вывести по порядку ID, LOCAT и DATE, но отсортировав по DATE - интересны только последние даты (свежие)


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

    Если смысл наших фраз совпадает, то поступить нужно иначе. С tab2 данные нужно выбирать по двум полям (id, max(date), а у вас ключ лишь один - id. Значит сперва нужно сформировать набор данных с ключом из двух полей (id, date), а потом приджоинить к нему саму таблицу tab1, связав их сразу по двум полям. Получается выборка в два захода.

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

    select 
      t1.id, t1.raw, t2.date, t2.locat
    from ( -- формируем промежуточный набор данных с id+date подходящих записей 
    select a2.id, max(a2.date) date
    from tab2  a2 
      join tab1 a1 on a2.id = a1.id  -- этот джоин ограничивает множество a2, чтобы не группировать лишние записи
    group by a1.id, a1.date
    ) n
    join tab1 t1 on t1.id = n.id
    join tab2 t2 on t2.id = n.id and t2.date = n.date -- теперь в джоине участвует два поля, чтобы точно указать на запись, которая нам нужна


    Можете выполнить внутренний запрос отдельно и увидеть, что он вам выберет.

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

    @AndryG
    Откройте для себя методы HTTP (get/post/put/delete/patch) - не зря их придумывали.

    Для простоты решения возьмите форму CLASS/param/param/param

    /user/234 - страница пользователя
    /user/234 - аналогично предыдущему
    albums/user/234/ - страница альбомов пользователя 234
    albums/567 - конкретный альбом пользователя (если номер альбомов сквозные)
    albums/234/6 - если нужны два поля user-num

    А вот что делать - пусть указывает HTTP метод (get/put/delete)

    Ну, или CLASS/METHOD/param/param/param
    Ответ написан