Voyager自定义控制器提示Trying to get property 'model_name' of non-object报错求助
问题根因
你遇到的报错是因为执行Voyager::model('DataType')->where('slug', '=', $slug)->first()时返回了null,所以访问$dataType->model_name会抛出属性不存在的错误,触发的原因通常有两个:
- 路由调用控制器时没有传入和BREAD匹配的slug参数
- 你没有在Voyager后台为
SubOrder模型创建对应的BREAD配置
解决方案
方案1:修复现有继承VoyagerBaseController的逻辑
按照以下步骤操作即可解决:
- 登录Voyager后台,进入工具 > BREAD页面,给你的
SubOrder模型创建BREAD配置,设置slug为你想要的值(比如sub-orders),保存配置 - 修改路由定义,给控制器传入对应slug参数,示例代码:
Route::get('/seller/orders', [\App\Http\Controllers\Admin\OrderController::class, 'index']) ->defaults('slug', 'sub-orders');
注意这里的slug值必须和你第一步创建BREAD时填写的slug完全一致
- 进入Voyager后台的角色管理页面,给对应的用户角色(比如你代码里的
pedagang角色)分配该BREAD的浏览权限
方案2:无需创建BREAD,直接复用Voyager布局(更灵活)
如果你不想受Voyager BREAD的逻辑限制,可以直接继承Voyager的母模板实现风格统一,不需要继承VoyagerBaseController,操作更简单:
- 修改控制器,去掉继承
VoyagerBaseController,直接继承默认的Controller,删掉原有和DataType、权限校验相关的Voyager原生逻辑,只保留你自己的业务查询代码,示例简化后的控制器:
<?php namespace App\Http\Controllers\Admin; use App\Models\Toko; use App\Models\SubOrder; use Illuminate\Http\Request; use App\Http\Controllers\Controller; use RealRashid\SweetAlert\Facades\Alert; class OrderController extends Controller { public function index(Request $request) { // 自己写权限校验逻辑,比如判断角色 if(!auth()->user()->hasRole('pedagang')) { abort(403); } $tokoId = Toko::select('id')->firstWhere('user_id', auth()->id())->id; $orders = SubOrder::with('items')->where('toko_id', $tokoId)->orderBy('created_at', 'desc')->get(); return view('sellers.order.index', compact('orders')); } // 你原有其他业务方法不变 public function markTolak(SubOrder $suborder) { $suborder->status = 'gagal'; $suborder->save(); Alert::info('Order di Proses!', 'Order ditandai proses!'); return redirect('/seller/orders')->withMessage('Order ditandai proses'); } public function markProses(SubOrder $suborder) { $suborder->status = 'proses'; $suborder->save(); Alert::info('Order di Proses!', 'Order ditandai proses!'); return redirect('/seller/orders')->withMessage('Order ditandai proses'); } public function markDelivered(SubOrder $suborder) { $suborder->status = 'selesai'; $suborder->save(); $pendingSubOrders = $suborder->order->subOrders()->where('status','!=', 'selesai')->count(); if($pendingSubOrders == 0) { $suborder->order()->update(['status'=>'selesai']); } Alert::success('Order Selesai!', 'Order ditandai selesai!'); return redirect('/seller/orders')->withMessage('Order ditandai selesai'); } }
- 修改你的视图文件
resources/views/sellers/order/index.blade.php,直接继承Voyager的母模板:
@extends('voyager::master') @section('page_title', '订单管理') @section('page_header') <h1 class="page-title"> <i class="voyager-bag"></i> 订单管理 </h1> @stop @section('content') <div class="page-content container-fluid"> <div class="row"> <div class="col-md-12"> <div class="panel panel-bordered"> <div class="panel-body"> {{-- 这里写你自己的页面内容,Voyager自带的所有样式、组件都可以直接使用 --}} <table class="table table-striped"> @foreach($orders as $order) <tr> <td>{{ $order->id }}</td> <td>{{ $order->status }}</td> <td> <a href="{{ route('order.mark.proses', $order) }}" class="btn btn-sm btn-primary">标记为处理中</a> </td> </tr> @endforeach </table> </div> </div> </div> </div> </div> @endsection
这种方式不用依赖Voyager的BREAD配置,完全自定义业务逻辑的同时可以100%保持和Voyager后台的风格统一。
内容的提问来源于stack exchange,提问作者Binz
相关产品推荐
相关产品推荐

