How to GroupBy in Relationship? - laravel

I have post table
| ID | TITLE | SLUG | CONTENT | COMMENTS_COUNT |
and i have post_reactions table
| ID | USER_ID | TYPE | POST_ID |
I want to make a relationship that what reactions that post have

You can directly do it by model.
public function postrelation()
{
return $this->hasMany(PostRelation::class)->groupBy('type');
}
Or
Post::with(['postrelation' => function($q){
$q->groupBy('type');
}])->get();

You can use callback function for grouping your relations describe at below.
Post::with(['post_reactions' => function($query){
$query->groupBy('TYPE');
}])->get();

You can make relation with the help of follwing syntax in the Model Class
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model {
/**
* Get the phone record associated with the user.
*/
public function phone(){
return $this->hasOne('App\Phone');
}
}

Related

how can i get around this belongsToMany pivot error

i have the following relationship for a belongsToMany relationship
Table:| users | forums |forum_user (pivot table)
| id | id | id
| name | name | user_id
| email | | forum_id
| | |
and have defined the following relationships
pubic function forums() {
return $this->belongsToMany(Forum::class);
}
on the user model and
pubic function forums() {
return $this->belongsToMany(Forum::class);
}
on the forum model
now when i try to do this
User::first()->forums()->get()
it returns the error
Symfony\Component\Debug\Exception\FatalErrorException
Type of Illuminate\Database\Eloquent\Relations\Pivot::$ must be array (as in class
Illuminate\Database\Eloquent\Model)
how can i get around this error
i'm currently using laravel 6 in my project
try this:
User::first()->forums->get();
And maybe rewrite the relation on User model to:
return $this->belongsToMany(Forum::class, 'forum_user', 'user_id', 'forum_id');
On the forum model shouldnt relation reflect user?
pubic function forums() {
return $this->belongsToMany(Forum::class);
}
Shouldnt this be
pubic function users() {
return $this->belongsToMany(User::class);
}

Laravel Eloquent Many to Many Relationship between three Models

Consider I have the following table structures for tables countries, products and suppliers:
countries
------------------------
id
name
code
product
------------------------
id
name
price
suppliers
------------------------
id
name
A product can be sold in different countries but supplier of that product can be different. With that keeping in mind, I made a relations table to keep track of which supplier is delivering which product in which country:
relations
------------------------
country_id
product_id
supplier_id
Let's say I have a product A which I need to store in country US and CA but the suppliers for these countries are X and Y respectively. The structure would look something like this:
countries
-------------------------------
id | name | code
-------------------------------
1 | United States | US
2 | Canada | CA
product
-------------------------------
id | name | price
-------------------------------
1 | A | 3.99
suppliers
------------
id | name
------------
1 | X
2 | Y
relations
-------------------------------
country_id | product_id | supplier_id
-------------------------------
1 | 1 | 1
2 | 1 | 2
My question is how can I use Eloquent Relationships to this table since many-to-many relationships only work on two tables. Is there any other workaround regarding this? Or is there any other efficient way to implement this scenario?
Thank you for your help.
There is no built-in way to make a relation using three tables. Whenever I encounter something like this myself, the best solution seems to be to make an in-between model that has relations to the three tables.
So in your case, I would create a SupplierProduct that has the relations country, supplier and product.
i have also same scenario class have multiple DaysClassDetails
use this function in your parent model
public function classType()
{
return $this->hasMany('App\DaysClassDetails(middlemodel)');
}
and DaysClassDetails have multiple DaysClassTimeDetails
public function classTime()
{
return $this->hasMany('App\DaysClassTimeDetails(lastchildmodel)');
}
public function classType(){
return $this->belongsTo('App\ManageClass(parentmodel)');
}
As Jerodev suggested, I made an intermediate model SupplierProduct. Instead of making many-to-many relationships, I made one-to-many relationships with SupplierProduct and retrieved data using with functions to retrieve all data related to that record.
This is how my Models look like (database structure is same as described in question):
SupplierProduct.php
namespace App;
use Illuminate\Database\Eloquent\Model;
class SupplierProduct extends Model {
public function country() {
return $this->belongsTo(Country::class);
}
public function product() {
return $this->belongsTo(Product::class);
}
public function supplier() {
return $this->belongsTo(Supplier::class);
}
}
Country.php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Country extends Model {
public function products() {
return $this->hasMany(SupplierProduct::class)->with('product', 'supplier');
}
}
Product.php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Product extends Model {
public function products() {
return $this->hasMany(SupplierProduct::class)->with('country', 'supplier');
}
}
Supplier.php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Supplier extends Model {
public function products() {
return $this->hasMany(SupplierProduct::class)->with('country', 'product');
}
}

