将Eloquent Model限制为特定列

时间:2014-09-12 21:19:54

标签: laravel model eloquent

我从一个相当大的数据库中提取,出于安全考虑,我的数据库用户只能从学生表中选择有限数量的列:name,gradu_date和gender。但是在select *语句中返回了许多其他列。

在常规SQL中,如果我运行类似:

SELECT * FROM students

将在该表上返回错误。如果我运行雄辩的模型

,也是如此
Students::all(); 

也会返回错误。

我知道在Eloquent中,您可以在定义类似于以下的关系时限制您的选择:

class Students extends Eloquent {

    protected $table        = 'student_info';

    public function classes() {
        return $this->hasMany('classes')->select(array('room', 'time'));
    }

}

所以,我的问题是,可以在主模型上完成选择限制,类似于在类表上限制它。因此,当我运行Student::all();时,它只选择我需要的列。

主要问题是每次我运行学生查询时,我每次都要做一个特定的选择命令,而不是只说“Student::all()”。 Student :: find(1)也是如此;也会返回错误,因为它仍会运行SELECT * FROM student_info WHERE id = 1

我尝试设置$visible变量,但仍然将sql等效为SELECT * FROM ...

任何人都有解决方案吗?

更新 请注意我在模型级别上寻找或解决方案,而不是控制器级别。我可以从控制器端进行选择,但这会破坏模型概念的目的,并且必须声明要在每个查询中选择的列。

谢谢! 特洛伊

3 个答案:

答案 0 :(得分:4)

您可以创建一个中间类并重载all()函数。我们称这个班为Elegant

<强> Elegant.php     

abstract class Elegant extends Model
{
    public static $returnable = [];

    public function all()
    {
        return $this->get(static::$returnable)->all();
    }
}

然后扩展此类,并为其定义可返回列。

<强> Student.php

<?php
class Student extends Elegant
{
    public static $returnable = ['room', 'time'];
}

现在可以根据需要使用它:控制器中的Student::all()。如果您将returnable作为空数组,那么您将获得所有内容。

答案 1 :(得分:2)

您可以使用以下内容:

public function newQuery()
{
    return parent::newQuery()->select('room', 'time');
}

newQuery方法放在Students模型中,并使用正常使用的Student模型。这是一种愚蠢的方式,但最容易。只需覆盖parent::query()即可。通过这种方式,您将始终获得所选字段。

答案 2 :(得分:2)

扩展Jarek关于使用Global Scope的建议你可以这样做,我不是100%确定移除部分是正确的,但是需要测试。

<强> SelectLimitTrait.php

trait SelectLimitTrait {

    public static function bootSelectLimitTrait()
    {    
        static::addGlobalScope(new SelectLimitScope);
    }

    public function getQueryable()
    {
        if(! $this->queryable ) return array('*');

        return $this->queryable;
    }  

} 

<强> SelectLimitScope.php

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\ScopeInterface;

class SelectLimitScope implements ScopeInterface {

    public function apply(Builder $builder)
    {
        $query = $builder->getQuery();

        $queryable = $builder->getModel()->getQueryable();

        $query->columns = $queryable;
    }

    public function remove(Builder $builder)
    {
        $query = $builder->getQuery();

        $query->columns = null;
    }

} 

然后在你的Eloquent模型中说出这个:

<强> Students.php

class Students extends \Eloquent  {

    use SelectLimitTrait;

    protected $queryable = array('name','graduation_date', 'gender');

}

现在Students::all()Students::find(1)等仅限于查询姓名,毕业日期和性别