在Laravel 5中添加自定义eloquent属性

时间:2016-01-17 09:43:37

标签: laravel laravel-5 eloquent

我有一个名为siblings的函数,它可以获取用户的所有兄弟姐妹。

select siblings(id) as `siblings` from users where id = 1

我可以在Eloquent中访问该功能

User::where('id', 1)->first([DB::raw(siblings(id) as `siblings`)]->siblings;

我想通过自定义属性提供siblings

我将siblings添加到$appends数组

我还在getSiblingsAttribute模型中创建了User方法

public function getSiblingsAttribute()
{
    if (!$this->exists()) {
        return [];
    }

    $siblings = User::where('idd', $this->id)
        ->first([DB::raw('siblings(id) AS `siblings`')])
        ->siblings;

    return explode(',', $siblings);
}

但这不起作用$this->id返回null

我的表架构为users(id, username,...),所以显然id存在。

有没有办法在查询db时绑定siblings函数,然后从$this->siblings返回getSiblingsAttribute之类的内容。如果我可以将siblings(id) as siblings与查询选择绑定全局,就像我们对使用全局范围的范围一样。

这样我的代码可以简单地

public function getSiblingsAttribute()
{
    return $this->siblings;
}

1 个答案:

答案 0 :(得分:0)

最简单的方法是在数据库中创建一个视图并将其用作表:

protected $table = 'user_view';

否则我需要有关您的id == null问题的更多信息。 如果您可以在下一步中自行解决此问题,请务必在访问者中选择使用其他列名称,否则您将无限循环运行。

public function getSiblingsAttribute()
{
    if (!$this->exists()) {
        return [];
    }

    $siblings = User::where('id', $this->id)
        ->first([DB::raw('siblings(id) AS `siblings_value`')])
        ->siblings_value;

    return explode(',', $siblings);
}

修改

可悲的是,没有简单的方法可以实现这一目标。 但经过一点点的修补后,我找到了一个(不是很好)的解决方案。 试一试。

您必须将以下类和特征添加到您的应用中。

app/Classes/AdditionalColumnsTrait.php(附加列特征)

namespace App\Classes;


trait AdditionalColumnsTrait {

    public function newEloquentBuilder($query) {
        $builder = new EloquentBuilder($query);
        $builder->additionalColumns = $this->getAdditionalColumns();

        return $builder;
    }

    protected function getAdditionalColumns() {
        return [];
    }
}

app/Classes/EloquentBuilder.php(扩展的EloquentBuilder)

namespace App\Classes;

use Illuminate\Database\Eloquent\Builder;

class EloquentBuilder extends Builder {

    public $additionalColumns = [];

    public function getModels($columns = ['*']) {
        $oldColumns = is_null($this->query->columns) ? [] : $this->query->columns;
        $withTablePrefix = $this->getModel()->getTable() . '.*';
        if (in_array('*', $columns) && !in_array($withTablePrefix, $oldColumns)) {

            $this->query->addSelect(array_merge($columns, array_values($this->additionalColumns)));
        } elseif (in_array($withTablePrefix, $oldColumns)) {
            $this->query->addSelect(array_values($this->additionalColumns));
        } else {
            foreach ($this->additionalColumns as $name => $additionalColumn) {
                if (!is_string($name)) {
                    $name = $additionalColumn;
                }
                if (in_array($name, $columns)) {
                    if (($key = array_search($name, $columns)) !== false) {
                        unset($columns[$key]);
                    }
                    $this->query->addSelect($additionalColumn);
                }
            }
            if (is_null($oldColumns)) {

                $this->query->addSelect($columns);
            }
        }

        return parent::getModels($columns);
    }

}
之后,您可以像这样编辑模型:

class User extends Model {
    ...
    use App\Classes\AdditionalColumnsTrait;

    protected function getAdditionalColumns() {
        return [
            'siblings' => DB::raw(siblings(id) as siblings)),
        ];
    }
    ...
}

现在默认情况下会选中您的siblings列。 您还可以选择仅选择特定列。 如果您不想选择可以使用的其他列:User::find(['users.*'])

也许这对你来说是一个解决方案。