Ответы пользователя по тегу PHP
  • Как вывести сообщение в рабочее время?

    abyrvalg
    @abyrvalg
    Вам надо отслеживать, в каком "рабочем дне" вы сейчас находитесь и на основе этого двигать границы интервала.

    Туповато, но, надеюсь, наглядно:
    function isWorkTime(string $timeFrom, string $timeTo, ?string $currentTime = null): bool
    {
        $t1 = strtotime($timeFrom);
        $t2 = strtotime($timeTo);
        $now = $currentTime === null ? time() : strtotime($currentTime);
    
        if ($t2 < $t1) {
            if ($t1 > $now) {
                $t1 -= 86400; // минус одни сутки
            } else {
                $t2 += 86400; // плюс одни сутки
            }
        }
        return $t1 <= $now && $now < $t2;
    }
    
    var_export([
        '=== 12:00 - 13:00 (1 hour) ===',
        '1. 11:59' => isWorkTime('12:00', '13:00', '11:59'),
        '1. 12:00' => isWorkTime('12:00', '13:00', '12:00'),
        '1. 12:01' => isWorkTime('12:00', '13:00', '12:01'),
        '1. 12:59' => isWorkTime('12:00', '13:00', '12:59'),
        '1. 13:00' => isWorkTime('12:00', '13:00', '13:00'),
        '1. 13:01' => isWorkTime('12:00', '13:00', '13:01'),
        '1. 00:00' => isWorkTime('12:00', '13:00', '00:00'),
        '=== 00:00 - 12:00, 13:00 - 00:00 (23 hours) ===',
        '2. 11:59' => isWorkTime('13:00', '12:00', '11:59'),
        '2. 12:00' => isWorkTime('13:00', '12:00', '12:00'),
        '2. 12:01' => isWorkTime('13:00', '12:00', '12:01'),
        '2. 12:59' => isWorkTime('13:00', '12:00', '12:59'),
        '2. 13:00' => isWorkTime('13:00', '12:00', '13:00'),
        '2. 13:01' => isWorkTime('13:00', '12:00', '13:01'),
        '2. 00:00' => isWorkTime('13:00', '12:00', '00:00'),
    ], false);
    Ответ написан
    Комментировать
  • Паттерн для выборки ссылок сортировкой по заданному домену/анкору?

    abyrvalg
    @abyrvalg
    Вы точно хотите парсить html регэкспами? Одумайтесь, ведь может прийти Он.

    Как-то так, может?

    $doc = new DOMDocument();
    $doc->loadHTML($htmlAsString);
    $links = $doc->getElementsByTagName('a');
    
    function filterByHref(DOMNodeList $anchors, string $hrefRegex): array {
        $links = [];
        /** @var DOMElement $elm */
        foreach ($anchors as $elm) {
            if (! $elm->hasAttribute('href')) {
                continue;
            }
            $link = $elm->getAttribute('href');
            if (preg_match($hrefRegex, $link)) {
                $links[] = $link;
            }
        }
    
        return $links;
    }
    
    var_export([
        'cnt' => $links->length,
        'goo' => filterByHref($links, '|^https://google.com\b|'),
        'link' => filterByHref($links, '|link1|i'),
    ], false);
    Ответ написан
    1 комментарий
  • Как выполнить "sudo service tor restart" из php скрипта?

    abyrvalg
    @abyrvalg
    > У пользователя Apache должны быть права на команды exec, как root, используя sudo.
    За такие рекомендации надо причинять рекомендодателю смерть через сепукку.

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

    abyrvalg
    @abyrvalg
    Разбейте на две части: группировка и вывод:

    $cities = [];
    while ($ob = $res->GetNextElement()) { 
        $cityName = ...;
        $image = ...;
        $cities[$city][] = $image;
    }
    
    foreach ($cities as $cityName => $images) {
        ...
        foreach ($images as $image) {
                ...
        }
        ...
    }
    Ответ написан
  • Как найти элемент в многомерном массиве используя array_search?

    abyrvalg
    @abyrvalg
    Если неизвестно, где конкретно может находиться искомая пара ключ-значение, то как-то так:

    function isItemExists(iterable $source, $expectedKey, $expectedValue): bool
        {
            $iterator = new RecursiveIteratorIterator(
                new RecursiveArrayIterator($source, RecursiveArrayIterator::CHILD_ARRAYS_ONLY),
                RecursiveIteratorIterator::LEAVES_ONLY
            );
    
            foreach ($iterator as $itemKey => $itemValue) {
                if ($expectedKey === $itemKey && $expectedValue === $itemValue) {
                    return true;
                }
            }
    
            return false;
        }
    Ответ написан
    Комментировать
  • Регулярные выражения для диапазона IP адресов?

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

    $firstIpAsString = '77.88.0.0';
    $lastIpAsString  = '77.88.0.18';
    $ipAsString      = '77.88.0.111';
    
    $firstIp = ip2long($firstIpAsString);
    $lastIp  = ip2long($lastIpAsString);
    $ip      = ip2long($ipAsString);
    
    var_export([
        'first' => $firstIp,
        'last' => $lastIp,
        'ip' => $ip,
        'in range?' => $firstIp <= $ip && $ip <= $lastIp,
    ], false);
    Ответ написан
    Комментировать
  • Как провести операцию вычисления с ассоциативным массивом?

    abyrvalg
    @abyrvalg
    array_map или array_walk.

    $limit = 8;
    
    // VAR 1
    $processedItems = \array_map(function ($value) use ($limit) {
        $subHours = 0;
        $hours = $value['hours'];
        if ($hours > $limit) {
            $subHours = $hours - $limit;
            $hours = $limit;
        }
        return [
            'hours' => $hours,
            'sub_hours' => $subHours,
        ];
    }, $items);
    
    // VAR 2
    \array_walk($items, function (&$value) use ($limit) {
        $hours = $value['hours'];
        if ($hours > $limit) {
            $value['hours'] = $limit;
            $value['sub_hours'] = $hours - $limit;
        }
    });
    Ответ написан
    2 комментария
  • Как экранировать кавычки?

    abyrvalg
    @abyrvalg
    Используйте heredoc: php.net/manual/en/language.types.string.php#langua...

    $x = <<<XML
    <Объект Нпп="1234" Тип="ДокументСсылка.РеализацияУслуг" ИмяПравила="РеализацияУслуг"><Ссылка Нпп="2142">
      <Свойство Имя="{УникальныйИдентификатор}" Тип="Строка">
        <Значение>LIMB-001628</Значение>
      </Свойство>
      <Свойство Имя="Дата" Тип="Дата">
        <Значение>2019-02-28T17:24:12</Значение>
      </Свойство>
    </Ссылка>
    </Объект>
    XML;
    Ответ написан
  • Как искать в многомерном массиве?

    abyrvalg
    @abyrvalg
    $arr = \json_decode($a, true);
    
    $reducer = function ($carry, $item): float {
        if ('qw_wallet_rub' === $item['alias'] ?? null) {
            return $carry + $item['balance']['amount'] ?? 0.0;
        }
        return (float)$carry;
    };
    
    $result = \array_reduce($arr['accounts'], $reducer);
    Ответ написан
    2 комментария
  • Как вывести дни между датами?

    abyrvalg
    @abyrvalg
    /**
         * @param \DateTimeImmutable $dateFrom
         * @param \DateTimeImmutable $dateTo
         *
         * @return \DateTimeImmutable[]
         * @throws \Exception
         */
        function daysRange(\DateTimeImmutable $dateFrom, \DateTimeImmutable $dateTo) : iterable
        {
            $iter = clone $dateFrom;
            while ($iter <= $dateTo) {
                yield $iter;
                $iter = $iter->add(new \DateInterval('P1D'));
            }
        }
    
        $days = daysRange(
            new \DateTimeImmutable('2020-01-25'), 
            new \DateTimeImmutable('2020-03-01')
        );
        foreach ($days as $day) {
            echo sprintf("%s\n", $day->format('Y-m-d'));
        }
    Ответ написан
    Комментировать
  • Как исправить Invalid argument supplied for foreach()?

    abyrvalg
    @abyrvalg
    Скорее всего, json невалидный. Проверить это можно как-то так:
    $data = json_decode('{qwe}', true);
    
    if (JSON_ERROR_NONE !== json_last_error()) {
        throw new \RuntimeException(sprintf(
            'JSON parsing error: `%s`',
            json_last_error_msg()
        ));
    }
    
    var_export($data, false);


    Если NULL в json - это допустимое значение, то можно сконвертировать его в пустой массив:
    $data = json_decode('null', true) ?? [];
    Ответ написан
  • Как правильно составить регулярное выражение?

    abyrvalg
    @abyrvalg
    Используйте заглядывание вперед/назад:

    $text = 'qwe {111} {+222} {-333} {+12e3}';
    
    $preg = '/(?<=\{) ([+-]* \d+) (?=\})/x';
    preg_match_all($preg, $text, $match);
    var_export($match);
    Ответ написан
    Комментировать