Laravel 5.2关联两张表实现搜索查询时出错求助
问题分析与解决方案
一、Trying to get property of non-object 错误的核心原因
你碰到的这个报错,主要是以下两个问题导致的:
1. 关联查询返回的不是Eloquent模型实例,无法调用关联属性
你的控制器里用了join关联两张表,并且只select了listings.city_id和cities.name,这时候返回的$listing集合里的元素不是Listing模型的实例,而是查询构造器返回的普通stdClass对象。如果你的结果视图(listingsresults.blade.php)里尝试调用类似$detail->city->name这样的关联属性,就会触发错误——普通对象没有city这个关联方法/属性。
2. where条件未指定表名,存在潜在歧义
你的查询里写了where('name', 'LIKE', '%' . $q . '%'),这里的name没有明确指定是cities表的字段。虽然当前你的listings表没有name字段不会直接报错,但未来如果表结构变更,这个查询就会出问题,属于需要修正的不严谨写法。
二、当前Model/Controller/View结构的合理性
整体结构是符合Laravel MVC规范的,但控制器的查询写法可以更贴合Eloquent的设计理念:
- Model部分:
Listing模型正确定义了和City的belongsTo关联,City模型的$fillable设置也没问题,这部分是合格的。 - Controller部分:用原生
join的写法虽然能实现功能,但没有利用Eloquent关联的便利性,还丢失了模型的特性(比如关联方法、模型事件等)。 - View部分:GET请求里的
csrf_field()其实是多余的(Laravel的CSRF保护默认只针对POST/PUT/DELETE等请求),可以去掉;另外placeholder里的citys是拼写错误,应该改成cities。
三、优化后的代码示例
1. 修正控制器查询(使用Eloquent关联查询)
public function listingsresults() { $q = Input::get('q'); // 使用whereHas筛选关联城市名称匹配的房源,同时预加载city关联避免N+1查询问题 $listings = Listing::whereHas('city', function($query) use ($q) { $query->where('name', 'LIKE', "%{$q}%"); }) ->with('city') // 预加载city关联,提升性能 ->paginate(8); if ($listings->isNotEmpty()) { return view('front-end/listingsresults') ->with('details', $listings) ->with('query', $q); } else { return view('front-end/listingsresults') ->with('message', 'No Details found. Try to search again !'); } }
2. 视图中正确访问关联数据(示例)
假设你的视图里循环展示搜索结果:
@if(isset($details)) @foreach($details as $listing) <div class="listing-item"> <p>城市:{{ $listing->city->name }}</p> <!-- 其他房源字段,比如街道、价格等 --> <p>街道:{{ $listing->street }}</p> <p>价格:${{ $listing->price }}</p> </div> @endforeach <!-- 分页链接 --> {{ $details->links() }} @else <p class="no-result">{{ $message }}</p> @endif
3. 优化首页表单
<form action="/search" method="GET" role="search"> <div class="form-wrapper"> <input type="text" class="search-query" name="q" placeholder="Search cities" autocomplete="off"> </div> <button type="submit" class="btn btn-success">SEARCH</button> </form>
四、额外学习建议
- 重点掌握Laravel的Eloquent关联查询和预加载(Eager Loading),这是Laravel ORM的核心优势,能让你的代码更简洁高效。
- 优先使用模型特性而非原生SQL/join,这样能更好地利用Laravel的生态功能,也便于后期维护。
- 调试时可以用
dd($listings)查看返回的数据结构,快速确认是不是你期望的模型实例,定位问题会更高效。
内容的提问来源于stack exchange,提问作者Jinjoe
相关产品推荐
相关产品推荐

