Laravel 10 morph许多不检索应报告的模型

Laravel 10 morphMany not retrieving notifiable models

提问人:Ryan H 提问时间:11/8/2023 更新时间:11/17/2023 访问量:140

问:

我需要一些关于我的关系的帮助。我正在构建一项功能,允许用户通过不同的通知渠道获取各种类型的通知。这是我的模型:morphMany

  • NotificationNotifiable- 这定义了 IDnotifiable_typenotifiable_idnotification_type_id 列,这是跟踪用户已启用并希望接收通知的所有类型的表。
  • NotificationChannel- 只是一个简单的表格来定义渠道,例如:推送、电子邮件、短信
  • NotificationType- 用于定义通知类型及其相应的支持notification_channel_id列的表格,也许通过电子邮件进行一般营销是一种类型。

我已经选择了,因为我可能还有其他模特也希望收到通知。NotificationNotifiable

我能够从我的控制器(通知首选项)中检索数据,但是尽管有用户的条目,但我在我的关系下没有看到它,它是空的,这是我的模型:notificationNotifiable

  1. 型:NotificationNotifiable
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\MorphTo;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

class NotificationNotifiable extends Model
{
    use HasFactory;

    /**
     * The table associated with the model.
     *
     * @var string
     */
    protected $table = 'notification_notifiables';

    /**
     * The attributes that aren't mass assignable.
     *
     * @var array
     */
    protected $guarded = [
        'id'
    ];

    /**
     * Get the parent notifiable model.
     */
    public function notifiable(): MorphTo
    {
        return $this->morphTo();
    }

    /**
     * Get the notification type for this model.
     */
    public function notificationType(): BelongsTo
    {
        return $this->belongsTo(NotificationType::class);
    }
}
  1. 型:NotificationChannel
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;

class NotificationChannel extends Model
{
    use HasFactory;

    /**
     * The table associated with the model.
     *
     * @var string
     */
    protected $table = 'notification_channels';

    /**
     * The attributes that should be cast.
     *
     * @var array
     */
    protected $casts = [
        'display_order' => 'integer',
        'requires_subscription' => 'boolean',
        'is_popular' => 'boolean',
        'is_recommended' => 'boolean',
        'is_enabled' => 'boolean',
    ];

    /**
     * Get the notification types for this model.
     */
    public function notificationTypes(): HasMany
    {
        return $this->hasMany(NotificationType::class);
    }
}
  1. 型:NotificationType
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\MorphMany;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;

class NotificationType extends Model
{
    use HasFactory;

    /**
     * The table associated with the model.
     *
     * @var string
     */
    protected $table = 'notification_types';

    /**
     * The attributes that should be cast.
     *
     * @var array
     */
    protected $casts = [
        'display_order' => 'integer',
    ];

    /**
     * The accessors to append to the model's array form.
     *
     * @var array
     */
    protected $appends = [
        'has_notifiables'
    ];

    /**
     * Determine whether the notification type has notifiables
     */
    public function getHasNotifiablesAttribute(): bool
    {
        if (isset($this->notificationNotifiables) && count($this->notificationNotifiables) > 0) {
            return true;
        }

        return false;
    }

    /**
     * Get the notification channels for this model
     */
    public function notificationChannels(): BelongsTo
    {
        return $this->belongsTo(NotificationChannel::class, 'notification_channel_id');
    }

    /**
     * Get the model's notifiables
     */
    public function notificationNotifiables(): MorphMany
    {
        return $this->morphMany(NotificationNotifiable::class, 'notifiable');
    }
}

这是我的端点索引函数:/account/1/notification-preferences

/**
 * Display a listing of the resource.
 */
public function index(User $account, Request $request)
{
    try {
        $channels = NotificationChannel::withWhereHas('notificationTypes', function ($query) {
            $query->with([
                'notificationNotifiables' => function ($query) {
                    $query->where('notifiable_type', User::class)->where('notifiable_id', Auth::id());
                }
            ])->orderBy('display_order', 'asc');
        })->orderBy('display_order', 'asc')->get();

        if (! $channels || count($channels) <= 0) {
            return new ApiSuccessResponse(null, [
                'message' => 'No channels found.',
            ], 404);
        }

        return new ApiSuccessResponse($channels);
    } catch (\Exception $e) {
        return new ApiErrorResponse($e, [
            'message' => 'Unable to load channels, please try again soon.',
        ]);
    }
}

尽管此表中有一个条目,但为什么会为空?notificationNotifiables

notifiables database

empty relationship

php mysql laravel 雄辩

评论

0赞 Adi 11/12/2023
几个澄清,是否包含所需的?也可以有多个 for 和(如果没有,请考虑重命名它以提高可读性,删除复数)?最后,您是否尝试使用而不是?Auth::id()idNotificationTypenotificationChannelsnotificationNotifiableswithwithWhereHas
0赞 Ryan H 11/14/2023
切换到 ,谢谢。hasMany
0赞 Peter Mortensen 11/21/2023
赏金吸引了至少一名 ChatGPT 抄袭者。

答:

-6赞 Théodore 11/17/2023 #1

看起来该问题可能与查询中关系的急切加载有关。具体而言,withWhereHas 方法可能无法正确加载嵌套关系。此外,在 NotificationType 模型中,你将 belongsTo 用于 notificationChannels,但它应该是 hasMany,因为 NotificationType 可以有多个通道。

下面是使用 with 方法进行预先加载的索引函数的更新版本:

/**
 * Display a listing of the resource.
 */
public function index(User $account, Request $request)
{
    try {
        $channels = NotificationChannel::with(['notificationTypes.notificationNotifiables' => function ($query) use ($account) {
            $query->where('notifiable_type', User::class)->where('notifiable_id', $account->id);
        }])
            ->orderBy('display_order', 'asc')
            ->get();

        if (!$channels || $channels->isEmpty()) {
            return new ApiSuccessResponse(null, [
                'message' => 'No channels found.',
            ], 404);
        }

        return new ApiSuccessResponse($channels);
    } catch (\Exception $e) {
        return new ApiErrorResponse($e, [
            'message' => 'Unable to load channels, please try again soon.',
        ]);
    }
}

评论

3赞 Jesse 11/17/2023
stackoverflow.com/help/ai-policy
1赞 EJoshuaS - Stand with Ukraine 11/22/2023
这似乎是 ChatGPT 抄袭。