I have 2 tables, users
and websites
. One user can have multiple websites assigned to it.
public function websites() {
return $this->hasMany('App\Models\Website');
}
The error I get is:
Object of class Illuminate\Database\Eloquent\Relations\HasMany could not be converted to string
If I try to output it as an array using print_r
I get hundreds of lines of array which I'm assuming is caused by an error somewhere.
Also, why do I have to use App\Models\Website
in the hasMany
method if I specified at the top of User
model use App\Models\Website;
?
If I use just Website
in the method, I get class not found error:
Class 'Website' not found
Not a big deal, but it would be much cleaner not to have to use the full namespace path.
The code in the controller:
<?php namespace App\Http\Controllers;
use DB;
use App\User;
class DashboardController extends Controller {
/*------------------------------------------------------------------
Dashboard page
-------------------------------------------------------------------*/
public function show() {
//$user = auth()->user();
$user = User::find(5);
return $user->websites();
//return view('dashboard');
}
};
The websites()
function itself is not causing the error. The error is coming from wherever you are using the function.
The hasMany()
function returns an Illuminate\Database\Eloquent\Relations\HasMany
object. So, when you call $user->websites()
, this will return the HasMany
relationship object. Wherever you are using this function, you are then trying to convert that result to a string, which is the error you're seeing.
For example:
$user = User::find(1);
echo $user->websites();
In this example, if you try to echo
the response from the websites()
method, you will get the "could not be converted to string" error.
If this doesn't help you enough to resolve the issue, you will need to post the code that is calling the websites()
function for anyone to be able to help further.
Edit
"The controller doesn't echo the websites() method, it just returns it." Anything returned by a controller method is converted to a string. This is your issue.
Instead of returning the HasMany
object, you need to return the results of the HasMany
object. There are two main options: call get()
on the relationship to actually get the results and return that, or use the relationship attribute instead of the method.
Option 1:
public function show() {
$user = User::find(5);
// call "get()" to get the results
return $user->websites()->get();
}
Option 2:
public function show() {
$user = User::find(5);
// use lazy loaded attribute instead of using relationship method
return $user->websites;
}
Both of the options above will return the same thing: a Collection
of the Website
objects. Since you're returning this from the controller, Laravel will convert this to a string, so your output will be a json array of json Website
objects.
I have a couple of possible solutions:
First, do you have the inverse relationship defined?
User.php
public function websites() {
return $this->hasMany('App\Models\Website');
}
Website.php
public function user()
{
return $this->belongsTo('App\Models\User');
}
Second, have you run composer dump-autoload
in terminal.
Note if you want a cleaner interface you can this if you are using >= php 5.5
User.php
public function websites() {
return $this->hasMany(App\Models\Website::class);
}
or
use App\Models\Website;
public function user() {
return $this->hasMany(Website::class);
}
Edit 1
Do your models have the right namespace?
namespace App\Models;
Edit 2
You could try 2 more things.
<?php namespace App\Http\Controllers;
use DB;
use App\User;
class DashboardController extends Controller {
public function show() {
$user = User::find(5);
return $user->websites()->toArray();
}
// this one will query the database only once.
public function newShow() {
$user = User::with('websites')->find(5);
return $user->websites->toArray();
}
};