Override primary key with foreign key in hasMany relation using laravel

Here are my tables
Posts
id | name | created_At
Comments
id | comment | post_id | created_at
Post Model
function comments(){
return $this->hasMany('App\Models\Comment','id','post_id');
}
PostsController
function index()
{
Post::with('comments')::get();
}
Now how can i get list of all posts along with comments?
I am trying to match post_id in the child table.
In Your Post Model:
public function comments()
{
return $this->hasMany('App\Model\Comment');
}
In Your Post Controller :
use Illuminate\Http\Request;
function index(Request $request)
{
$posts=Post::with('comments')->get();
// in json
return response()->json($posts);
// in your view
//return view('viewname')->with('posts',$posts);
}

Get all posts and check if user liked each post

I'm trying to create an Eloquent query that fetches all posts and checks if the user liked each of those posts.
I have the following models:
Post.php
class Post extends Eloquent {
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'posts';
public function user()
{
return $this->belongsTo('User');
}
public function likes()
{
return $this->hasMany('Like');
}
}
Like.php:
class Like extends Eloquent {
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'likes';
}
And your typical User model as well.
My DB structure is the following:
posts table:
+----+---------+---------+
| id | user_id | message |
+----+---------+---------+
users table:
+----+----------+
| id | username |
+----+----------+
likes table:
+----+---------+---------+
| id | post_id | user_id |
+----+---------+---------+
Right now, my query only returns all posts, but how can I modify it to return all posts and check if the user liked each post?
Route::get('/', array('as' => 'index', function()
{
$posts = Post::all();
return View::make('index')->with('posts', $posts);
}));
Thanks!
What about a left join between the posts table and the likes table, filtering by the actual user's id?
$post = DB::table('post')
->select(DB::raw('message, likes.user_id IS NOT NULL as liked'))
->leftJoin('likes', 'users_id', '=', 'likes.user_id')
->where('likes.user_id', '=', $curent_user_id)
->get();
I have no way to test it now, but I hope it might give you some inspiration :)
You can grab the likes with the post for that specific user. Try this..
Post::with(['likes' => function() use ($user_id) { $q->where('user_id','=', $user_id); }])->all();
It will return blank array if user haven't like the post.

Polymorphic Eloquent relationships with namespaces

I've tried to implement polymorphic relationships. They work perfectly... However, I'm trying to reduce my database size as much as possible so... I've this
Table action
| id | realatable_type | relatable_id
| 1 | Lion\People | 65
| 2 | Lion\Company | 13
Obviously I've this
<?php namespace Lion;
class Company extends \Eloquent { ... }
class People extends \Eloquent { ... }
Is there any way to store only "People" or "Company" assuming that the namespace is always going to be "Lion"?
Since Laravel 4.1, inside your model (in this case Company and People) you can set the protected property $morphClass to whatever you want.
<?php namespace Lion;
class Company extends \Eloquent {
protected $morphClass = 'Company';
}
Now in your table you can store the type without the namespace:
| id | realatable_type | relatable_id
| 2 | Company | 13
I believe the best solution here (for database size at least) would be to simply change readable_type to ENUM('Lion\Company', 'Lion\People').
That being said, if you really want to handle this on Laravel side, you'll have to create new classes extending from Illuminate\Database\Eloquent\Relations\Morph* ¹ and overwrite their constructors ² as to get only the last value after a dash, on $morphClass. Something like this:
<?php
use \Illuminate\Database\Eloquent\Model;
use \Illuminate\Database\Eloquent\Builder;
class MyMorphOne extends \Illuminate\Database\Eloquent\Relations\MorphOne {
public function __construct(Builder $query, Model $parent, $type, $id) {
parent::__construct($query, $parent, $type, $id);
$this->morphClass = substr($this->morphClass, strrpos($this->morphClass, '\\') + 1);
}
}
Then, extend your own model or base model, to overwrite morphOne, morphMany and morphToMany methods as to make use of your new extended classes. Something like this:
<?php
class People extends Eloquent {
// ...
public function morphOne($related, $name, $type = null, $id = null) {
$instance = new $related;
list($type, $id) = $this->getMorphs($name, $type, $id);
$table = $instance->getTable();
return new MyMorphOne($instance->newQuery(), $this, $table.'.'.$type, $table.'.'.$id);
}
}
* = One, Many and ToMany
Which are actually inherited from MorphOneOrMany on MorphOne and MorphMany.

Resources