Tengo un modelo de Producto
class Product extends Model
{
...
public function prices()
{
return $this->hasMany('App\Price');
}
...
}
Quiero agregar una función que devolverá el precio más bajo, y en el controlador puedo obtener el valor usando:
Product::find(1)->lowest;
Agregué esto en el modelo del producto:
public function lowest()
{
return $this->prices->min('price');
}
pero tengo un error que dice:
Relationship method must return an object of type Illuminate\Database\Eloquent\Relations\Relation
y si uso Product::find(1)->lowest();
, funcionará. ¿Es posible conseguir Product::find(1)->lowest;
¿trabajar?
Cualquier ayuda sería apreciada.
Raúl M
Cuando intenta acceder a una función en el modelo como una variable, laravel asume que está tratando de recuperar un modelo relacionado. Las llaman propiedades dinámicas. Lo que necesita en su lugar es un atributo personalizado.
Antes de Laravel 9
Documentos de Laravel 6: https://laravel.com/docs/6.x/eloquent-mutators
agregue el siguiente método a su modelo:
public function getLowestAttribute()
{
//do whatever you want to do
return 'lowest price';
}
Ahora debería poder acceder a él de esta manera:
Product::find(1)->lowest;
EDITAR: Nuevo en Laravel 9
Laravel 9 ofrece una nueva forma de manejar los atributos:
Documentos: https://laravel.com/docs/9.x/eloquent-mutators#accessors-and-mutators
// use Illuminate\Database\Eloquent\Casts\Attribute;
public function lowest(): Attribute
{
return new Attribute(
get: function( $originalValue ){
//do whatever you want to do
//return $modifiedValue;
});
/**
* Or alternatively:-
*
* return Attribute::get( function( $originalValue ){
* // do whatever you want to do
* // return $modifiedValue;
* });
*/
}
-
No me di cuenta de que podías hacer eso con atributos que no estaban definidos como columnas en la tabla subyacente; la documentación no mencionó eso (que pude encontrar).
– Aarón Wallentine
29 de noviembre de 2016 a las 6:21
-
Hola, también me interesaría saber dónde podría encontrar esto en la documentación de Laravel. Gracias.
– lijadoras
24 de enero de 2017 a las 21:26
-
creo que esto debe ser el más bajo (); — recibo un error de relación sin que termine ‘()’
– caro
16 abr 2017 a las 21:14
-
-
Así que básicamente, tienes que hacer
get
+ nombre-de-la-propiedad-con-la-primera-letra-en-mayuscula +Attribute()
para conseguir lo que quieres? Eso es confuso, pero funciona. Gracias.– Hartley San
19 de marzo de 2019 a las 21:11
Usar elocuente accesorios
public function getLowestAttribute()
{
return $this->prices->min('price');
}
Después
$product->lowest;
puede usar los métodos anteriores o usar el siguiente método para agregar una función directamente al modelo existente:
class Company extends Model
{
protected $table="companies";
// get detail by id
static function detail($id)
{
return self::find($id)->toArray();
}
// get list by condition
static function list($name="")
{
if ( !empty($name) ) return self::where('name', 'LIKE', $name)->get()->toArray();
else return self::all()->toArray();
}
}
O use Illuminate\Support\Facades\DB; dentro de su función. Espero que esto ayude a otros.
-
¿Cómo se accede a estos métodos? Lo es
Company::detail(2);
oCompany::list('Company 1')
?– Hmerman6006
17 de julio de 2020 a las 9:59
-
@HalfMens sí, intenta hacer esto
– May’Habit
18 de julio de 2020 a las 10:16
-
Gracias. Lo principal es que el método debe ser
static
de lo contrario obtienes un error:Non-static method App\Models\Company::detail(2) should not be called statically
– Hmerman6006
18 de julio de 2020 a las 11:47
-
Claro, si quieres llamarlo directamente. De lo contrario, Company::where()->detail() o algún otro método estático está disponible en laravel.
– May’Habit
20 de julio de 2020 a las 3:00
Achraf Khouadja
¿Por qué simplemente no haces esto? Lo sé, no es lo que pediste específicamente y, a veces, puede ser una mala práctica. pero en tu caso supongo que es bueno.
$product = Product::with(['prices' => function ($query) {
$query->min('price');
}])->find($id);
cambiar el código de seguimiento
public function lowest()
{
return $this->prices->min('price');
}
a
// add get as prefix and add posfix Attribute and make camel case function
public function getLowestAttribute()
{
return $this->prices->min('price');
}
no ofc porque está llamando a un método, creo que tgat funcionará solo para una relación hasone, ¿y cuál es la diferencia? ¡con o sin!
– Achraf Khouadja
8 de junio de 2016 a las 3:15