我必须处理一个数据库设计欠佳的Laravel 7应用程序,导致标题中提到的错误。
数据库如下:
mains
- id
- sub_type
subs_a
- id
- main_id
subs_b
- id
- main_id
然后我有一个类Main
和方法sub
:
public function sub()
{
switch($this->sub_type) {
case 'a':
return $this->hasOne('SubTypeA');
break;
case 'b':
return $this->hasOne('SubTypeB');
break;
default:
return null;
}
}
此代码在所有情况下的99%都有效,但是Laravel有时会加载Main
的空实例,然后尝试加载关系。这不起作用,因为方法sub
的默认值为null
。
重组数据库在待办事项列表上,但是目前没有任何帮助。
我必须采取什么措施阻止Laravel尝试在空对象上加载sub
关系?
答案 0 :(得分:4)
我知道这是某种期望,但是试图返回一个空关系?
public function sub()
{
switch($this->sub_type) {
case 'a':
return $this->hasOne('SubTypeA');
break;
case 'b':
return $this->hasOne('SubTypeB');
break;
default:
return $this->newQuery(); // or newQueryWithoutScopes()
}
}
感谢此answer。应该可以防止addEagerConstraints()在null上的错误。
答案 1 :(得分:0)
我想指出的几件事是,您的关系不应该是有条件的,在建立默认关系后,您可以定义scope并管理内容或使用{{3} }在失败的情况下返回某些内容。
关于在null上调用成员函数的错误:-下面是另一个示例
<?php
class MyClass{
function bar(){
echo "something";
}
}
class MyAnotherClass{
function foo(){
if (1>2) {
$obj = new MyClass();
$obj->x = $x;
$obj->y = $y;
$obj->save();
return $obj;
} else {
return null;
}
}
}
$myAnotherObj = new MyAnotherClass();
$myClass = $myAnotherObj->foo();
$myClass->bar()
?>
我宁愿抛出异常并对其进行处理,而不是这样做,这样我才能获得失败的具体原因,您可以选择在Laravel withDefault帮助函数中使用它。
<?php
class MyClass{
function bar(){
echo "something";
}
}
class MyAnotherClass{
function foo(){
if (1>2) {
$obj = new MyClass();
$obj->x = $x;
$obj->y = $y;
$obj->save();
return $obj;
} else {
throw new Exception("could not create my class object", 100); // Better to create custom exception class here
}
}
}
$myAnotherObj = new MyAnotherClass();
try {
$myClass = $myAnotherObj->foo();
$myClass->bar();
} catch(Exception $e) {
echo $e->getMessage();
}
?>
如果对我来说数据不是那么重要,我会考虑创建一个空对象
<?php
class MyClass{
function bar(){
echo "something";
}
}
class MyAnotherClass{
function foo(){
$obj = new MyClass();
if (1>2) {
$obj->x = $x;
$obj->y = $y;
$obj->save();
}
return $obj;
}
}
$myAnotherObj = new MyAnotherClass();
$myClass = $myAnotherObj->foo();
$myClass->bar()
?>
但是,如果要使用该对象属性进行操作,则属性将为null而不是对象,因此,根据使用时的纪律,您可以做出决定。
我要如何处理您的情况?
异常类
<?php
namespace App\Exceptions;
use Exception;
class SubTypeNotFound extends Exception {
public function report()
{
\Log::debug('Could not find this subtype');
}
}
?>
模型类
<?php
class Mains extends Model
{
public function subA()
{
return $this->hasOne(SubTypeA::class);
}
public function subB()
{
return $this->hasOne(SubTypeB::class);
}
public function scopeSub($query, $type)
{
return $query
->when($type === 'a',function($q){
return $q->with('subA');
})
->when($type === 'b',function($q){
return $q->with('subB');
}),function($q){
throw SubTypeNotFound();
});
}
}
?>
同时检索
try {
$sub = Mains::sub('a')->get();
} catch(SubTypeNotFound $e) {
return $e->getMessage();
}
如果您有$this->sub_type
,则可以避免使用type
参数。
答案 2 :(得分:-2)
您可以简单地将if条件放在开关盒之前。
public function sub()
{
if($this->sub_type){
switch($this->sub_type) {
case 'a':
return $this->hasOne('SubTypeA');
break;
case 'b':
return $this->hasOne('SubTypeB');
break;
default:
return null;
}
}else{
return null
}
}