¿Por qué obtengo ‘El método no estático no debe llamarse estáticamente’ cuando invoco un método en un modelo Eloquent?

7 minutos de lectura

avatar de usuario
sam pettersson

Estoy tratando de cargar mi modelo en mi controlador e intenté esto:

return Post::getAll();

obtuve el error Non-static method Post::getAll() should not be called statically, assuming $this from incompatible context

La función en el modelo se ve así:

public function getAll()
{

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

}

¿Cuál es la forma correcta de cargar el modelo en un controlador y luego devolver su contenido?

  • 2 maneras. Primero, cree una instancia del modelo y use $obj->getAll() o hacer la función estática.

    – itachi

    20 de agosto de 2013 a las 16:14

  • Cuando usas: :: usted está tratando de acceder a un método inactivamente por lo que la firma de su función debe declararse como: public static function getAll().

    – Rubens Mariuzzo

    20 de agosto de 2013 a las 18:12


  • @Sam, te recomendaré una lectura de cinco minutos sobre programación orientada a objetos y métodos estáticos en PHP: php.net/manual/en/language.oop5.static.php

    – Rubens Mariuzzo

    20 ago 2013 a las 18:30

avatar de usuario
Rubens Mariuzzo

Definió su método como no estático y está tratando de invocarlo como estático. Dicho esto…

1.si desea invocar un método estático, debe usar el :: y define tu método como estático.

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

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

2. De lo contrario, si desea invocar un método de instancia, debe instanciar su clase, use ->.

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

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

Nota: En Laravel, casi todos los métodos de Eloquent devuelven una instancia de su modelo, lo que le permite encadenar métodos como se muestra a continuación:

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

En ese código estamos inactivamente llamando al all método a través de Fachada. Después de eso, todos los demás métodos se llaman como métodos de instancia.

  • ¿Cómo es getAll () no estático en la segunda opción?

    – Tratando de ser yo mismo

    20 de agosto de 2013 a las 19:58


  • Gracias @TryingTobemyself por notificarme sobre esto. Actualicé mi respuesta con tu sugerencia.

    – Rubens Mariuzzo

    20 de agosto de 2013 a las 20:58

  • In Laravel, almost all Eloquent methods are defined as static…. eso es un error. NINGUNA son estáticos.

    – itachi

    21 de agosto de 2013 a las 1:38


  • Sí, en Laravel, ninguno de los métodos Eloquent se define como estático.podemos usar ellos como si fueran definidos como estáticos, pero eso es una Fachada, más sobre esto: laravel.com/docs/fachadas

    – Rubens Mariuzzo

    9 de julio de 2014 a las 15:49

  • Aunque la respuesta es objetiva, en el contexto de Laravel es poco probable que esta sea la solución que buscan los usuarios de este hilo. Esta respuesta debe eliminarse y la respuesta keithics debe marcarse como correcta.

    – ceros y unos

    2 de diciembre de 2016 a las 18:02

avatar de usuario
keithics

¿Por qué no intentar agregar Scope? Scope es una característica muy buena de 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();

#scopes elocuentes en Laravel Docs

  • En mi opinión, esta debería ser la respuesta aceptada porque es específica de Laravel y la respuesta de Rubens es correcta pero no lo suficientemente específica.

    – JacobRossDev

    13 de marzo de 2015 a las 18:15

  • @JacobRossDev Estoy usando el alcance, la primera vez que usé el alcance local y funcionó correctamente, luego creé el alcance global cuando no satisface mi necesidad. Vuelvo al alcance local. Sigo todas las convenciones de nomenclatura, pero cuando lo llamo obtengo el error de BadMethodCallException Llamada al método no definido App\Models\Share::popular()

    – MANSOOR KOCHY

    2 de marzo a las 6:43

  • tengo scope y estaba recibiendo este error (porque tenía ambos published() y scopePublished() definido). Solución era hacer: Post::query()->published(); en vez de Post::published();

    – Top Master

    1 abr a las 14:14


avatar de usuario
Anis LOUNIS alias AnixPasBesoin

TL;DR. Puede evitar esto expresando sus consultas como MyModel::query()->find(10); en vez de MyModel::find(10);.

Hasta donde yo sé, a partir de PHPStorm 2017.2 la inspección de código falla para métodos como MyModel::where(), MyModel::find()etc. (verifique esto hilo). Esto podría volverse bastante molesto, cuando intentas (digamos) usar Integración Git de PhpStorm antes de enviar su código, PhpStorm no dejará de quejarse de estas advertencias de llamada de método estático.

Una forma elegante (IMOO) de sortear esto es llamar explícitamente ::query() donde sea que tenga sentido. Esto le permitirá beneficiarse de autocompletado gratuito y un bonito formato para sus consultas.

Ejemplos

MALO

Fragmento donde la inspección se queja de las llamadas a métodos estáticos

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

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

BUENO

Código bien formateado sin quejas

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

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

  • Cambiar el código solo para eliminar un incorrecto La advertencia de IDE suena como una mala idea. Si sabes que es correcto, mantenlo así.

    – zundi

    19 de julio de 2018 a las 23:08

  • @zundi sí señor, estoy totalmente de acuerdo en que cambiar el código para complacer al IDE no siempre es una buena práctica, PERO en este caso, solo estamos agregando una llamada de método estático que se habría llamado de cualquier manera (solo estamos siendo explícitos aquí). De lo contrario, tendría que: deshabilitar esta inspección o anotar otra clase en otro lugar … (¡un ajetreo! ¿No está de acuerdo?)

    – Anis LOUNIS alias AnixPasBesoin

    20 de julio de 2018 a las 23:56


  • Lo mismo, me gusta mucho esta respuesta. Para empezar, no soy un gran admirador de Facades, y el hecho de que PhpStorm no los admita desde el primer momento hace que me gusten menos. MyModel::query() deja muy claro lo que sucede debajo del capó y al mismo tiempo complace al IDE.

    – michasaurio

    23 de julio de 2019 a las 19:22

En caso de que esto ayude a alguien, recibí este error porque me perdí por completo el hecho declarado que el prefijo de ámbito no se debe utilizar al llamar a un ámbito local. Entonces, si definió un alcance local en su modelo de esta manera:

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

Deberías llamarlo así:

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

Tenga en cuenta que el prefijo scope no está presente en la llamada.

Solución a la pregunta original.

Llamó a un método no estático estáticamente. Para hacer que una función pública sea estática en el modelo, se vería así:

public static function {
  
}

En general:

Post::get()

En este caso particular:

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

Una cosa a tener en cuenta, al definir las relaciones y el alcance, con el que tuve un problema que causó un error de “método no estático no debe llamarse estáticamente” es cuando se nombran de la misma manera, por ejemplo:

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

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

Cuando hago lo siguiente, aparece el error no estático:

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

El problema es que Laravel está usando mi método de relación llamado categoría, en lugar de mi alcance de categoría (scopeCategory). Esto se puede resolver cambiando el nombre del ámbito o la relación. Elegí cambiar el nombre de la relación:

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

Tenga en cuenta que definí la clave externa (category_id) porque, de lo contrario, Laravel habría buscado cat_id en su lugar y no lo habría encontrado, ya que lo había definido como category_id en la base de datos.

avatar de usuario
Karthiga

Puedes dar así

public static function getAll()
{

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

}

Y cuando llama estáticamente dentro de la función de su controlador también …

avatar de usuario
idro2k

Literalmente acabo de llegar a la respuesta en mi caso. Estoy creando un sistema que implementó un método de creación, por lo que recibí este error real porque estaba accediendo a la versión anulada, no a la de Eloquent.

Espero que ayude?

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad