【问题标题】:relatableQuery() for two resource fields on same model in Laravel Nova用于 Laravel Nova 中同一模型上的两个资源字段的 relatableQuery()
【发布时间】:2019-11-14 16:15:14
【问题描述】:

我在“工作日”和不同类型的项目之间建立了关系。所以我的“天数”记录两次引用了我的“项目”表,因为我有两种不同类型的项目,分别称为“系列”和“事件”。

在我的“days”资源中,我创建了两个字段:

BelongsTo::make('Series','series',Project::class)->sortable()->nullable(),
BelongsTo::make('Event','event',Project::class)->sortable()->nullable(),

我想做的是按项目类型过滤项目,所以我创建了这个:

public static function relatableProjects(NovaRequest $request, $query){
    return $query->where('type', 'Series');
}

我尝试过制作 relatableSeries 和 relatableEvents,但它们不起作用。我怎样才能使它正确连接到字段,而不必为“系列”和“事件”创建两个单独的表。

上面的 relatableQuery 最终过滤了两个资源字段。

【问题讨论】:

    标签: php laravel laravel-nova


    【解决方案1】:

    我知道这是一个老问题,但我在 laravel nova 所属领域面临同样的问题,在某些资源中,我有一个与用户相关的所属,但这些在另一个资源中应该是“主管”角色,我有一个所属领域与用户有关,但这些应该是角色“守卫”,因为 laravel nova 属于字段只需要所有用户都选择所有出现的用户,而且似乎 nova 属于字段没有办法,或者至少我没有找到它的范围查询,所以我所做的是创建一个名为 BelongstoScoped 的 php 类,这个类扩展了 laravel nova 字段 BelongsTo,所以我覆盖了负责创建查询的方法

    <?php
    
    namespace App\Nova\Customized;
    
    use Laravel\Nova\Query\Builder;
    use Laravel\Nova\Fields\BelongsTo;
    use Laravel\Nova\Http\Requests\NovaRequest;
    
    class BelongsToScoped extends BelongsTo
    {
    
        private  $modelScopes = [];
    
        //original function in laravel belongsto field
        public function buildAssociatableQuery(NovaRequest $request, $withTrashed = false)
        {
            $model = forward_static_call(
                [$resourceClass = $this->resourceClass, 'newModel']
            );
    
            $query = new Builder($resourceClass);
            
            //here i chaned this:
            /*
            $query->search(
                                    $request,  $model->newQuery(), $request->search,
                                    [], [], ''
                              );
            */
            //To this:
            /*
            $query->search(
                                    $request,  $this->addScopesToQuery($model->newQuery()), $request->search,
                                    [], [], ''
                              );
            */
            //The method search receives a query builder as second parameter, i just passed the result of custom function 
            //addScopesToQuery as second parameter, thi method returns the same query but with the model scopes passed
    
            $request->first === 'true'
                            ? $query->whereKey($model->newQueryWithoutScopes(), $request->current)
                            : $query->search(
                                    $request,  $this->addScopesToQuery($model->newQuery()), $request->search,
                                    [], [], ''
                              );
    
            return $query->tap(function ($query) use ($request, $model) {
                forward_static_call($this->associatableQueryCallable($request, $model), $request, $query, $this);
            });
        }
    
        //this method reads the property $modelScopes and adds them to the query
        private function addScopesToQuery($query){
            foreach($this->modelScopes as $scope){
                $query->$scope();
            }
            return $query;
        }
    
        // this method should be chained tho the field 
        //example: BelongsToScoped::make('Supervisores', 'supervisor', 'App\Nova\Users')->scopes(['supervisor', 'active'])
        public function scopes(Array $modelScopes){
    
            $this->modelScopes = $modelScopes;
            return $this;
    
        }
    
    }
    
    ?>
    

    在我的用户模型中,我有这样的主管和警卫角色的范围:

    public function scopeActive($query)
        {
            return $query->where('state', 1);
        }
    
        public function scopeSupervisor($query)
        {
            return $query->role('supervisor');
        }
    
        public function scopeSuperadmin($query)
        {
            return $query->role('superadmin');
        }
    
        public function scopeGuarda($query)
        {
            return $query->role('guarda');
        }
    

    所以在 laravel nova 资源中我只包含了这个类的使用 *记住命名空间取决于你如何命名你的文件,在我的例子中,我创建了自定义文件夹并将文件包含在其中:

    use App\Nova\Customized\BelongsToScoped;
    

    在 nova 资源的字段中我是这样使用的:

    BelongsToScoped::make('Supervisor', 'supervisorUser', 'App\Nova\Users\User')
                                ->scopes(['supervisor', 'active'])
                                ->searchable()
    

    这样我就可以调用nova资源中的belongsto字段,根据模型范围过滤用户。

    我希望这对某人有所帮助,如果我的英语不是那么好,请见谅。

    【讨论】:

      【解决方案2】:

      因为 relatableQuery() 引用了一个 relatableModel()(所以 relatableProjects() 引用了 Project 模型)我能够创建另一个模型只是为了帮助解决这个问题。

      我创建了一个引用同一个 projects 表的事件模型,然后能够创建一个 relatableEvents() 方法来使用 where() 过滤器查询。

      注意:我还必须创建一个引用 Event 模型的 Event 资源,因为这是 Nova 的工作方式,但能够隐藏它以防止被访问,您可以找到有关 @987654321 的更多信息@

      请参阅以下修订后的 BelongsTo 字段和新模型:

      日资源

          /**
           * Build a "relatable" query for the given resource.
           *
           * This query determines which instances of the model may be attached to other resources.
           *
           * @param  \Laravel\Nova\Http\Requests\NovaRequest  $request
           * @param  \Illuminate\Database\Eloquent\Builder  $query
           * @return \Illuminate\Database\Eloquent\Builder
           */
          public static function relatableProjects(NovaRequest $request, $query){
              return $query->where('type', 'Series');
          }
      
          /**
           * Build a "relatable" query for the given resource.
           *
           * This query determines which instances of the model may be attached to other resources.
           *
           * @param  \Laravel\Nova\Http\Requests\NovaRequest  $request
           * @param  \Illuminate\Database\Eloquent\Builder  $query
           * @return \Illuminate\Database\Eloquent\Builder
           */
          public static function relatableEvents(NovaRequest $request, $query){
              return $query->where('type', 'Event');
          }
      
          /**
           * Get the fields displayed by the resource.
           *
           * @param  \Illuminate\Http\Request  $request
           * @return array
           */
          public function fields(Request $request)
          {
              return [
                  ID::make()->hideFromIndex()->hideFromDetail()->hideWhenUpdating(),
                  BelongsTo::make('User','user',User::class)->sortable(),
                  BelongsTo::make('Budget','budget',Budget::class)->sortable()->nullable(),
                  BelongsTo::make('Series','series',Project::class)->sortable()->nullable(),
                  BelongsTo::make('Event','event',Event::class)->sortable()->nullable(),
                  DateTime::make('Last Updated','updated_at')->hideFromIndex()->readOnly(),
                  new Panel('Schedule',$this->schedule()),
                  new Panel('Time Entry',$this->timeEntries()),
      
              ];
          }
      

      事件模型

      <?php
      
      namespace App;
      
      use Illuminate\Database\Eloquent\Model;
      
      class Event extends Model
      {
          /**
           * The table associated with the model.
           *
           * @var string
           */
          protected $table = 'projects';
      
          protected $casts = [
              'starts_on' => 'date',
              'ends_on' => 'date',
          ];
      
          public function event(){
              return $this->belongsTo('App\Event');
          }
      
          public function project(){
              return $this->belongsTo('App\Project');
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2021-09-20
        • 1970-01-01
        • 2019-12-08
        • 1970-01-01
        • 2019-05-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多