Laravel 5.3 get belongsToMany and count pivot - php

I have next models:
class Polling extends Model
{
/**
* #return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function participants()
{
return $this->belongsToMany(Participant::class, 'participant_poll', 'poll_id');
}
/**
* #return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function results()
{
return $this->belongsToMany(Participant::class, 'poll_results', 'poll_id');
}
}
class Participant extends Model
{
public function polls()
{
return $this->belongsToMany(Polling::class);
}
public function results()
{
return $this->belongsToMany(Polling::class);
}
}
poll_results - pivot table have structure: id, poll_id, participant_id.
I need view next table:
№|participant.name|Count vote|
1|Mike |15 |
2|................|10 |
..............................
Count vote get pivot table poll_results.
Help please, write query.
$poll = Polling::first();
$poll->participants()->get();

You may want to use withCount() method.
If you want to count the number of results from a relationship without actually loading them you may use the withCount method, which will place a {relation}_count column on your resulting models
Your query would look like this one:
Participant::withCount('polls')->get();
This will add new property to results called polls_count

Related

Correct way to set up this Laravel relationship?

I'm after a bit of logic advice. I am creating a system where users login and register their participation at an activity. They can participate at an activity many times. What is the best way to do this? I want to ensure I can use eloquent with this rather than creating my own functions.
I am imagining...
Users:
id
Activitys:
id
name
Participations:
id
user_id
activity_id
time_at_activity
I want to later be able to do such things as:
$user->participations->where('activity_id', 3)
for example.
What is the best way to set this up? I had in mind..
User: hasMany->Participations
Activity: belongsTo->Participation
Participation: hasMany->Activitys & belongsTo->User
Does this look correct?
The users schema can relate to activities through a pivot table called participations:
/**
* Indicate that the model belongs to a user.
*
* #see \App\Model\User
*
* #return BelongsTo
*/
public function user()
{
return $this->belongsTo(User::class);
}
/**
* Indicate that the model belongs to many activity participations.
*
* #see \App\Model\Activity
*
* #return BelongsTo
*/
public function participations()
{
return $this->belongsToMany(Activity::class, 'participations');
}
$user->participations()->attach($activity);
You may want to add the reciprocal relationships. These can be separated out into traits for code reuse. ->attach(['participated_at' => now()])
You can use Many-to-Many Relationship.
Use Participation as your pivot table. Define relationships as
/* in User */
public function activity()
{
return $this->belongsToMany('App\Models\Activitys','participation','user_id','activity_id')->as('participation')->withPivot('time_at_activity');
}
/* in Activity */
public function user()
{
return $this->belongsToMany('App\Models\Users','participation','activity_id','user_id')->as('participation')->withPivot('time_at_activity');
}
DB schema
// App\User
public function participations()
{
return $this->hasMany('App\Participation');
}
// You may create App\Participation Model
// App\Participation
public function user()
{
return $this->belongsTo('App\User');
}
// Controller
$userParticipations = $user->participations->where('activity_id', 3);
// eager loading version
$userWithParticipations = $user->with(['participations' => function($q) { $q->where('activity_id', 3) }])->get();

Laravel Model recursion supress infinite loop

Having the following Laravel recursion in my model how do I avoid accidentally registered relation. What I mean: I have users and users can have many reportees and we want to get back the tree on a given user with the following snippet, which is works fine till the point if user is not a reportee to itself
/**
* User can have many Reporters
*
* #return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function hasreporters()
{
return $this->belongsToMany('App\User', 'reporting_to', 'acc_receiving_from_id', 'acc_reporting_to_id')
->where('status', 'A');
}
/**
* #return $this
*/
public function children()
{
return $this->hasreporters()->with(['children']);
}
where can I check in the loop if a given id is not equal to the parent id
In function children() you are use relation as query builder. Its not wrong way, but method->with()` search relation from its argument, then call it. Here is recursion :) Try:
public function children()
{
return $this->hasreporters();
}

How to merge hasMany relationships and return a relationship in Laravel?

I'm trying to merge 2 collections, because I need to search for records in multiple columns, team_one_id and team_two_id depending on if its an away game or home game.
This happens in function matches when trying to merge them. When I call merge on the first relationship, function matches doesn't return an actual relationship, but returns a collection.
Exception:
SQLSTATE[21000]: Cardinality violation: 1222 The used SELECT statements have a different number of columns (SQL: (select count(*) as aggregate from `matches` where `matches`.`team_one_id` = 1 and `matches`.`team_one_id` is not null and `winning_team_id` = 1) union (select * from `matches` where `matches`.`team_two_id` = 1 and `matches`.`team_two_id` is not null))
Code:
<?php
namespace App\Database;
use Illuminate\Database\Eloquent\Model;
class Team extends Model
{
protected $primaryKey = 'id';
protected $table = 'teams';
public $timestamps = false;
protected $guarded = ['id'];
public function homeMatches() {
return $this->hasMany('App\Database\Match', 'team_one_id');
}
public function awayMatches() {
return $this->hasMany('App\Database\Match', 'team_two_id');
}
public function matches() {
return $this->homeMatches()->union($this->awayMatches()->toBase());
}
}
Eloquent Relationships aren't designed to match one or the other field, they are designed to have one foreign key. You can run a query within your method to get the results you need without relying a relationship.
As discussed in the comments, if you want to re-use that query, contain that logic in a protected function.
protected function allMatchesQuery()
{
// This needs to be wrapped in a nested query or else your orWhere will not be contained in parentheses.
return Match::where(function($q) {
$q->where('team_one_id', $this->id)->orWhere('team_two_id', $this->id);
});
}
public function getMatches() {
return $this->allMatchesQuery()->get();
}
public function getRecentMatches() {
return $this->allMatchesQuery()->orderBy('date', 'DESC')->limit(10)->get();
}
You may try this:
public function matches() {
return $this->getRelationValue('homeMatches')->union($this->getRelationValue('awayMatches')->toBase());
}
Because of homeMatches() function return a Relation instance but the dynamic property returns a Collection.

Polymorphic relationshoip in Laravel

I'm trying to understand polymorphic relationship in Laravel. I know how it works in principle, but the choice of wording in Laravel is not intuitive in this part. Given the exanple,
namespace App;
use Illuminate\Database\Eloquent\Model;
class Like extends Model
{
/**
* Get all of the owning likeable models.
*/
public function likeable()
{
return $this->morphTo();
}
}
class Post extends Model
{
/**
* Get all of the product's likes.
*/
public function likes()
{
return $this->morphMany('App\Like', 'likeable');
}
}
class Comment extends Model
{
/**
* Get all of the comment's likes.
*/
public function likes()
{
return $this->morphMany('App\Like', 'likeable');
}
}
How do yo put in plain English sentence morphTo for instance? It is "belongsto"? and morphmany, hasMany? going further,
$post = App\Post::find(1);
foreach ($post->likes as $like) {
//
}
$likeable = $like->likeable;
morphToMany and morphByMany
How do you describe in plain english?
A polymorphic relationship means an object can have a relationship to more than one type of object. This is determined by two fields in the database rather the typical one foreign key field you would normally see.
Using the code you included in your question any type of object extending the Model class can have a relationship with a Like object. So you could have Comments and Posts that can have Likes associated to them. In your likes table you may have rows where 'likable_type' = 'post' and 'likable_id' = 1 or 'likable_type' = 'comment' and 'likable_id' = 4 for example.

Add relationship between two models

I have model 1 represent a table with (id1,par1, para2 ) and model 2 represent a table with (id2,para3)
I want to modify model 1 in order when I use
$mydata = model1::model()->findBySql('SELECT * FROM table1 ORDER BY id1 DESC');
this query return for me directly only where par1 > par3 (both of them are time), without adding the condition where . Or if thee is a method to add a condition where based in other model ?
class model1 extends CActiveRecord
{
public static function model($className=__CLASS__)
{
return parent::model($className);
}
public function tableName()
{
return 'table1';
}
}
Many thanks.
thanks for all comments, I solve it by using two cdbcreteria and make a condition between them
see my post here

Categories