由于条件关系而在null上调用成员函数addEagerConstraints()

时间:2020-09-11 09:51:49

标签: php laravel

我必须处理一个数据库设计欠佳的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关系?

3 个答案:

答案 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
    }       
}
相关问题