Estoy tratando de ejecutar algunas llamadas de método dinámico basadas en el valor de un campo de base de datos. Un poco de contexto: tengo un modelo de Anniversary y quiero mostrar todos los próximos aniversarios dentro de los próximos x días. Un aniversario tiene una date y una frequency . Por ejemplo, mensual, trimestral, etc. En función de la frecuencia, quiero verificar cada aniversario si es próximo.
Aquí está mi código hasta ahora:
$anniversaries = auth()->user()->anniversaries()->get(); $test = $anniversaries->filter(function ($anniversary) { $method = Str::of($anniversary->frequency)->camel(); return ${$anniversary->$method}() == true; }); dd($test); Lo anterior funciona, cuando en el método real dd() algo. Pero al devolver verdadero o falso, me sale el error:
App\Models\Anniversary::monthly must return a relationship instanceY en mi modelo solo tengo algunos métodos como los siguientes, para probar:
public function monthly() { return true; } public function quarterly() { return false; }Mi única pregunta es, quiero entender por qué recibo este error y, por supuesto, cualquier indicación en la dirección correcta para obtener lo que quiero que funcione. ¡Gracias!
La siguiente línea crea un objeto Illuminate\Support\Str en lugar de una cadena. Esto hace que el Method name must be a string .
$method = Str::of($anniversary->frequency)->camel();Puede solucionar esto convirtiéndolo manualmente en una cadena e invocándolo directamente:
$test = $anniversaries->filter(function ($anniversary) { $method = (string) (Str::of($anniversary->frequency)->camel()); return $anniversary->$method() == true; });Lanzando mis 2 centavos por esto también. Las Str::of() , que son "cadenas fluidas" agregadas en Laravel 7.x, devuelven una instancia de Stringable :
https://laravel.com/api/8.x/Illuminate/Support/Stringable.html
Por ejemplo:
dd(Str::of('monthly')->camel()); Illuminate\Support\Stringable {#3444 value: "monthly" } Para obtener el value de esto, como una string y no como un object , puede convertirlo (como se muestra en la respuesta de MaartenDev) o llamar al método __toString() :
dd(Str::of('monthly')->camel()->__toString()); "monthly"En su ejemplo de código, eso sería simplemente:
$method = Str::of($anniversary->frequency)->camel()->__toString(); return $anniversary->{$method}() == true; Alternativamente, puede usar la función Str::camel() para omitir esta clase Stringable :
$method = Str::camel($anniversary->frequency); return $anniversary->{$method}() == true;https://laravel.com/docs/8.x/helpers#method-camel-caso
Espero que ayude a aclarar algunas confusiones 😄
tiene un problema en esta parte ${$anniversary->$method}() . si accede a una función como property laravel models piensa en su función de relación. así que reemplace con $anniversary->{$method}()
prueba este
$anniversaries = auth()->user()->anniversaries()->get(); $test = $anniversaries->filter(function ($anniversary) { $method = Str::of($anniversary->frequency)->camel(); return $anniversary->{$method}() == true; }); dd($test);