简体   繁体   English

Laravel 5.关系的findOrNew

[英]Laravel 5. findOrNew for relationships

Just wondering if it is possible that some kind of findOrNew for relationships exist in Eloquent (in case if relationship do not exist attach new model instance)? 只是想知道Eloquent是否存在某种用于关系的findOrNew(如果不存在关系,请附加新模型实例)?

What that mean: Lets say that we have devices and specifications tables. 含义:假设我们有设备和规格表。 Device belongs to specification. 设备属于规格。 Specification_id is an FK (Know that is not best approach, but I have something like this left by previous programmer). Specification_id是一个FK(知道这不是最好的方法,但是我以前的程序员留下了类似的内容)。 Under id 11 we have device that do not have specification but we have to display that for user anyway. 在ID 11下,我们的设备没有规范,但无论如何我们都必须向用户显示该规范。

$device = Device::find(11);
echo $device->specification->cpu;

In this case it will throw an error because specification will be null - it do not exist for device with id 11. 在这种情况下,它会引发错误,因为规范将为空-ID为11的设备不存在该规范。

Know that I could check first if it exist but there aa lot of similar lines and app is pretty big. 知道我可以先检查它是否存在,但是有很多相似的代码,而且应用程序很大。 I need to move it from Kohana to Laravel. 我需要将其从Kohana移至Laravel。 It works in Kohana because empty object is loaded then and 2nd line just return null. 它在Kohana中起作用,因为然后会加载空对象,并且第二行只是返回null。 For Laravel I can just check if relationship exist and load new model then but I am curios if maybe there is any other and better way? 对于Laravel,我可以检查是否存在关系并加载新模型,但是如果您有其他更好的方法,我很想知道吗?

I would go for creating extra method in Device model this way: 我会这样在Device模型中创建额外的方法:

public function getSpecification()
{
   if ($device->specification) {
       return $device->specification;
   }
   return Specification::find(20); // some default specification
   // or
   // return new Specification(['cpu' => 'Not provided']);
}

And now you could use it this way: 现在您可以通过以下方式使用它:

$device = Device::find(11);
$device->getSpecification()->cpu;

Of course it depends how would you need to use it. 当然,这取决于您将如何使用它。 If you have many properties, you should run this method just once for object to not run multiple queries and in case you would use it for big collections you should also rethink improvements to lower database queries. 如果您有许多属性,则应只运行一次此方法,以使对象不运行多个查询,并且如果将其用于大集合,则还应重新考虑对较低数据库查询的改进。

This doesn't quite create the related object as you requested, but for the purposes of outputting the data or replicating Kohana's null output in the absence of a related model, I tend to use the data_get() or object_get() helpers for this purpose. 这并没有完全按照您的要求创建相关对象,但是出于输出数据或在缺少相关模型的情况下复制Kohana空输出的目的,我倾向于使用data_get()object_get()帮助器。

$device = Device::find(11);

echo object_get($device->specification, 'cpu');

// You could probably do this too (untested)

echo object_get($device, 'specification.cpu');

Having had a bit of a look, you can override the getRelationshipFromMethod() method in Illuminate\\Database\\Eloquent\\Model 看一看,您可以在Illuminate\\Database\\Eloquent\\Model重写getRelationshipFromMethod()方法

protected function getRelationshipFromMethod($method)
{
    // Different relationships return different types of data so
    // tweak this as necessary. In theory you only care if the relationship
    // type is a single entity rather than a collection.
    $results = parent::getRelationshipFromMethod($method);

    if ($results instanceOf Illuminate\Database\Eloquent\Collection) {
        return $results;
    }

    // Generate a null value for any missing attributes
    // PHP7 anonymous class. Return a real class < 7.0
    return $this->relations[$method] = new class {
        public function __get($attribute) {
            return null;
        }
    };

    // Or perhaps actually create a relationship with a specification
    $this->relations[$method] = Specification::where('default', true)->first();

    $this->specification()->associate($this->relations[$method]);

    return $this->relations[$method];
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM