Call to undefined method Illuminate\Database\Eloquent\Collection - laravel-5

i have this two models:
class Opcion extends Model
{
protected $table = 'opciones';
public function pregunta(){
return $this->belongsTo('Send\Pregunta', 'pregunta_id');
}
}
class Pregunta extends Model
{
protected $table = 'preguntas';
public function opciones(){
return $this->hasMany('Send\Opcion', 'pregunta_id');
}
}
then in my controller:
class GraficosController extends Controller
{
public function getIndex(){
$preguntas= \Send\Pregunta::where('encuesta_id','=',1)->get();
$opciones= $preguntas->opciones();
return view('graficos.grafico')->with(['preguntas'=>$preguntas,'opciones'=>$opciones]);
}
}
im getting this error: Call to undefined method Illuminate\Database\Eloquent\Collection::opciones(), im trying to get all the "opciones" related with "preguntas"

You're getting this error because the get() method returns a Collection object, which you can think of as an array of results. So the first element returned by your query would be $preguntas[0], and you could do this:
$opciones= $preguntas[0]->opciones();
But if you know that you're only going to get one result from your query, then you should use the first() method instead of get(). first() will return an instance of the first result from your query.
$preguntas= \Send\Pregunta::where('encuesta_id','=',1)->first();
$opciones= $preguntas->opciones(); // Now this will work

Related

Laravel Error Argument 1 passed to method must be an instance of App\Model, instance of Illuminate\Database\Eloquent\Collection given

I have these 3 models:
product
class Product extends Model
{
public function categories()
{
return $this->belongsToMany(Category::class);
}
public function getPriceAttribute($price)
{
$categories=$this->categories;
//dd($categories->first()->validCoupons()); //dd#1
$coupons =collect(new Coupon);
foreach($categoriesas $category){
$coupons->add($category->validCoupons());
}
//dd($coupons->first()); //dd#2
if ($coupons->isNotEmpty()){
$discountCalculator = resolve(DiscountCalculator::class);
return $discountCalculator->discountedPrice($coupons->first() ,$price);
}
return $price ;
}
}
Coupon
class Coupon extends Model
{
public function isExpired()
{
return Carbon::now()->isAfter(Carbon::parse($this->expire_time));
}
}
Category
class Category extends Model
{
use Couponable;
}
and this is Coponable:
trait Couponable
{
public function coupons()
{
return $this->morphMany(Coupon::class , 'couponable');
}
public function validCoupons()
{
return $this->coupons->where('expire_time' , '>' , Carbon::now());
}
}
but I get this error:
Argument 1 passed to
App\Support\Discount\DiscountCalculator::discountedPrice() must be an
instance of App\Coupon, instance of
Illuminate\Database\Eloquent\Collection given
I get to dd as As specified in question dd#1 and dd#2 and get the following results:
dd($categories->first()->validCoupons());
and for dd#2:
dd($coupons->first());
As the error said the method discountedPrice() accepts App\Coupon as the first parameter and you gave it a Collection
$coupons = collect(new Coupon);
in this line you are making a new collection, then you add() coupons in that collection if you dd($coupons) you will find it's an instance of Illuminate\Support\Collection not App\Coupon so you need to pass App\Coupon instead as first parameter

How to call BaseController public function from child classes in Laravel (4)?

I have a CustomController. For not to repeat myself, I defined getVars function in BaseController. I want to call getVars function from some functions in CustomController.
However, Laravel returns 404 error without any exception. What is wrong?
class BaseController extends Controller {
public function getVars($var1, $var2, $var3=Null, $var4=Null) {
return [];
}
}
class CustomController extends BaseController {
public function doBla1($var1, $var2) {
$vars = $this->getVars();
}
public function doBla2() {
$vars = $this->getVars();
}
public function doBla3() {
$vars = $this->getVars();
}
}
Sorry :( I found the reason of error. The names of doBla1 and getVars functions are same. This results in a 404 error. Sorry :(
$this is useful when you have method/function defined in same controller.
For functions inside parent controller you can use
Parent::getVars($var1, $var2)

Laravel 5 Displaying related model data on blade

I would like to create an eager loading on my model but I keep getting and error. Anyways here is my model structure
// table name is drug_logs
class DrugLog extends Model
{
public function drug() {
return $this->belongsTo('App\Drug');
}
public function dispensedDrug() {
return $this->hasOne('App\DispensedDrug');
}
}
// table name is drugs
class Drug extends Model
{
public function drugLogs() {
return $this->hasMany('App\DrugLog');
}
}
// table name is dispensed_drugs
class DispensedDrug extends Model
{
public function drugLog() {
return $this->belongsTo('App\DrugLog');
}
}
But now on my controller I tried using this function
$drug_logs = DrugLog::with('dispensed_drugs')->get();
But I keep getting an error
BadMethodCallException in Builder.php line 2003: Call to undefined method Illuminate\Database\Query\Builder::dispensed_drugs()
Any idea on this guys?

Laravel Relationship problems: Relationship method must return an object of type Illuminate\Database\Eloquent\Relations\Relation

I must be missing something obvious. I've got a Invoice_detail Model:
class Invoice_detail extends Eloquent {
public function products()
{
$this->belongsTo('Product');
}
}
A Product Model:
class Product extends Eloquent {
public function invoiceDetails()
{
$this->hasMany('Invoice_detail');
}
}
but when I try to use this:
Route::get('/', function(){
$detail = Invoice_detail::whereId(27)->first();
return $detail->products;
});
I get: Relationship method must return an object of type Illuminate\Database\Eloquent\Relations\Relation
What am I missing here?
Yep - your relationship methods should have returns on them:
public function invoiceDetails()
{
return $this->hasMany('Invoice_detail');
}

Eloquent construction returning too many results

I have the following code in my DesignsController:
public function show($id)
{
return Design::find($id)->with('variables')->get();
}
When I GET /designs/1 I should get back json of just the design with id=1, but I get back all the current designs.
In the design model:
/* Define relationship between designs and variables */
public function variables()
{
return $this->hasMany('Variable');
}
The routes.php:
Route::resource('designs', 'DesignsController');
What am I doing wrong here?
Edit: a bit more information. I get all the results back as long as I hit an id of an actual design, so it seems to be finding the result according to the id, but then returning all results.
If I remove ->with('variables')->get(); then this works, but I need the variables too. Here's the model for Design:
class Design extends Eloquent {
/* Define relationship between designs and variables */
public function variables()
{
return $this->hasMany('Variable');
}
/* Define relationship between designs and variables */
public function user()
{
return $this->belongsTo('User');
}
}
Variable model:
class Variable extends Eloquent {
public $timestamps = false;
}
You're doing your "with" statement incorrectly:
Eager load:
public function show($id)
{
return Design::with('variables')->find($id);
}
Actually I think you're problem was calling get() after find() since find already returns a model. Find should be called at the end of a query you build because it essentially calls get() inside of it.
Lazy-Eager alternative:
public function show($id)
{
return Design::find($id)->load('variables');
}

Resources