laravel消息通知数据库频道中文转义问题

1. 运行环境

1). 当前使用的 Laravel 版本?

9.1
//: <> (使用 php artisan --version 命令查看)

2). 当前使用的 php/php-fpm 版本?

PHP 版本:
8.2.16
//: <> (使用 php --version 命令查看 php 版本)

php-fpm 版本:

3). 当前系统

windows 10

4). 业务环境

开发环境
//: <> (期待信息 开发环境生产环境)
//: <> (是否使用负载均衡?请提供相关信息)

5). 相关软件版本

2. 问题描述?

在laravel的消息通知中,通知类的toDatabase方法返回一个普通的PHP数组,将返回的数组转化为json数据存储在数据库中的过程似乎被laravel隐藏了,当我使用json_encode转化数据然后在toDatabase方法中尝试返回时,程序出错了,因为他不是规定返回的值(规定返回一个普通的php数组)。我希望中文字符可以不被转义而存储到数据库的notification表中,我应该怎么做?

3. 您期望得到的结果?

4. 您实际得到的结果?

《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
最佳答案

database作为渠道来发送通知时是将通知数据保存到数据库中,由于通知数据是array类型,所以保存数据时模型会json序列化来保持数据可以正常存储。如果需要修改序列化的参数那就需要需要重写modelasJson()方法。

由于默认的类是Illuminate\Notifications\DatabaseNotification位于框架代码中,而指定这个类的地方在trait Illuminate\Notifications\Notifiable

// 子trait Illuminate\Notifications\RoutesNotifications 里的 routeNotificationFor()
   /**
     * Get the notification routing information for the given driver.
     *
     * @param  string  $driver
     * @param  \Illuminate\Notifications\Notification|null  $notification
     * @return mixed
     */
    public function routeNotificationFor($driver, $notification = null)
    {
        if (method_exists($this, $method = 'routeNotificationFor'.Str::studly($driver))) {
            return $this->{$method}($notification);
        }

        return match ($driver) {
            'database' => $this->notifications(),
            'mail' => $this->email,
            default => null,
        };
    }

// Illuminate\Notifications\HasDatabaseNotifications 里 notifications() 的实现
    /**
     * Get the entity's notifications.
     *
     * @return \Illuminate\Database\Eloquent\Relations\MorphMany
     */
    public function notifications()
    {
        return $this->morphMany(DatabaseNotification::class, 'notifiable')->latest();
    }

所以我们可以通过实现使用了Notifiable的模型类的routeNotificationForDatabase() 方法来达到自定义通知模型的目的。

通常来说可以采用自建模型并继承DatabaseNotification 然后重写模型的asJson() 然后在routeNotificationForDatabase 中替换成自建的模型类即可。

1个月前 评论
lord_li (楼主) 1个月前
讨论数量: 12

@Summer 大佬能解答一下吗

1个月前 评论

消息通知《Laravel 10 中文文档》 为获取toDatabase返回结果 然后去存储? 它会自己存储的 $user->notifications 就可以获取到发送的消息

1个月前 评论
lord_li (楼主) 1个月前
Alone88 (作者) 1个月前
sanders

能请教一下为什么不想存取 unicode 编码吗?我理解除非需要对这个字段进行匹配查询,一般没有不转换的理由。

1个月前 评论
lord_li (楼主) 1个月前
lord_li (楼主) 1个月前

代码先 json_encode($arr,JSON_UNESCAPED_UNICODE) ?

1个月前 评论

database作为渠道来发送通知时是将通知数据保存到数据库中,由于通知数据是array类型,所以保存数据时模型会json序列化来保持数据可以正常存储。如果需要修改序列化的参数那就需要需要重写modelasJson()方法。

由于默认的类是Illuminate\Notifications\DatabaseNotification位于框架代码中,而指定这个类的地方在trait Illuminate\Notifications\Notifiable

// 子trait Illuminate\Notifications\RoutesNotifications 里的 routeNotificationFor()
   /**
     * Get the notification routing information for the given driver.
     *
     * @param  string  $driver
     * @param  \Illuminate\Notifications\Notification|null  $notification
     * @return mixed
     */
    public function routeNotificationFor($driver, $notification = null)
    {
        if (method_exists($this, $method = 'routeNotificationFor'.Str::studly($driver))) {
            return $this->{$method}($notification);
        }

        return match ($driver) {
            'database' => $this->notifications(),
            'mail' => $this->email,
            default => null,
        };
    }

// Illuminate\Notifications\HasDatabaseNotifications 里 notifications() 的实现
    /**
     * Get the entity's notifications.
     *
     * @return \Illuminate\Database\Eloquent\Relations\MorphMany
     */
    public function notifications()
    {
        return $this->morphMany(DatabaseNotification::class, 'notifiable')->latest();
    }

所以我们可以通过实现使用了Notifiable的模型类的routeNotificationForDatabase() 方法来达到自定义通知模型的目的。

通常来说可以采用自建模型并继承DatabaseNotification 然后重写模型的asJson() 然后在routeNotificationForDatabase 中替换成自建的模型类即可。

1个月前 评论
lord_li (楼主) 1个月前

试试

<?php

declare(strict_types=1);

namespace App\Providers;

use Illuminate\Database\Eloquent\Casts\Json;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     */
    public function register(): void
    {
        //
    }

    /**
     * Bootstrap any application services.
     */
    public function boot(): void
    {
        Json::encodeUsing(static fn (mixed $value): bool|string => json_encode(
            $value,
            JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_LINE_TERMINATORS
        ));
    }
}
1个月前 评论
lord_li (楼主) 1个月前

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!