Laravel eloquant belongsToMany get records belongs to relationship - eloquent

I'm using many to many relationship with products and product_categories tables using product_product_category pivot table.
Product model
class Product extends Model
{
public function product_categories() {
return $this->belongsToMany(ProductCategory::class, 'product_product_category');
}
}
ProductCategory model
class ProductCategory extends Model {
public function products() {
return $this->belongsToMany(Product::class, 'product_product_category');
}
}
What I need to do is when I supply an array of categories need to get products only with these categories. This is my code
$selectedCategotries = array(1, 2);
$products = Product::with(['product_categories' => function($q) use ($selectedCategotries){
$q->whereIn('product_categories.id', $selectedCategotries);
}])->get();
But I get all the products instead. It will be a great help if you can supply a solution for me.

Finally, I found an answer with whereHas. Adding the answer for anyone who come up with the same issue.
$products = Product::whereHas('product_categories', function ($q) use ($selectedCategotries) {
$q->whereIn('product_categories.id', $selectedCategotries);
})->get();

Related

Yii2: How to do a simple join query?

I am learning how to do simple queries using the Yii2 framework. I use PostgreSQL.
I am trying to join two tables and get the data from both tables with a where condition.
The tables are called Admins and Persons.
The join use field called idadm.
The condition is idadm = 33. This works great but the result has data only from the Admins table and I need data from the other table.
Here is my example:
$query = \app\models\Admins::find()
->select('*')
->leftJoin('persons', 'persons.idadm = admins.idadm')
->where(['admins.idadm' => 33])
->with('persons')
->all();
I am following the Yii2 official guide: http://www.yiiframework.com/doc-2.0/guide-db-active-record.html
Update: Here I show the updated code that doesn't solve de problem:
You need to write all column name in select().
$query = \app\models\Admins::find()
->select('admin.*,persons.*') // make sure same column name not there in both table
->leftJoin('persons', 'persons.idadm = admins.idadm')
->where(['admins.idadm' => 33])
->with('persons')
->all();
And also you need to define person table attributes in Admin model.
Second way is get records as array,so you dont need to define attributes in Admin model.
$query = \app\models\Admins::find()
->select('admin.*,persons.*') // make sure same column name not there in both table
->leftJoin('persons', 'persons.idadm = admins.idadm')
->where(['admins.idadm' => 33])
->with('persons')
->asArray()
->all();
Ensure that active record has required relations, e.g. something like follows:
class Admins extends \yii\db\ActiveRecord {
public function table() {
return "admins";
}
public function getPersons()
{
return $this->hasMany(Person::className(), ['idadm' => 'idadm']);
}
}
class Person extends \yii\db\ActiveRecord {
public function table() {
return "persons";
}
}
Then use joinWith to build query:
$query = Admins::find()
->joinWith('persons')
->limit(1);
$result = $query->createCommand()->getSql();
echo $result;
Here is produced query:
SELECT `admins`.* FROM `admins`
LEFT JOIN `person` ON `admins`.`idadm` = `person`.`idadm` LIMIT 1

how to join 3 table in laravel using database mongodb?

Our Application has 3 Model "Notification", "Postlike" and "Post"
In Notification Model:
public function postlike()
{
return $this->belongsTo('App\Models\PostLikes', 'postlist');
}
public function post()
{
return $this->hasMany('App\Models\PostLikes', '_id', 'c_post_id');
}
In Postlike Model:
public function postlist()
{
return $this->hasMany('App\Models\Post', '_id', 'c_post_id');
}
In Notification Repository: (Query)
public function getnotification($userId)
{
$notification = $this->makeModel()
->with('post')
->with('postlike')
->with('notification')
->orderBy('created_at' , 'desc')
->where('replied_id', $userId)
->get();
return $notification;
}
For more information we have attached following Image
enter image description here
When i firt saw your post, i thought your problem could be solved using Laravel's built-in eager loading, so it lets you do something like this:
$notification = $this->makeModel()
->with('post', 'postlike', 'postlike.postlist')
//...
->get();
If thats your case, these links shoud do the trick:
https://laracasts.com/discuss/channels/eloquent/eager-load-multiple-nested-relationships
laravel eloquent eager load multiple nested relationships
Im not sure, but it seems a little bit odd to me, that 'Notification' Model has two relations with 'Postlike' model. Maybe you should consider using some pivot table.
Hope it helps,
Notification Model :
public function postlike()
{
return $this->belongsTo('App\Models\PostLikes', 'c_post_id');
}
Query:
$notification = $this->makeModel()
{
->with('post', 'postlike', 'postlike.postlist')->get()
}

eloquent refer to a column of a related a model

I have three tables:
categories
id, title
products
id, name
categories_products
id, category_id, product_id
I have also setup the according models and relationships (both have belongsToMany of the other)
Now I want to get all products belonging to a category
Category::where('title','Electronics')->first()->products()->limit(10)->get(['products.name']);
which works fine, but I also want to include the category title for each product as well:
Category::where('title','Electronics')->first()->products()->limit(10)->get(['products.name','category.title']);
However it returns: Column not found category.title
I thought that the relation would take care of it.
EDIT: Models -->
Category:
class Category extends Model
{
protected $fillable = array('title');
public function products()
{
return $this->belongsToMany('Product', 'categories_products', 'category_id', 'product_id');
}
}
class Product extends Model
{
protected $fillable = array('name');
public function categories()
{
return $this->belongsToMany('Category', 'categories_products', 'product_id', 'category_id');
}
}
The reason you're getting the error is because get() works just like select() and because you're running the category query and then running the product query after there is no categories table to reference for the select.
Look into Eager Loading. It will help with a lot of these kinds of issues. Your query can be written as:
Product::select('id', 'name')
->with(['categories' => function($query) {
return $query->select('id', 'title');
}])
->whereHas('categories', function($query) {
return $query->where('title', 'Electronics');
})
->limit(10)
->get();
Because we are lazy loading you NEED the id column on each model so Laravel knows where to attach the relationships after the queries are run.
The with() method above will eager load the categories relationship and the whereHas() method puts a relationship constraint on the current query.
UPDATE
Similar query from Category model:
$category = Category::where('title','Electronics')
->with(['products' => function($query) {
return $query->select('id', 'name')->limit(10);
}])
->first(['id', 'title']);
Then access the products with:
$category->products

Eloquent ORM One to many query is not working

I am working with laravel 5.4. I have created countries and states table.
countries table looks like below
And my states table is :
Here, I have written join query as shown in below. It works perfect.
$state = DB::table($this->tbl_states)
->join($this->tbl_countries, $this->tbl_countries.'.id', '=', $this->tbl_states.'.country_id')
->select($this->tbl_states.'.*', $this->tbl_countries.'.name as country_name')
->whereNull($this->tbl_states.'.deleted_at')
->paginate(10)
But, Instead of writing this query I want to use Eloquent ORM so what query should I have to write?
In Country model I have create function that looks like below :
public function states()
{
return $this->hasMany('state');
}
And in State model I have write function that looks like below :
public function country()
{
return $this->hasOne('country');
}
In Country model try this:
public function states()
{
return $this->hasMany(App\State::class);
}
And in State model:
public function country()
{
return $this->belongsTo(App\Country::class);
}
And then $country->states will give you all states of this country. As well as $state->country will return state's country.
Official Docs: Eloquent: Relationships

How to get result by joining two collections (tables) [Cakephp/MongoDB]

I am using https://github.com/ichikaway/cakephp-mongodb.git plugin for accessing mongodb datasource.
I have two Models: Teachers and Subject. I want joint find result on Teacher and Subject.
Here are my two models:
Teacher:
<?php
class Teacher extends AppModel {
public $actsAs = array('Containable');
public $hasOne = array('Subject');
public $primaryKey = '_id';
var $mongoSchema = array(
'name'=>array('type'=>'string'),
'age'=>array('type'=>'string'),
'subjectid'=>array('type'=>'string'),
'created'=>array('type'=>'datetime'),
'modified'=>array('type'=>'datetime'),
);
Subject:
<?php
class Subject extends Model {
public $actsAs = array('Containable');
public $belongsTo= array('Teacher');
public $primaryKey = '_id';
var $mongoSchema = array(
'name'=>array('type'=>'String'),
'code'=>array('type'=>'String'),
'created'=>array('type'=>'datetime'),
'modified'=>array('type'=>'datetime')
);
In Teachers Controller to get joint result, I did:
$results = $this->Teacher->find('all',array('contain'=>array('Subject')));
$this->set('results', $results);
But I am not getting any result from Subjects Collections.
Here is what I am getting:
array(5) {
[0]=>
array(1) {
["Teacher"]=>
array(7) {
["_id"]=>
string(24) "52e63d98aca7b9ca2f09d869"
["name"]=>
string(13) "Jon Doe"
["age"]=>
string(2) "51"
["subjectid"]=>
string(24) "52e63c0faca7b9272c09d869"
["modified"]=>
object(MongoDate)#78 (2) {
["sec"]=>
int(1390820760)
["usec"]=>
int(392000)
}
["created"]=>
object(MongoDate)#79 (2) {
["sec"]=>
int(1390820760)
["usec"]=>
int(392000)
}
}
}
I am a cakephp/mongoDB rookie only, Please guide me to get the desired result.
Edit: I read that mongoDb don't support Join Operation. Then How to manually do it? I mean I can write two find query on each Model, then how to combine both array and set it to view?
As you said, MongoDB does not support joins. Documents in query results come directly from the collection being queried.
In this case, I imagine you would query for Teacher documents and then iterate over all documents and query for the Subject documents by the subjectid field, storing the resulting subject document in a new property on the Teacher. I'm not familiar with this CakePHP module, but you may or may not need to wrap the subjectid string value in a MongoId object before querying. This depends on whether or not your document _id fields in MongoDB are ObjectIds or plain strings.
If Subjects only belong to a single teacher and you find that you never query for Subjects outside of the context of a Teacher, you may want to consider embedding the Subject instead of simply storing its identifier. That would remove the need to query for Subjects after the fact.