Ответы пользователя по тегу PHP
  • Какой метод реализации при подходе CQRS правильный?

    vhood
    @vhood
    Не забывайте отмечать решения
    Архитектура монолит.
    например для Order это его классы которые лежать в папке Order, его Aggregate Root
    У Вас модуль = агрегат? Это не одно и то же.

    За пределами своего неймспейса модуля, классы напрямую не используются и не вызываются, кроме Api service классов
    Модуль - самостоятельная единица, которая должна работать без других модулей. Low coupling, high cohesion. Представьте, что он может подключаться через composer, вот каким он должен быть? У Вас так?
    Что за паттерн "Api service", который какие-то DTO отдает? У агрегата может быть id другого агрегата и этого ему должно быть достаточно.

    У Вас один контекст? Когда кто-то говорит "Store" (или, скорее всего, склад), все имеют ввиду одно и то же? Store с точки зрения покупателя и Store с точки зрения какого-то другого актора (например, поставщика) - одно и то же?
    Если нет, Вам стоит разделить 2 контекста и сделать 2 Store. Один самостоятельный, и один как поддомен у Order и тогда вся логика будет в Order.
    spoiler
    слой Application одного контекста не может ссылаться на слой Domain другого контекста

    Если контекст единый, может Store не заслуживает быть самостоятельным агрегатом? Если все-таки заслуживает, Order может выполнять свои обязанности, имея только id из Store? Это "на подумать".

    В любом случае, один агрегат может воспользоваться другим (но не получать напрямую его объекты для реализации своей логики, только использовать функционал Aggregate Root), но если ими можно воспользоваться в слое Apprication последовательно - это будет лучше.

    сперва у модуля Store проверить работает ли этот store, то есть проверить его рабочие часы и дневной лимит на продажу
    Мне кажется, очевидно, что если это все-таки 2 разных агрегата одного контекста, то Store даже бизнес-логику тут не реализует, нужно просто проверить спецификацию. Делать это нужно в Application, вызвать 2 агрегата последовательно. Не нужно делать это ответственностью Order.
    Ответ написан
  • Как найти в строке текст который содержит спецсимволы с помощью регулярного выражения?

    vhood
    @vhood
    Не забывайте отмечать решения
    Судя по предоставленным данным, от поставщика некий артикул всегда находится в конце строки.

    Регулярные выражения тут не нужны.

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

    $items = array_intersect(
        $companyItems, // на сайте
        array_map(
            function (string $item) {
                $parts = explode(' ', $item);
                return end($parts);
            },
            $supplierItems // от поставщика
        ),
    );
    Проверка

    spoiler
    если не доставать отдельно имена товаров на сайте, можно собрать артикулы с товаров поставщика в один массив, пройтись по товарам на сайте и проверить in_array($item['name'], $supplierNames, true)
    Ответ написан
    8 комментариев
  • Как упростить метод, выполняющий операции для всех других методов класса, если он получается слишком раздутым?

    vhood
    @vhood
    Не забывайте отмечать решения
    Здесь Вы принимаете type
    public function makeRequest(array $args, string $type) {
    Здесь выполняете логику в зависимости от typeif($type === "source1") {

    Для каждого type нужно создать класс, который будет выполнять логику, описанную в его блоке if.
    пример

    class SpecificTypeApiService implemets ApiServiceInterface
    {
        public function send()
       {
    //код ниже просто скопирован, стоит вынести что-то в параметры, что-то в конструктор и сделать код более элегантным
    //можно сделать абстрактный класс и делегировать ему общий для разных type (сервисов) функционал
        $proxiesArr = array('72.37.217.3:4145', '174.77.111.196:4145');
              
              $randProx = array_rand($proxiesArr, 1);
              
              $proxyIp = $proxiesArr[$randProx];
            
    //      $proxyIp = '174.77.111.196:4145';
            $url1 = $args[0] . $args[1];
                $headers = [
                'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.105 YaBrowser/21.3.3.230 Yowser/2.5 Safari/537.36'
                ];
    
                $curl = curl_init();
    
            curl_setopt($curl, CURLOPT_PROXY, $proxyIp);
            curl_setopt($curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS4);
            curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
            curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); 
            curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
            curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
            curl_setopt($curl, CURLOPT_VERBOSE, 1); 
            curl_setopt($curl, CURLOPT_POST, false);
            curl_setopt($curl, CURLOPT_URL, $url1);
    
            $result = curl_exec($curl);
    
            if(curl_exec($curl) === false)
            {
            echo 'Ошибка curl: ' . curl_error($curl);
            } else {
            echo 'Операция завершена без каких-либо ошибок';
            }
    
            return $result;
       }
    }


    После, с помощью DI и полиморфизма, отрефакторить существующий код следующим образом:

    Здесь Вы принимаете сервис вместо type
    public function makeRequest(array $args, ApiServiceInterface $apiService) {

    Здесь выполняете логику, но выполнение делегируете сервису$apiService->send();

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

    vhood
    @vhood
    Не забывайте отмечать решения
    С помощью функций для работы с массивами и/или конструкций для итерации массивов.

    UPD:
    Если только configuration_value, то можно напрямую
    //$array - исходный массив
    //$configurationValue - новый массив
    $configurationValue = $array['configuration_value'];
    Однако смысла в этом никогда нет, только память расходовать. Значения по ключу можно получать там, где это нужно, не сохраняя их в отдельную переменную.
    Ответ написан
    Комментировать
  • Как убрать отступы в коде?

    vhood
    @vhood
    Не забывайте отмечать решения
    $BaseSiteMap = preg_replace('/\s{2,}/m', '', $BaseSiteMap);

    В песочнице
    Ответ написан
    Комментировать
  • Почему не видит контроллер?

    vhood
    @vhood
    Не забывайте отмечать решения
    Мне выдает такую ошибку Class "App\Http\Controllers\Post\BaseController" not found

    Ваш контроллер называется BasesController, а не BaseController
    Ответ написан
  • Как вывести время в текущем часовом поясе?

    vhood
    @vhood
    Не забывайте отмечать решения
    По коду:
    $datetime создается внутри условия, в else не хватает return, т.к. код дальше требует переменную $datetime, которой нет ($formatter->format($datetime))

    По вопросу:
    Часовой пояс устанавливается так
    $datetime = new DateTime($user_reg);
    + $datetime->setTimezone(new DateTimeZone('Europe/Moscow'));

    Но, скорее всего, в системе нужно установить часовой пояс глобально. Если это так:
    Ответ написан
    5 комментариев
  • Проблема с отображением данных о городах из таблицы в запросе SQL?

    vhood
    @vhood
    Не забывайте отмечать решения
    алиасы нужно указать
    $sql = "SELECT
        o.overhead_code,
        f.name from_name,
        f.comapny from_company,
        f.city from_city,
        f.address from_address,
        f.phone from_phone,
        t.name to_name,
        t.comapny to_company,
        t.city to_city,
        t.address to_address,
        t.phone to_phone,
    FROM overheads o
    JOIN cities f
        ON f.from_city = o.id 
    JOIN cities t
        ON t.to_city = o.id 
    WHERE o.overhead_code = '$trackingNumber'";
    Ответ написан
    Комментировать
  • Как через foreach прочитать два файла в масив?

    vhood
    @vhood
    Не забывайте отмечать решения
    открывается второй файл и подгружается первый есть есть номер т звоним а если нет ищем другой вариант

    $phones = file("./promotion.dat");
    $users = file("./promotion2.dat");
    
    foreach ($users as $index => $data) {
    	if (!array_key_exists($index, $phones)) {
    		continue;
    	}
    
    	$user = preg_replace('/[^<]*<\|>[^<]*<\|>([^<]+).*/', '\1', $data);
    	$phone = preg_replace('/.*<\|>(\d+)<\|>.*/', '\1', $phones[$index]);
    
    	echo sprintf('%s: %s', $user, $phone);
    	echo PHP_EOL;
    }


    Проверка
    Ответ написан
  • Как реализовать склонения слов после чисел в исходном коде php?

    vhood
    @vhood
    Не забывайте отмечать решения
    Не ломать голову и использовать готовый инструмент

    Пример из README (только на русском):
    echo Carbon::now()->subMinutes(2)->locale('ru_RU')->diffForHumans(); // '2 минуты назад'

    Документация настройки вариантов переводов здесь (можно с запятыми, можно словами без цифр и т.д.)
    Ответ написан
    Комментировать
  • Случайный вывод элементов на php?

    vhood
    @vhood
    Не забывайте отмечать решения
    Можно использовать массив с названиями подключаемых файлов и перемешивать его с помощью shuffle перед выводом.
    Выводить в цикле.
    $files = [
        'file-foo.php',
        'file.php',
        'file2.php',
        'file-bar.php',
        'file3.php',
    ];
    shuffle($files);
    
    foreach  ($files as $file) {
        include ($file);
    }


    Если файлов много, 10 файлов можно подключать, выбрав срез массива имен файлов
    foreach  (array_slice($files, 0, 10) as $file) {
        include ($file);
    }

    Однако операция shuffle для большого массива может быть затратной, по-этому вместо shuffle и array_slice можно воспользоваться array_rand
    - shuffle($files);
    
    - foreach  ($files as $file) {
    + foreach  (array_rand($files, 10) as $file) {
        include ($file);
    }
    Но array_rand не подойдет, если нужно сделать некую пагинацию (выводить первые 10 случайных файлов, затем следующие 10 других случайных файлов и в итоге вывести все файлы в случайном порядке, а затем поменять порядок и снова выводить по 10). Подход с array_slice позволит сделать такую пагинацию.
    Ответ написан
    2 комментария
  • Как локализовать дату регистрации пользователя wordpress?

    vhood
    @vhood
    Не забывайте отмечать решения
    $datetime = new DateTime($user_reg);
    + $formatter = new IntlDateFormatter('ru_RU');
    + $formatter->setPattern('d MMM, Y');
    
    - echo $datetime->format('F j, Y');
    + echo $formatter->format($datetime);


    Должен быть установлен модуль php-intl
    Ответ написан
    Комментировать
  • Вывод определенной информации на страницах с конкретными именами в адресе URL с помощью strpos?

    vhood
    @vhood
    Не забывайте отмечать решения
    Просто добавить логики в условие.

    В PHP 8 есть str_contains

    if (!str_contains($url, '/info/') && !str_contains($url, '/news/')) {
        echo 'вывод содержимого';
    } else {
        echo 'вывод содержимого';
    }
    Ответ написан
    1 комментарий
  • Функция str_replace() не работает?

    vhood
    @vhood
    Не забывайте отмечать решения
    html_entity_decode()

    https://onlinephp.io/c/9d203 (при работе с этой строкой, учтите, что в строке есть кавычка)
    Ответ написан
    4 комментария
  • Регулярное выражение поиск по группам или нет?

    vhood
    @vhood
    Не забывайте отмечать решения
    preg_match()
    $str = "$status['Совершенно_новое'] = 'Brand_new<br>New'";
    $pattern = "(?<=\$status\[')([а-яА-ЯёЁa-zA-Z]+?.*')([A-za-z]+?.*)(?=')";
    preg_match($patern, $str, $matches);
    
    var_dump($matches);
    // полный match и группы


    Паттерн получше: \$status\['([^']+)'\][^']*'([^']*)'
    https://regex101.com/r/10CLSM/1
    Ответ написан
  • Как подружить html с json?

    vhood
    @vhood
    Не забывайте отмечать решения
    HTML - язык разметки, никакие значения он не меняет
    Ответ написан
    Комментировать
  • Переписать грамотнее и с помощью Laravel реально ли и каким лучше образом?

    vhood
    @vhood
    Не забывайте отмечать решения
    Выводить HTML через echo точно не правильно, изначально PHP полюбили как раз за то, что можно закрыть PHP тег ?> и писать чистый HTML, можно посреди HTML открыть PHP тег <?php и воспользоваться языком, например вывести HTML в цикле (опять же, закрыв тег после начала цикла), или использовать переменную как значение, или выводить HTML по условию.

    В Laravel используется шаблонизатор Blade, но если есть ощущение, что Laravel изучать еще рано, можно через composer поставить какой-нибудь самостоятельный шаблонизатор (искать не сложно) и научиться пользоваться им.

    тут всякие визуальные уточнения страницы; форма, css специфика для страницы
    css стоит писать отдельно и подключать как файл/файлы, для формы будет отдельный шаблон

    тут всякие оперативные реакции на действия в браузере требуемые страницей.
    js тоже стоит писать отдельно и подключать как файл/файлы

    Работа с шаблонами - не самое востребованное знание, скорее очень базовое. Стоит так же изучить:
    • Архитектурный паттерн MVC (Model, View, Controller), т.к. его все популярные фреймворки реализуют и с ним так или иначе придется работать
    • Базы данных и SQL. Обязательно нужно уметь проектировать таблицы и индексы, забирать данные из базы и обновлять их
    • Безопасность, или как правильно писать приложения, что-бы их не взломали SQL инъекциями, XSS атаками и т.д.
    • Маршрутизацию. Можно попробовать найти какой-нибудь php-router на github и изучить работу с ним, внедрить в проект

    Таким образом, приложение будет обрабатывать запрос через некий роутер, посылать его в контроллер (буква C из MVC), контроллер запросит данные в какой-нибудь модели (M), отправит их в шаблон некого шаблонизатора и вернет с его помощью готовый HTML.

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

    Так же добавлю, что первую работу лично я нашел без знания фреймворков, но хорошее знание языка и баз данных, а так же знания HTML, CSS и базовые знания JS - обязательно. Да и без фронтенда динамичный сайт не сделать, но начать изучение фронтенда лучше всего с изучения чистого javascript, т.к. знание языка важнее и открывает правильную дорогу дальше. А вот на каком этапе изучения останавливаться и куда больше делать упор - решать Вам.
    Ответ написан
    1 комментарий
  • Как правильно сформировать запрос и вывести данные в цикле?

    vhood
    @vhood
    Не забывайте отмечать решения
    Если "в лоб":

    1. Убираем группировку, никаких подгрупп база не выдаст, будет по 1 записи на "уровень"
    - $ref_system = $pdo->prepare("SELECT * FROM `db_ref_system` GROUP BY `rs_type` ORDER BY `id` ASC");
    + $ref_system = $pdo->prepare("SELECT * FROM `db_ref_system` ORDER BY `id` ASC");


    2. Фильтруем итоговый вывод в 3 массива и выводим их
    <?php
    $all = $ref_system->fetchAll();
    $plc = array_filter($all, fn ($fields) => $fields['rs_type'] === 'plc');
    $deposit = array_filter($all, fn ($fields) => $fields['rs_type'] === 'deposit');
    $offer = array_filter($all, fn ($fields) => $fields['rs_type'] === 'offer');
    ?>
    <?php foreach ([$plc, $deposit, $offer] as $level => $data): ?>
      <div class="col-md-4 col-12 mb-lg-0 mb-4">
        <div class="fw-bold h5 mb-3">
          <?= $level + 1 ?>-й уровень
        </div>
        <?php foreach($data as $ref) : ?>
        <div class="mb-4">
          <span class="text-muted fw-semibold"><?=$ref['rs_type']?></span>
          <div>
            <div class="d-flex align-items-center pt-2">
              <div class="progress w-100">
                <div class="progress-bar bg-warning" role="progressbar" style="width: 100%;" aria-valuenow="100" aria-valuemin="0" aria-valuemax="100"></div>
              </div>
              <span class="ms-3 fw-bold text-warning"><?=$ref['rs_percent']?>%</span>
            </div>
          </div>
        </div>
        <?php endforeach; ?>
      </div>
    <?php endforeach; ?>
    Ответ написан
    5 комментариев
  • Как поулчить XML выгрузку на Битрикс с вложенными атрибутами?

    vhood
    @vhood
    Не забывайте отмечать решения
    Если это (ссылку взял из комментов в документации) и есть класс \Bitrix\Main\XmlWriter, то с его помощью - никак.

    Он пишет сразу в файл, так что и регуляркой итоговый результат не пройти.

    Можно залезть в него рефлексией, но в программировании это моветон и читабельность кода будет ухудшена.

    Самый оптимальный вариант - наследовать этот класс, изменить несколько его функций и использовать унаследованный класс. Примерно так:
    class AppXmlWriter extends XmlWriter
    {
        private $file = '';
        private $charset = '';
        private $tab = 0;
        private $f = null;
        private $lowercaseTag = false;
        private $errors = array();
    
        // конструктор скопирован, т.к. там все private
        public function __construct(array $params)
        {
            if (isset($params['file']))
            {
                $server = \Bitrix\Main\Application::getInstance()->getContext()->getServer();
                $this->file = $server->getDocumentRoot() . trim($params['file']);
                // create new file
                if (
                    isset($params['create_file']) &&
                    $params['create_file'] === true &&
                    is_writable($this->file)
                    )
                {
                    unlink($this->file);
                }
            }
            if (isset($params['charset']))
            {
                $this->charset = trim($params['charset']);
            }
            else
            {
                $this->charset = SITE_CHARSET;
            }
            if (isset($params['lowercase']) && $params['lowercase'] === true)
            {
                $this->lowercaseTag = true;
            }
            if (isset($params['tab']))
            {
                $this->tab = (int)$params['tab'];
            }
        }
    
        public function prepareAttributes(array $attributes): string
        {
            $result = '';
    
            if (empty($attributes)) {
                return $result;
            }
    
            foreach ($attributes as $key => $value) {
                $result .= sprintf(' %s="%s"', $key, $value);
            }
    
            return $result;
        }
    
        public function writeBeginTag($code, array $attributes = [])
        {
            if (!$this->f) {
                return;
            }
    
            fwrite($this->f, str_repeat("\t", $this->tab) . '<' . $this->prepareTag($code) . $this->prepareAttributes($attributes) . '>' . PHP_EOL);
            $this->tab++;
        }
    
        public function writeFullTag($code, $value, array $attributes = [])
        {
            if (!$this->f) {
                return;
            }
    
            $code = $this->prepareTag($code);
            $codeAttributes = $this->prepareAttributes($attributes);
            fwrite($this->f,
                str_repeat("\t", $this->tab) .
                (
                    trim($value) == ''
                    ? '<' . $code . $codeAttributes . ' />' . PHP_EOL
                    :   '<' . $code . $codeAttributes . '>' .
                    $this->prepareValue($value) .
                    '</' . $code . '>' . PHP_EOL
                )
            );
        }
    }
    Ответ написан
    1 комментарий
  • Как исправить синтаксическую ошибку в Битрикс?

    vhood
    @vhood
    Не забывайте отмечать решения
    Можно засунуть код в редактор, который подсвечивает синтаксис, и исправить там.

    Ошибок много, какие-то символы )"&gt; после span идут, href не назначен (переменная вызывается, в которой массив, а ключ массива отсутствует и php не закрывается).

    Вот, немного поправил именно тот участок, что предоставлен:
    <a href="<?=$arSection["SECTION_PAGE_UR"]?>" data-bx-app-ex-href="<?=$arSection["SECTION_PAGE_UR"]?>" class="section">
    			<div class="section__picture">
    				 <?
                                $picture = SITE_TEMPLATE_PATH.'/img/no_photo.png';
                                if ($arSection["PICTURE"] != ""){
                                    $picture = CFile::ResizeImageGet($arSection["PICTURE"], Array("height" => 175))["src"];
                                }
                                ?>
    				<div style="background-image:url('<span id=" title="Код PHP: &lt;?=$picture;?&gt;" class="bxhtmled-surrogate">
    					<span class="bxhtmled-surrogate-inner"><span class="bxhtmled-right-side-item-icon"></span><span class="bxhtmled-comp-lable" unselectable="on" spellcheck="false">Код PHP</span></span>
    				</div>
    				<div class="section__icon">
     <i class="far fa-sign-in"></i>
    				</div>
    			</div>
    			<div class="section__main">
    				 <?=$arSection["NAME"];?>
    			</div>
     </a>
    		</div>
    		 <?
                    if ($s > 5)
                        break;
                    $s++;?> <?endforeach;?>
    	</div>
    	 <?if (count($arSections) > 6):?>
    	<div class="button-line">
     <a href="/katalog/" class="button button_black wstyle wstyle_white">Посмотреть все категории</a>
    	</div>
    	 <?endif;?>
    </div>
     <?endif;?> <?
    $iblock_id = 4;
    $arServices = Array();
    $arFilterE = Array("IBLOCK_ID" => $iblock_id, "ACTIVE" => "Y");
    $arSelectE = Array("IBLOCK_ID", "ID", "NAME", "PREVIEW_PICTURE");
    $rsElement = CIBlockElement::GetList(
        Array("SORT"=>"ASC"),
        $arFilterE,
        false,
        false,
        $arSelectE
    );
    while($arElement = $rsElement->GetNextElement()){
        $arFieldsE = $arElement->GetFields();
        $arServices[] = $arFieldsE;
    }
    ?> <?if (count($arServices) > 0):?>
    <div class="block block_border">
    	<div class="title title_center">
    		Популярные услуги
    	</div>
    	<div class="row">
    		 <?$s = 1;?> <?foreach ($arServices as $arService):?>
    		<div class="col-lg-4">
     <a href="<?=$arService["DETAIL_PAGE_URL"]?>" data-bx-app-ex-href="<?=$arService["DETAIL_PAGE_URL"];?>" class="section section_wtitle">
    			<div class="section__picture">
    				 <?
                                $picture = SITE_TEMPLATE_PATH.'/img/no_photo.png';
                                if ($arService["PREVIEW_PICTURE"] != ""){
                                    $picture = CFile::ResizeImageGet($arService["PREVIEW_PICTURE"], Array("height" => 200))["src"];
                                }
                                ?>
    				<div style="background-image:url('<span id=" title="Код PHP: &lt;?=$picture;?&gt;" class="bxhtmled-surrogate">
    					<span class="bxhtmled-surrogate-inner"><span class="bxhtmled-right-side-item-icon"></span><span class="bxhtmled-comp-lable" unselectable="on" spellcheck="false">Код PHP</span></span>
    				</div>
    				<div class="section__title">
    					 <?=$arService["NAME"];?>
    				</div>
    			</div>
     </a>
    Ответ написан
    1 комментарий