在Laravel中向Eloquent模型添加方法

时间:2015-08-27 20:12:46

标签: laravel eloquent

我对如何向Eloquent模型添加方法感到有点困惑。这是我的控制器中的代码:

public function show($id)
    {
        $limit = Input::get('limit', false);

        try {
            if ($this->isExpand('posts')) {
                $user = User::with(['posts' => function($query) {
                    $query->active()->ordered();
                }])->findByIdOrUsernameOrFail($id);
            } else {
                $user = User::findByIdOrUsernameOrFail($id);
            }

            $userTransformed = $this->userTransformer->transform($user);

        } catch (ModelNotFoundException $e) {
            return $this->respondNotFound('User does not exist');
        }

        return $this->respond([
            'item' => $userTransformed
        ]);
    }

User模型中的代码:

public static function findByIdOrUsernameOrFail($id, $columns = array('*')) {
        if (is_int($id)) return static::findOrFail($id, $columns);

        if ( ! is_null($user = static::whereUsername($id)->first($columns))) {
            return $user;
        }

        throw new ModelNotFoundException;
    }

基本上我试图允许user_idusername检索用户。我想通过创建自己的方法来保留findOrFail()的强大功能,该方法会检查$idint的{​​{1}}。

当我单独检索string时,它没有问题。当我展开User时,我得到错误:

  

调用未定义的方法   照亮\数据库\查询\生成器:: findByIdOrUsernameOrFail()

我不确定如何解决这个问题。

2 个答案:

答案 0 :(得分:2)

您正试图在静态和非静态上下文中调用您的方法,但这种方法不起作用。要在不重复代码的情况下完成您想要的任务,您可以使用Query Scopes

public function scopeFindByIdOrUsernameOrFail($query, $id, $columns = array('*')) {
    if (is_int($id)) return $query->findOrFail($id, $columns);

    if ( ! is_null($user = $query->whereUsername($id)->first($columns))) {
        return $user;
    }

    throw new ModelNotFoundException;
}

您可以按照现在的方式使用它。

此外,您可以使用firstOrFail

public function scopeFindByIdOrUsernameOrFail($query, $id, $columns = array('*')) {
    if (is_int($id)) return $query->findOrFail($id, $columns);

    return $query->whereUsername($id)->firstOrFail($columns);
}

答案 1 :(得分:1)

你的方法很好,但是你试图以两种相互矛盾的方式使用它。按照你的意图工作的是else子句中的那个,就像你意识到的那样。

第一次提及不起作用的原因是因为两件事:

  1. 您将该方法编写为静态方法,这意味着您不会在实例化对象上调用它。换句话说:User::someStaticMethod()有效,但$user->someStaticMethod()没有。
  2. 代码User::with(...)返回一个Eloquent查询Builder对象。此对象无法调用您的静态方法。
  3. 不幸的是,你要么必须复制功能,要么绕过它。就个人而言,我可能会创建一个用于链接的非静态方法的用户存储库。另一种选择是在User模型上创建一个静态方法,用于启动链接并从那里调用静态方法。

    编辑:Lukas建议使用示波器当然是最好的选择。我不认为它会在这种情况下起作用。