Laravel collection returning duplicate - laravel

Hi I am trying to return a Users Schedule where greater than or equal to todays date, or if that schedule contains a relation (ScheduledYard) that is not complete:
$schedules = Auth::user()
->schedules()
->where('due_at', '>=' , Carbon::now())
->orWhereHas('scheduledYards', function ($query) {
$query->where('completed', false);
})->get();
$schedules = $schedules->sortBy('due_at');
return ScheduleResource::collection($schedules);
This works perfectly fine, but for some reason it is duplicating this for each user it is attached to. i.e if 3 users have this schedule then it is returned 3 times for the Authenticated user.
User Model:
public function schedules()
{
return $this->belongsToMany('App\Models\Schedule');
}
Schedule Model:
public function users() {
return $this->belongsToMany('App\Models\User');
}
If I remove the orWhereHas() it will return a single object. What am I doing wrong here and how can I return a single object based on the requirements above?

In Schedule Model, you need to change the relationship type. i assuming its one to many relationship between users and schedules. in that case change users() to user() and method body as below.
public function user() {
return $this->belongsTo('App\Models\User');
}

In User model the correct relationship should be defined as:
public function schedules()
{
return $this->belongsTo('App\Models\Schedule');
}

Please try with distinct. For example,
public function schedules()
{
return $this->belongsToMany('App\Models\Schedule')->**distinct**();
}

Related

Laravel retrieve multiple relationships

I have a laravel project where a User can have many Client class. The Client can have many Session and and a Session can have many Assessment and many Plan. I am using hasManyThrough on the Client to get Assessment and Plan. Each Assessment and Plan has a review_date timestamp saved into the database.
What I'd like to do is get all the Assessment and Plan for any Client with their review_date as today. Ideally something like:
$events = Auth::user()->reviews()->today();
What I don't know how to do it make the reviews function, because it's essentially combining 2 relationships.
Can anyone help me out?
User.php
public function clients()
{
return $this->hasMany(Client::class);
}
public function assessments()
{
return $this->hasManyThrough(Assessment::class, Client::class);
}
public function plans()
{
return $this->hasManyThrough(Plan::class, Client::class);
}
public function reviews()
{
// return all assessments and plans
}
public function scopeToday(Builder $query)
{
$query->whereDate('review_date', Carbon::today());
}
Client.php
public function assessments()
{
return $this->hasManyThrough(Assessment::class, Session::class);
}
public function plans()
{
return $this->hasManyThrough(Plan::class, Session::class);
}
Session.php
public function assessments()
{
return $this->hasMany(Assessment::class);
}
public function plans()
{
return $this->hasMany(Plan::class);
}
You can get a collection from both methods, so you could simply merge the 2 together. (Be warned, this will lead to ugly code later when you have to check object types during the loop.) You can't chain the scope method, since you aren't getting back a relationship object, but you could pass the date as a parameter instead, or just fix it at today's date if you'll never need other dates.
public function reviews(Carbon $date)
{
return $this
->assessments()
->whereDate('review_date', $date)
->get()
->toBase()
->merge(
$this->plans()->whereDate('review_date', $date)->get()->toBase()
)
->sortBy('review_date');
}
And then call it like this:
$date = now();
$events = Auth::user()->reviews($date);

Laravel one to one (polymorphic) not working only on specific model

I am facing a super weird issue.
I have 3 tables and their equivalent model:
App\User
public function company() {
return $this->morphTo();
}
App\Supplier
public function user() {
return $this->morphOne(User::class, 'company');
}
App\Company
public function users() {
return $this->morphMany(User::class, 'company');
}
For some reason the relationship on App\Supplier does not work, but all the other works normal, I can even get the supplier if I have the user:
$supplier = \App\Supplier::find(1);
$company = \App\Company::find(2);
$supplieruser = \App\User::find(1);
$supplier->user //THIS RETURN NULL
$company->users //return collection of users normally
$suppplieruser->company //returns an instance of supplier model
I have tried, changing the name of the relationship and nothing.
Any idea?
In case someone find this in the future... the relationship was not working because I had in my AppServiceProvider the following:
Relation::morphMap([
.....
'supplier_to_supplier' => 'App\Supplier',
.....
]);
It seems that registering it here will affect all the morphs from that model.

