Eloquent 모델에서 메서드를 호출 할 때 '비 정적 메서드를 정적으로 호출해서는 안됩니다'라는 메시지가 나타나는 이유는 무엇입니까?


84

내 컨트롤러에 내 모델을로드하려고 시도하고 이것을 시도했습니다.

return Post::getAll();

오류가 발생했습니다 Non-static method Post::getAll() should not be called statically, assuming $this from incompatible context

모델의 기능은 다음과 같습니다.

public function getAll()
{

    return $posts = $this->all()->take(2)->get();

}

컨트롤러에서 모델을로드 한 다음 내용을 반환하는 올바른 방법은 무엇입니까?


2 가지 방법. 첫째, 모델의 인스턴스를 만들고 $obj->getAll()함수를 정적으로 사용 하거나 만듭니다.
itachi 2013-08-20

5
사용할 때 : ::메서드에 정적으로 액세스하려고 하므로 함수 서명을 다음과 같이 선언해야합니다 public static function getAll()..
Rubens Mariuzzo

: @Sam, 나는 당신에게 PHP에서 OOP 및 정적 방법에 대해 읽는 오분 추천합니다 php.net/manual/en/language.oop5.static.php
루벤스 Mariuzzo

답변:


110

메서드를 비 정적으로 정의했고이를 정적으로 호출하려고합니다. 그건 ...

1. 정적 메서드를 호출하려면을 사용하고 ::메서드를 static으로 정의해야합니다.

// Defining a static method in a Foo class.
public static function getAll() { /* code */ }

// Invoking that static method
Foo::getAll();

2. 그렇지 않으면 인스턴스 메서드를 호출하려면 클래스를 인스턴스화해야합니다 ->.

// Defining a non-static method in a Foo class.
public function getAll() { /* code */ }

// Invoking that non-static method.
$foo = new Foo();
$foo->getAll();

참고 : Laravel에서 거의 모든 Eloquent 메서드는 모델의 인스턴스를 반환하므로 아래와 같이 메서드를 연결할 수 있습니다.

$foos = Foo::all()->take(10)->get();

이 코드에서 우리는 Facade를 통해 메서드를 정적으로 호출합니다 all. 그 후, 다른 모든 메소드는 인스턴스 메소드 로 호출됩니다 .


두 번째 옵션에서 getAll ()이 어떻게 비 정적입니까 ??
Trying Tobemyself 2013-08-20

1
이것에 대해 알려주는 @TryingTobemyself에게 감사드립니다. 귀하의 제안으로 제 답변을 업데이트했습니다.
Rubens Mariuzzo

9
In Laravel, almost all Eloquent methods are defined as static.... 그건 오해입니다. NONE 은 정적입니다.
itachi

@itachi, 제발, 오해를 설명해 주시겠습니까?
Rubens Mariuzzo

4
예, Laravel에, 아무도 웅변 방법은 정적으로 정의 우리가 할 수있는, 사용 이 정적으로 정의 된 그들을하지만 더 이것에 대해, 외관의 : laravel.com/docs/facades
루벤스 Mariuzzo

36

스코프를 추가해보세요. 스코프는 Eloquent의 아주 좋은 기능입니다.

class User extends Eloquent {

    public function scopePopular($query)
    {
        return $query->where('votes', '>', 100);
    }

    public function scopeWomen($query)
    {
        return $query->whereGender('W');
    }

}

$users = User::popular()->women()->orderBy('created_at')->get();

Laravel Docs의 Eloquent #scopes


2
IMO 이것은 Laravel에 한정되어 있으며 Rubens 답변이 정확하지만 충분히 구체적이지 않기 때문에 허용되는 답변이어야합니다.
JacobRossDev

8

TL; DR . MyModel::query()->find(10);대신 쿼리를 표현하여이 문제를 해결할 수 있습니다 MyModel::find(10);.

내가 아는 한 PhpStorm 2017.2 시작 코드 검사는 다음과 같은 방법에 대해 실패합니다.MyModel::where() , MyModel::find()등 (이 확인 스레드 ). 코드를 커밋하기 전에 PhpStorm의 Git 통합 을 사용하려고하면 PhpStorm 이 이러한 정적 메서드 호출 경고에 대해 불평하는 것을 멈추지 않을 것입니다.

이 문제를 해결하는 우아한 방법 (IMOO) 중 하나 는 의미가있는 곳 을 명시 적으로 호출::query() 하는 것입니다. 이렇게하면 무료 자동 완성과 멋진 쿼리 형식의 이점을 얻을 수 있습니다.

