Laravel模型上的自定义查找方法应该是静态的吗?

时间:2016-11-06 04:26:04

标签: php laravel methods eloquent

在下面的Laravel 5模型中,findByIdAndCourseOrFail方法应该是静态的吗?

class Section extends Model {

    //should this method be static?
    public function findByIdAndCourseOrFail($id, $courseId)
    {

        $result = $this->where('id', $id)->where('course_id', $courseId)->first();

        if (!is_null($result))
        {
            return $result;
        }

        throw (new ModelNotFoundException())->setModel(Section::class);

    }


    }

使用控制器:

class SectionsController extends Controller {

protected $sections;

public function __construct(Section $section)
{

    $this->sections = $section;

}

public function foo($id, $courseId)  //illustration only
{
     $section = $this->sections->findOrFail($id);   

     $section = $this->sections->findByIdAndCourseOrFail($id, $courseId);  
     //would need to be non-static

     $section = Section::findByIdAndCourseOrFail($id, $courseId); 
     //weird when compared with find above
}

一方面,我们没有采取剖面实例[见注释]。另一方面,在通过Laravel's service container进行自动依赖注入的控制器中,我们将对一个实例执行操作:$sections = $this->sections-> findByIdAndCourseOrFail(7,3);并且我的IDE(PhpStorm)会在Static时发出警告。

[注意]:这个评论可能是对Laravel Models如何运作的误解。对我来说,我希望find()findOrFail()是Class方法,因此静态而不是find方法返回的实例。

3 个答案:

答案 0 :(得分:1)

class Section extends Model {


public static function findByIdAndCourseOrFail($id, $courseId)
{

    $result = self::where('id', $id)->where('course_id', $courseId)->first();

    if (!is_null($result))
    {
        return $result;
    }

    throw (new ModelNotFoundException())->setModel(Section::class);

}


}

答案 1 :(得分:1)

我个人认为这是一个静态的方法,我不确定是否有“正确”的答案,但任何一方都可以。我在脑海中将它们分开的方式是,如果我正在对模型的实例做一些事情,那么我将它作为普通的公共函数。如果我正在对集合做一些事情,我会使用静态。例如:

$person = new Person();
$person->setAdmin(true);
$person->save();

// OR

$admins = Person::getAdmins();

在第一个例子中,我们有一个Person的特定实例,我们正在操作它,所有代码都只是操纵该特定实例。在第二个示例中,我们对Person的整个集合进行操作,并且我们希望返回一组对象。

在您的情况下,您必须启动Section的实例才能使用非静态公共方法,如下所示:

$section = new Section();
$foundSection = $section->findByIdAndCourseOrFail(7,3);

所以$section成为一个永远不会真正使用的临时变量。另一方面,如果你把它设为静态,你就可以不必这样做就可以调用它。

$section = Section::findByIdAndCourseOrFail(7,3);

希望这是有道理的。

答案 2 :(得分:1)

我不确定local scopes是否应该像这样使用。但它在laravel 5.2上适用于我:

public function scopeFindByIdAndCourseOrFail($query, $id, $courseId)
{
    $result = $query->where('id', $id)->where('course_id', $courseId)->first();

    if (!is_null($result))
    {
        return $result;
    }

    throw (new ModelNotFoundException())->setModel(Section::class);
}

在控制器中,您可以双向使用:

$section = Section::findByIdAndCourseOrFail($id, $courseId);

$model = new Section();
$section = $model->findByIdAndCourseOrFail($id, $courseId);