Laravel Model must return a relationship instance

My website has comments. These comments can have "votes", upvotes and downvotes.
I have a Comment Model and a CommentVote model.
In my comment model I have a functions that returns the votes:
public function votes() {
return $this->hasMany('App\CommentVote', 'comment_id');
}
public function upvotes() {
return $this->hasMany('App\CommentVote', 'comment_id')->where('vote', 1);
}
public function downvotes() {
return $this->hasMany('App\CommentVote', 'comment_id')->where('vote', -1);
}
Notice that upvotes are stored in the database in a tinyInt as 1 and downvotes are stored as -1
In my CommentVote model I have the belongsTo relationship:
public function comment() {
return $this->belongsTo('App\Comment');
}
Now I want to have a function that calculates the total "score" of the comment. Total upvotes minus total downvotes.
I try to make a function that counts all the upvotes - all the downvotes.
public function score() {
return $this->upvotes()->count() - $this->downvotes()->count();
}
This returns the error:
App\Comment::score must return a relationship instance.
In fact using the count() anywhere will return this error, despite it working fine in my other Models.
Doing something simple like:
public function voteCount() {
return $this->hasMany('App\CommentVote', 'comment_id')->count();
or even
return $this->votes()->count();
}
will return the error:
App\Comment::voteCount must return a relationship instance.
Why is this happening?
EDIT:
Here is the controller, as per requests in the comments:
public function getSubmission($subchan, $id, $URLtitle) {
$submission = Submission::where('id', $id)->first();
$comments = Comment::where('submission_id', $submission->id)->where('parent_id', NULL)->orderBy('created_at', 'desc')->get();
$comments = $comments->sortByDesc(function($comment){
return count($comment['upvotes']) - count($comment['downvotes']);
});
if (!$submission) {
return redirect()->route('home')->with('error', 'Submission not found.' );
}
return view('submissions.submission')
->with('submission', $submission)
->with('navSubchan', $submission->getSubchan->name)
->with('submissionPage', 1)
->with('comments', $comments)
;
}
I suspect you're doing $model->score, which is going to look for a function called score(), but in a specific manner that expects that function to return a HasMany, HasOne, BelongsTo etc. style relationship object.
Consider an accessor function instead.
public function getScoreAttribute() {
return $this->upvotes()->count() - $this->downvotes()->count();
}
allows you to do $model->score successfully.

Laravel 5 - Defining Two Relationships Between Models