검사에서 정적 메서드 호출에 대해 불평하는 스 니펫

$myModel = MyModel::find(10); // static call complaint

// another poorly formatted query with code inspection complaints
$myFilteredModels = MyModel::where('is_beautiful', true)
    ->where('is_not_smart', false)
    ->get();

불만이없는 올바른 형식의 코드

$myModel = MyModel::query()->find(10);

// a nicely formatted query with no complaints
$myFilteredModels = MyModel::query()
    ->where('is_beautiful', true)
    ->where('is_not_smart', false)
    ->get();

잘못된 IDE 경고 를 제거하기 위해 코드를 변경 하는 것은 나쁜 생각처럼 들립니다. 그것이 옳다는 것을 알고 있다면 그대로 유지하십시오.
zundi

@zundi 그렇습니다, 나는 완전히 IDE를 기쁘게을 위해 코드를 변경하는 것이 항상 좋은 방법이 아닙니다 동의합니다, 하지만 우리는 (이 경우, 우리는 단지 두 가지 방법으로 호출 된 한 것이다 하나의 정적 메소드 호출을 추가하는 '여기서 명시 적입니다). 그렇지 않으면 당신은해야 할 것입니다 ... 다른 곳에서 다른 클래스이 검사를 비활성화하거나 주석 중 (허슬를 u는 동의하지 않는다!?)
아니스 LOUNIS

1
동일합니다.이 답변이 정말 마음에 듭니다. 저는 Facades의 팬이 아닙니다. PhpStorm이 바로 그들을 지원하지 않는다는 사실은 저를 덜 좋아하게 만듭니다. MyModel::query()IDE를 만족시키면서 내부에서 무슨 일이 일어나고 있는지 매우 명확하게 보여줍니다.
michasaurus

3

이것이 누군가에게 도움이되는 경우를 대비 하여 로컬 범위를 호출 할 때 범위 접두사를 사용해서는 안된다는 명시된 사실 을 완전히 놓 쳤기 때문에이 오류가 발생했습니다 . 따라서 다음과 같이 모델에 로컬 범위를 정의한 경우 :

public function scopeRecentFirst($query)
{
    return $query->orderBy('updated_at', 'desc');
}

다음과 같이 호출해야합니다.

$CurrentUsers = \App\Models\Users::recentFirst()->get();

접두사 scope는 호출에 없습니다.


0

이렇게 줄 수 있어요

public static function getAll()
{

    return $posts = $this->all()->take(2)->get();

}

그리고 컨트롤러 함수 내부에서 정적으로 호출 할 때도 ..


4
당신은 당신이 정적 방법 안에이 $ 수 없습니다
Luvias

0

나는 문자 그대로 내 경우에 대한 답에 도달했습니다. 저는 create 메서드를 구현 한 시스템을 만들고 있으므로 Eloquent가 아닌 재정의 된 버전에 액세스했기 때문에이 실제 오류가 발생했습니다.

도움이 되었나요?


0

모델에서 getAll () 메소드를 선언하지 않았는지 확인하십시오. 그러면 컨트롤러가 비 정적 메서드를 호출하고 있다고 생각하게됩니다.


0

구문을 사용하려면 모든 정적 호출을 처리하는 클래스에 return Post::getAll();매직 함수가 있어야 __callStatic합니다.

public static function __callStatic($method, $parameters)
{
    return (new static)->$method(...$parameters);
}

0

원래 질문에 대한 해결책

비 정적 메서드를 정적으로 호출했습니다. 모델에서 공용 함수를 정적으로 만들려면 다음과 같습니다.

public static function {
  
}

일반적으로 :

Post::get()

이 특별한 경우 :

Post::take(2)->get()

관계와 범위를 정의 할 때주의해야 할 사항은 '비 정적 메서드를 정적으로 호출하면 안 됨'오류가 발생하는 문제가 있는데, 이름이 같은 경우입니다. 예를 들면 다음과 같습니다.

public function category(){
    return $this->belongsTo('App\Category');
}

public function scopeCategory(){
    return $query->where('category', 1);
}

다음을 수행 할 때 비 정적 오류가 발생합니다.

Event::category()->get();

문제는 라 라벨이 내 카테고리 범위 (scopeCategory)가 아닌 카테고리라는 내 관계 방법을 사용하고 있다는 것입니다. 이 문제는 범위 또는 관계의 이름을 변경하여 해결할 수 있습니다. 관계 이름을 변경하기로 선택했습니다.

public function cat(){
    return $this->belongsTo('App\Category', 'category_id');
}

내가 외래 키 (category_id)를 정의했음을 확인하십시오.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.