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

    nokimaro
    @nokimaro
    Меня невозможно остановить, если я смогу начать.
    Делается одним проходом в цикле
    Ключем выставляем поле по которому делать группировку и внутрь уже ложим нужные данные
    В конце array_values() чтобы переиндексировать результат и сбросить ключи

    https://3v4l.org/mZQIN#v8.3.14

    <?php
    error_reporting(-1);
    ini_set('display_errors', 1);
    
    $json_data = <<<JSON
    {"messages": [
    	{
    		"id": 1,
    		"customer": "Dr. Kane Hill",
    		"customer_id": 1,
    		"created_at": "2024-11-19 11:18:57",
    		"text": "Hello, how are you?"
    	},
    	{
    		"id": 2,
    		"customer": "Dr. Kane Hill",
    		"customer_id": 1,
    		"created_at": "2024-11-19 11:20:57",
    		"text": "I am good, thanks! How about you?"
    	},
    	{
    		"id": 3,
    		"customer": "Prof. Samir McClure III",
    		"customer_id": 2,
    		"created_at": "2024-11-19 11:21:57",
    		"text": "Hey, what time is it?"
    	},
    	{
    		"id": 4,
    		"customer": "Prof. Samir McClure III",
    		"customer_id": 2,
    		"created_at": "2024-11-19 11:22:57",
    		"text": "It is 3 PM."
    	},
    	{
    		"id": 5,
    		"customer": "Shad Leffler",
    		"customer_id": 3,
    		"created_at": "2024-11-19 11:23:57",
    		"text": "Did you finish the project?"
    	},
    	{
    		"id": 6,
    		"customer": "Shad Leffler",
    		"customer_id": 3,
    		"created_at": "2024-11-19 11:24:57",
    		"text": "New mesh"
    	},
    	{
    		"id": 7,
    		"customer": "Prof. Samir McClure III",
    		"customer_id": 2,
    		"created_at": "2024-11-19 11:26:57",
    		"text": "Not bed?"
    	},
    	{
    		"id": 8,
    		"customer": "Prof. Samir McClure III",
    		"customer_id": 2,
    		"created_at": "2024-11-19 11:27:57",
    		"text": "Cool?"
    	}
    ]}
    JSON;
    
    $messages = json_decode($json_data, true)['messages'];
    
    $messages2 = [];
    $messageCounter = 0;
    foreach($messages as $row) {
        
        $key = $row['customer_id'];
        
        if(!isset($messages2[$key])) {
            $messages2[$key] = [
                'customer' => $row['customer'],
                'message_id' => (++$messageCounter),
                'customer_id' => $row['customer_id'],
                'messages' => [],
            ];
        }
    
        
        $messages2[$key]['messages'][] = [
            'id' => $row['id'],
            'created_at' => $row['created_at'],
            'text' => $row['text'],
        ];
    }
    
    $messages2 = array_values($messages2);
    
    echo json_encode($messages2, JSON_PRETTY_PRINT);


    upd: подправил ответ, так как по всей видимости message_id в сгруппированном результате должен быть счётчиком
    upd2: по совету. Adamos обновил ответ убрав не нужные присваивания при каждом проходе цикла
    Ответ написан
  • Как выявить символы не поддерживаемые кодировкой?

    nokimaro
    @nokimaro
    Меня невозможно остановить, если я смогу начать.
    Двойной конверт через iconv() нормальный и "не дорогой" вариант utf8 -> koi8r -> utf8
    Можно используйте флаги типа //TRANSLIT или //IGNORE
    Соотв-но если изначальный utf8 не равен итоговому utf8 значит в исходной строке были символы вне кодовой таблицы koi8r

    Так же можно попробовать часто-используемые символы типа символа рубля закодировать в &#8381; или &#x20BD;. Естественно если при отображении данных делается escaping для html (html_entity_encode / htmlspecialchars) это надо будет учесть чтобы & не превратился в &amp;
    Ответ написан
    7 комментариев
  • Как сжать изображение PNG без изменение типа MIME?

    nokimaro
    @nokimaro
    Меня невозможно остановить, если я смогу начать.
    Можно "сжать" png
    Для этого понадобятся спец. утилиты из категории "png optimizer", одним GD тут не обойтись.
    https://habr.com/ru/articles/63528/

    https://github.com/imagemin/pngout-bin
    https://pngquant.org/
    https://github.com/funbox/optimizt
    и аналоги

    то что png можно "сжать" практически без визуальных потерь можете проверить онлайн на сервисе https://tinypng.com/
    Ответ написан
    Комментировать
  • Ошибка при попытке редиректа CORS?

    nokimaro
    @nokimaro
    Меня невозможно остановить, если я смогу начать.
    Внутри pay.php вместо header location возвращайте json-ответ

    echo json_encode(['url' => $response['confirmation']['confirmation_url']]);
    exit;


    Соотв-но через fetch получаете в ответе json-объект от php, декодируете его, находите нужный url и делаете редирект средствами браузера например через window.location
    Ответ написан
    Комментировать
  • Как более оптимизированно подгружать посты через кнопку "показать еще"?

    nokimaro
    @nokimaro
    Меня невозможно остановить, если я смогу начать.
    Второй вариант.
    Для оптимизации скорости пагинации можете изучить тему "пагинация с курсором" (php cursor pagination)
    У вас же нет проблем когда листаете ленту в ВК, всё упирается в скорость сети пользователя.
    Ответ написан
    Комментировать
  • Почему появляется Typed property must not be accessed before initialization?

    nokimaro
    @nokimaro
    Меня невозможно остановить, если я смогу начать.
    Используйте Constructor property promotion чтобы писать меньше букв)
    <?php
    
    class Product
    {
        public function __construct(
            public int $id,
            public ?int $parentId = null
        ) {
        }
    
        public function getParentId(): ?int
        {
            return $this->parentId;
        }
    
    }
    
    $obj = new Product(1);
    if (!empty($obj->getParentId())) {
        echo 'ok';
    }


    Либо уберите типизацию у свойства и при public $parentId; ошибки не будет. Всё как и написано в тексте ошибки, нельзя обратиться к типизированному свойству до его инициализации, а значит нужно либо задать значение по умолчанию при описании свойства, либо через конструктор, либо вызвав setter.

    uninitialized и typed properties
    https://php.watch/versions/7.4/typed-properties#un...
    Ответ написан
    Комментировать
  • В чем причина ошибки fwrite(): Write of 526 bytes failed with errno=32 Broken pipe?

    nokimaro
    @nokimaro
    Меня невозможно остановить, если я смогу начать.
    А как апгрейдились?
    По хорошему при таком апгрейде надо по шагам проходить и в первую очередь обращать на то что помечено как "impact high" или "breaking change"
    5 -> 6 https://laravel.com/docs/6.x/upgrade
    6 -> 7 https://laravel.com/docs/7.x/upgrade
    7 -> 8 https://laravel.com/docs/8.x/upgrade
    8 -> 9 https://laravel.com/docs/9.x/upgrade

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

    Возьмите актуальный `config/logging.php` из чистой установки Laravel 9 и сравните со своим. В том числе посмотрите каких ключей может не хватать по дефолту в .env
    Ответ написан
  • Присвоить значение массива переменной?

    nokimaro
    @nokimaro
    Меня невозможно остановить, если я смогу начать.
    На лицо "проблема XY"

    <?php
    $input = [
        '28.06.2024' => ['Петров Петр Петрович', 'Петров Петр Петрович'],
        '03.07.2024' => ['Петров Петр Петрович', 'Иванов Иван Иванович', 'Петров Петр Петрович', 'Иванов Иван Иванович'],
        '02.07.2024' => ['Петров Петр Петрович', 'Иванов Иван Иванович'],
        '01.07.2024' => ['Иванов Иван Иванович', 'Петров Петр Петрович', 'Иванов Иван Иванович'],
        '26.06.2024' => ['Петров Петр Петрович', 'Петров Петр Петрович'],
        '04.07.2024' => ['Иванов Иван Иванович']
    ];
    
    $names = [];
    foreach($input as $rows) {
        foreach($rows as $name) {
            $names[$name] = $name;
        }
    }
    
    $names = array_values($names);
    
    var_dump($names[0]);
    
    var_dump($names[1]);
    Ответ написан
    1 комментарий
  • Как наложить текст прихожей с сервера на изображение?

    nokimaro
    @nokimaro
    Меня невозможно остановить, если я смогу начать.
    Для работы с изображениями нужно расширение (extension). Это или php-gd или php-imagick (gmagick)
    И рекомендую обертку чтобы не писать всю логику работы с расширением самому - https://image.intervention.io/v3/modifying/text-fonts
    Эта библиотека предоставляет универсальный api для работы с изображениями используя GD Library или Imagick.
    Там вам и ресайз, обрезка, транфсформация, наложение картинок и работа с текстом
    Ответ написан
    Комментировать
  • При использовании ftruncate после сохранения файла fwrite появляются много NULL в начале строки, что сделать чтобы их там не было?

    nokimaro
    @nokimaro
    Меня невозможно остановить, если я смогу начать.
    <?php
    $pathUrl = dirname(__DIR__, 1) . "/orders/";
    $filename = 'listOrderFiles.txt';
    $lines = [];
    
    //считываем все строки файла в массив
    $handle = fopen($pathUrl . $filename, "r");
    while (($line = fgets($handle)) !== false) {
        $lines[] = $line;
    }
    fclose($handle);
    
    //удаляем первую строку
    unset($lines[0]);
    
    //записываем всё оставшееся в файл
    $handle = fopen($pathUrl . $filename, "w");
    foreach($lines as $line) {
        fwrite($handle, $line);
    }
    fclose($handle);
    Ответ написан
    Комментировать
  • Как реализовать склонения слов после чисел в исходном коде php?

    nokimaro
    @nokimaro
    Меня невозможно остановить, если я смогу начать.
    Нужно добавить варианты склонения
    Для русского языка это обычно по три варианта которые формируются по правилу "один ___", "два ___", "много (пять) ___"
    один день
    два дня
    много дней

    <?php
    function time_elapsed_string($datetime, $full = false) {
        $now = new DateTime;
        $ago = new DateTime($datetime);
        $diff = $now->diff($ago);
    
        $diff->w = floor($diff->d / 7);
        $diff->d -= $diff->w * 7;
    
        //один ___, два ___, много ___
        $string = array(
            'y' => ['год', 'года', 'лет'],
            'm' => ['месяц', 'месяца', 'месяцев'],
            'w' => ['неделя', 'недели', 'недель'],
            'd' => ['день', 'дня', 'дней'],
            'h' => ['час', 'часа', 'часов'],
            'i' => ['минута', 'минуты', 'минут'],
            's' => ['секунда', 'секунды', 'секунд'],
        );
        foreach ($string as $k => &$v) {
            if ($diff->$k) {
                $v = $diff->$k . ' ' . pluralize($diff->$k, $v);
            } else {
                unset($string[$k]);
            }
        }
    
        if (!$full) $string = array_slice($string, 0, 1);
        return $string ? implode(', ', $string) . ' назад' : 'только что';
    }
    
    function pluralize($n, array $forms) 
    {
        return 
        $n%10==1 && $n%100!=11
         ? $forms[0] :
         ( $n%10>=2 && $n%10<=4 && ($n%100<10 || $n%100>=20)
            ?$forms[1] : $forms[2]
        );
    }
    
    ?>
    <?php echo time_elapsed_string('2019-04-22 00:22:35'); ?>
    Ответ написан
    2 комментария
  • Почему неправильно работает авторизация через jwt токен?

    nokimaro
    @nokimaro
    Меня невозможно остановить, если я смогу начать.
    $token = htmlspecialchars(isset($_POST['token']));
    $message = htmlspecialchars(isset($_POST['message']));
    $subtopic_id = intval(isset($_POST['subtopic_id']));

    превращают переданные значения в string/int "1" или "0" так как результат isset() - bool

    корректный вариант скорее всего такой
    <?php
    $token = htmlspecialchars($_POST['token'] ?? '');
    $message = htmlspecialchars($_POST['message'] ?? '');
    $subtopic_id = intval($_POST['subtopic_id'] ?? 0);


    чтобы понять где ошибка достаточно было посмотреть значение $token которое попадает в JWT::decode и там бы увидели "1" вместо переданного токена.
    Ответ написан
    7 комментариев
  • Как в symfony распространить сессию и cookie на все поддомены?

    nokimaro
    @nokimaro
    Меня невозможно остановить, если я смогу начать.
    # config/packages/framework.yaml

    framework:
      session:
        cookie_domain: .my-domain.com

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

    nokimaro
    @nokimaro
    Меня невозможно остановить, если я смогу начать.
    Да, логика правильная. То есть надо переписать код так чтобы отлавливать ошибку с потерей соединения с базой, например в момент неудачного выполнения запроса, переподключаться и повторять запрос.

    Если процедурный код обернуть в простейший класс то сделать всё это будет гораздо проще.
    goto и global рекомендую избегать. Всё что можно сделать с ними - можно сделать и без них.
    Ответ написан
    4 комментария
  • Не работает часть скрипта PHP при смены PHP 7 на 8?

    nokimaro
    @nokimaro
    Меня невозможно остановить, если я смогу начать.
    надо переписывать код и выкидывать mysql_result, mysql_query, mysql_fetch_assoc, mysql_num_rows
    https://www.php.net/manual/en/function.mysql-query.php

    Warning
    This extension was deprecated in PHP 5.5.0, and it was removed in PHP 7.0.0. Instead, the MySQLi or PDO_MySQL extension should be used. See also MySQL: choosing an API guide. Alternatives to this function include:


    меняйте на mysqli или pdo
    Ответ написан
    Комментировать
  • Заполнить не существующими датами из бд в графике apexcharts?

    nokimaro
    @nokimaro
    Меня невозможно остановить, если я смогу начать.
    На SQL можно использовать CTE и конкретно WITH RECURSIVE чтобы сперва сгенерировать интервалы дат с любым шагом и потом сделать JOIN и агрегацию интересующих данных
    Возможны проблемы с производительностью запроса при отсутствии правильных индексов.

    https://dev.mysql.com/doc/refman/8.0/en/with.html
    with recursive cte as (
        select 
            '2024-04-16' dt, 
            '2024-05-16' end_dt
        union all
        select dt + interval 1 day, end_dt from cte where dt < end_dt
    )
    select c.dt, count(t.id)
    from cte c
    left join sells t on DATE(t.datetime) = c.dt
    group by c.dt
    Ответ написан
    Комментировать
  • Ошибка call to member function takeUrl() on null ( October CMS) Как сделать проверку на пустой URL?

    nokimaro
    @nokimaro
    Меня невозможно остановить, если я смогу начать.
    $full_category_slug = $this->category?->takeUrl($pageName, $controller);

    а по факту ошибка говорит о том что $this->category пустая (null)
    Ответ написан
  • Кто-нибудь знает как отправлять медиагруппу файлов через Telegram API?

    nokimaro
    @nokimaro
    Меня невозможно остановить, если я смогу начать.
    А доку посмотреть от тг?
    https://core.telegram.org/bots/api#sendmediagroup

    media	Array of InputMediaAudio, InputMediaDocument, InputMediaPhoto and InputMediaVideo


    То есть вам надо передать массив объектов вида InputMediaXxxxx - https://github.com/php-telegram-bot/core/tree/deve...

    Если ещё более конкретно то в коде есть примеры
    https://github.com/php-telegram-bot/core/blob/57a6...
    * Request::sendMediaGroup([
         *     'media'   => [
         *         new InputMediaPhoto(['media' => Request::encodeFile($local_photo_1)]),
         *         new InputMediaPhoto(['media' => Request::encodeFile($local_photo_2)]),
         *         new InputMediaVideo(['media' => Request::encodeFile($local_video_1)]),
         *     ],
         * ]);
         * and even
         * Request::sendMediaGroup([
         *     'media'   => [
         *         new InputMediaPhoto(['media' => $local_photo_1]),
         *         new InputMediaPhoto(['media' => $local_photo_2]),
         *         new InputMediaVideo(['media' => $local_video_1]),
         *     ],
         * ]);
    Ответ написан
    Комментировать
  • Как используя preg_match распарсить html?

    nokimaro
    @nokimaro
    Меня невозможно остановить, если я смогу начать.
    Вариант решения через DOMDocument + DOMXpath

    <?php
    $html = '<select name="appointments[consulate_appointment][facility_id]" id="appointments_consulate_appointment_facility_id" class="required"><option value="" label=" "></option>
    <option data-collects-biometrics="false" value="89">Calgary</option>
    <option data-collects-biometrics="false" value="90">Halifax</option>
    <option data-collects-biometrics="false" value="91">Montreal</option>
    <option data-collects-biometrics="false" value="92">Ottawa</option>
    <option data-collects-biometrics="false" value="93">Quebec City</option>
    <option data-collects-biometrics="false" value="94">Toronto</option>
    <option data-collects-biometrics="false" selected="selected" value="95">Vancouver</option></select>';
    
    $dom = new DOMDocument();
    $dom->loadHTML($html);
    
    $xpath = new DOMXpath($dom);
    $result = $xpath->query("//select/option[@selected='selected']");
    $value = $result->item(0)->getAttribute('value');
    
    var_dump($value); //string(2) "95"
    Ответ написан
    Комментировать