I'm learning Laravel, and really OOP in general. I've followed several YouTube tutorial series, that teach you to create a blog in Laravel.
I'm building a task app for a brewery, and I'm trying to define the relationships between the users and the tasks. So I have two models: User.php and Task.php. I had no problem defining the user in a hasMany tasks relationship, and reciprocally, a task belongsTo a user. Where I'm confused is that I'd like to also have a user belong to the task as well. I have two MySQL columns, one with the heading of "user_id" and the other with "user_assigned_id". What I want is that a user has many tasks, but a task also has one assigned user, the idea being that the user that created the task might assign the task to another user. I've found several tutorials on creating relationships between three models, such as a user owning several messages, but only having one address, so I figured that I could just treat two models as if they were three models and connected the User model back to the Task model in a hasOne relationship, but I'm having a really hard time passing that through to the Controller and View.
Here is the relevant code in each file:
User.php
public function tasks()
{
return $this->hasMany('App\Task');
}
Task.php
public function user()
{
return $this->belongsTo('App\User');
}
// Added an user_assigned_id relationship
public function user_assigned()
{
return $this->hasOne('App\User', 'name', 'user_assigned_id');
}
DashboardController.php
public function index()
{
$user_id = auth()->user()->id;
$now = Carbon::now();
$tasks_assigned = Task::orderBy('date', 'asc')->whereDate('date', '>=', $now)->where('user_assigned_id', '=', $user_id)->user_assigned()->where('name', '=', 1)->get();
$tasks_created = Task::orderBy('date', 'asc')->whereDate('date', '>=', $now)->where('user_id', '=', $user_id)->get();
return view('dashboard')->with('tasks_assigned', $tasks_assigned)->with('tasks_created', $tasks_created);
}
I've gotten a bit turned around in the Controller, so I'm not sure if I messed something up there. Basically, I'm getting results from tasks owned by the logged in user, but not assigned to the logged in user.
You can just add a second relationship defined on your Task.php Model and assign a different agent based on user_assigned_id. You can manipulate it as expected via Eloquent.
Task.php
public function user() {
return $this->belongsTo('App\User');
}
public function assignedUser() {
return $this->belongsTo('App\User', 'user_assigned_id');
}
Then on DashboardController.php
$tasks_assigned = Task::orderBy('date', 'asc')->whereDate('date', '>=', $now)->where('user_assigned_id', '=', $user_id)->get();
should work
public function user()
{
return $this->belongsTo('App\User');
}
// Added an user_assigned_id relationship
public function assignee()
{
return $this->belongsTo('App\User', 'user_assigned_id');
}
The relationship is still a belongsTo, you just need to provide the column where the foreign key is held.
Other files:
User.php
public function ownedTasks()
{
return $this->hasMany('App\Task');
}
public function assignedTasks()
{
return $this->hasMany('App\Task', 'user_assigned_id');
}
Dashboard Controller
public function index()
{
$now = Carbon::now();
$tasks_assigned = Auth::user()->assignedTasks()->where('date', '>=', $now)->get();
$tasks_created = Auth::user()->ownedTasks()->where('date', '>=', $now)->get();
return view('dashboard')->with(compact('tasks_assigned', 'tasks_created'));
}

Laravel Jenssegers MongoDb Relationships not working?

I'm trying to setup some simple favoriting for my app using Laravel/Jenssegers MongoDB
I have two models:
class Item {
public function favorites()
{
return $this->hasMany('App\Models\User', 'favorites');
}
}
class User {
public function favorites()
{
return $this->hasMany('App\Models\Item', 'favorites');
}
}
So an item can have many users and a user can have many items or "favorites".
When I try to run a simple query like:
Item::with('favorites')->get();
The relationship for favorites is there but an empty array.
The favorites table is simple and just has three columns:
_id, item_id, user_id
I've also tried using embedsMany with no luck:
return $this->embedsMany('App\Models\User', 'favorites');
I've also tried every combination of parameters.
return $this->embedsMany('App\Models\User', 'favorites', 'building_id', 'user_id');
return $this->embedsMany('App\Models\User', 'favorites', 'user_id', 'building_id');
return $this->hasMany('App\Models\User', 'favorites', 'building_id', 'user_id');
return $this->hasMany('App\Models\User', 'favorites', 'user_id', 'building_id');
Strange results when using:
return $this->hasMany('App\Models\User', 'favorites', 'building_id', 'user_id');
Only in this situation it returns ALL users, even though favorites has only one record.
Also trying to debug using getQueryLog just gives me an empty array at all times.
print_r(\DB::connection('mongodb')->getQueryLog());
I've done this using mysql and have never had issues. So not really sure where the issues are coming from.
Can you try these instead, I know its the same thing but might do the trick :
use App\User;
use App\Item;
class Item {
public function favorites()
{
return $this->hasMany('User');
}
}
class User {
public function favorites()
{
return $this->hasMany('Item');
}
}
class Favourite {
public function users()
{
return $this->belongsTo('User');
}
public function items()
{
return $this->belongsTo('Item');
}
}
Also add inverse of the above relations like: belongsTo.
and try this query then :
//Just for testing purpose, if raw query returns right result
$items = DB::table('items')
->join('favorites','items.id','=','favorites.id')
->get();

Resources