• Как трансформировать массив?

    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 комментариев
  • Есть ли неофициальный телеграм клиент, имитирующий официальный мобильный клиент?

    nokimaro
    @nokimaro
    Меня невозможно остановить, если я смогу начать.
    Исходный код всех официальных клиентов telegram выложен в открытый доступ
    https://telegram.org/apps
    Ответ написан
  • Как сжать изображение 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.
    Там вам и ресайз, обрезка, транфсформация, наложение картинок и работа с текстом
    Ответ написан
    Комментировать
  • Откуда появляется обложка в MP3-файле?

    nokimaro
    @nokimaro
    Меня невозможно остановить, если я смогу начать.
    Конкретно в tg обложка приходит с серверов tg как мета-информация о загруженном файле
    https://core.telegram.org/api/files#downloading-we...
    ищите на странице "cover"

    То есть после того как вы залили файл на сервера tg он проходит обработку и сервер для файла находит обложку. Через какой сервис делается поиск обложки для mp3 - неизвестно.
    Раньше десктопный тг-клиент делал это втупую используя iTunes Search API, теперь tg-сервер делает поиск обложки после загрузки mp3 и отдаёт это как мета-информацию в клиент. Естественно оригинальный файл никак не изменяется и обложка внутрь файла не пишется.
    Если в загруженном mp3 есть файл с обложкой в id3-тегах то будет использоваться он. Поэтому если не устраивает обложка которую находит ТГ - зашейте нужную картинку через id3-теги.

    сам автор песни был в шоке от содержимого

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

    nokimaro
    @nokimaro
    Меня невозможно остановить, если я смогу начать.
    Если максимально надёжно, то сперва надо попросить войти пользователя через twitter на сайте (twitter oauth)
    По сути это позволит привязать twitter аккаунт к аккаунут в вашей системе для которого рисуете кнопку
    После этого уже проверят комментарии под постом, и если видете коммент от twitter пользователя связанного с учёткой пользователя - то для этого пользователя кнопку больше не показываем, так как на 100% знаем что он через свой twitter аккаунт оставил коммент.
    Ответ написан
    Комментировать
  • Как одновременно отобразить страницу, выдать файл и удалить его после?

    nokimaro
    @nokimaro
    Меня невозможно остановить, если я смогу начать.
    так как вы используете Response-фасад то есть встроенный метод

    response()
    ->download($pathToFile, $name, $headers)
    ->deleteFileAfterSend(true); //<--

    https://dev.to/codeanddeploy/how-to-delete-files-a...

    Альтернативные варианты
    Terminable Middleware позволит выполнить любой код перед завершением работы скрипта (уже после того как был отдан Response), туда можно разместить код удаления файла. Под капотом используется fastcgi_finish_request()

    или Job::dispatchAfterResponse()
    https://divinglaravel.com/running-a-task-after-the...
    Ответ написан
    5 комментариев
  • Как правильно создать класс в laravel-data?

    nokimaro
    @nokimaro
    Меня невозможно остановить, если я смогу начать.
    #[DataCollectionOf(ProductData::class)]
    public array $products
    Ответ написан
  • При использовании 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
    Меня невозможно остановить, если я смогу начать.
    Автоматически синхронизировать - репликация
    https://dev.mysql.com/doc/refman/8.0/en/replicatio...

    В вашем случае так как запись может быть сделана в любую из баз, и они должны быть в синхроне то нужна master-master репликация. Читайте информацию по теме "mysql master master replication".
    Из минусов - запросы на запись (update, insert, delete) будут работать чуть дольше так как придётся дожидаться синхронизации данных. Из плюсов - всё будет работать из коробки как только настроите репликацию, и всё что записано в одну базу сразу же будет доступно в другой и наоборот.
    Ответ написан
    4 комментария