I have three models:
User:
public function projects()
{
return $this->hasMany('StoredFile', 'user_id', 'id')->with('files');
}
StoredFile:
public function files()
{
return $this->hasMany('File', 'hash', 'user_hash');
}
and File models which does not have relation method
The problem:
I use the following piece of code to get projects and each project stored files:
$projects = $user->projects;
var_dump(json_encode($projects))
// {"project_name":"test","user_hash":"64650458b6Fhgd68ca57308222","files":[{"id":1,"name":"example.pdf"}]}
I can use count($projects[0]->files) to get files count
but this $projects variable need to return to client side by Response::json
return Response::json($project);
and I can't leak the files to the visitor, I want to modify the StoredFile model to return files count only
just like:
return $this->hasMany('File', 'hash', 'user_hash')->count();
but this will throw me an error:
Call to a member function addEagerConstraints() on a non-object"
How can I receive the count value in relations??
please help! thanks
Relationship methods must return an object of type Illuminate\Database\Eloquent\Relations\Relation
. There is nothing wrong with your files()
function, but it is not a relationship, so it can't be used in your projects()
functions.
The problem piece of code is with('files')
, as Laravel is expecting an object of type Illuminate\Database\Eloquent\Relations\Relation
to be returned from the files()
function, and instead it receives an int
.
You can manually add this value to the model though. Try adding this to your StoredFile
model:
public function fileCount() {
return $this->hasMany('File', 'hash', 'user_hash')->count();
}
Change the User
model:
public function projects() {
return $this->hasMany('StoredFile', 'user_id', 'id');
}
Now use:
$projects = $user->projects;
$project = $project->first();
$project->fileCount = $project->fileCount();
var_dump(json_encode($project));
// {..., "fileCount":"1"}
Bare in mind that the number of files is being queried from the database once everytime you ask for it, so this is not efficient if you need to return more than one project. Given that you were returning a JSON response, I assumed that this would be the case though!
Otherwise, why not just do something like this:
public function files() {
return $this->hasMany('File', 'hash', 'user_hash');
}
public function projects() {
return $this->hasMany('StoredFile', 'user_id', 'id')->with('files');
}
Now use:
$projects = $user->projects;
$project = $project->first();
$project->fileCount = $project->files->count();
unset($project->files);
var_dump(json_encode($project));
// {..., "fileCount":"1"}
Something like that should work?
@Warren Moore is almost correct, but I just found a better solution:
protected $appends = array('file_count');
public function getFileCountAttribute()
{
return $this->files->count()
}
this will append a file_count
attribute to each file object