Doesn't Laravel eloquent hasmany allow multiple columns? - eloquent

return $this->hasMany(Key::class, 'order_id' , 'order_id')->with('supplier');
How can I add a 2nd condition here, both order_id must be equal to order_id and game_id must be equal to game_id.

I think you can use this way to have multiple conditions
public function whatever()
{
return Whatever::where(function ($query) {
return $query->where('order_id', $this->order_id)
->where('game_id', $this->game_id);
});
}

Related

Objection.js alias to relationMapping

I have a working relation mapping with Objection / Knex / Sql server that is causing a problem when the results are paged.
components: {
relation: BaseModel.HasManyRelation,
modelClass: Component,
join: {
from: 'vehicle.id',
to: 'component.vehicleID'
}
}
When I use withGraphFetched to get related components for every vehicle, the query fails if I include the 'vehicle.id' in the original select.
static getFieldList() {
return [
'id',
'mark',
'model'
].
}
static getPagedList(page, pagelength) {
return this.query()
.select(this.getFieldList())
.withGraphFetched('components')
.page(page, pagelength)
}
Now, when paging is done, Objection / Knex runs a second query after the primary one to fetch the total number of rows. Objection adds 'vehicle.id' from the relation mapping to the query, thus causing the query to fail because the column 'id' is now fetched twice for the subquery.
exec sp_executesql #statement=N'select count(*) as [count] from (select [id], [mark], [model], [id] from [vehicle]) as [temp]'
My question is, how can this be avoided? Can I use some alias in the relation mapping? I tried 'vehicle.id as vehicleFK' in the relation mapping but that caused the withGraphFetched to not run at all.
there might be two ways to try to solve your issue
get rid of component's id column
const componentsSelectList = ()=>{
// select columns you need from components without the id column
return [
'column1', // columns you need
'column2'
]
}
static getPagedList(page, pagelength) {
return this.query()
.select(this.getFieldList())
.withGraphFetched('components',{minimize: true})
.modifyGraph('components',builder => builder.select(componentsSelectList()))
.page(page, pagelength)
}
use ref function from objection to reference the id column from which table
const {ref} = require('objection')
...
static getFieldList() {
return [
ref('vehicle.id'),
'mark',
'model'
].
}
static getPagedList(page, pagelength) {
return this.query()
.select(this.getFieldList())
.withGraphFetched('components')
.page(page, pagelength)
}
...

Laravel eloquent limit query

I have 3 tables TAble, TableB and TableC.
each one with 1 milion registers.
And i have the Laravel eloquent query.
$list= TableA::with([
'TableB',
'TableC'
])
->whereIn('field1',['A','B','C'])
->where('created_at','>=','2018-01-01') ->orderBy('fieldC', 'ASC')->orderBy('created_at', 'ASC')
->get()
->take(50) ;
TableA have TableB and TableC mapping this way.
public function TableB(){
return $this->belongsTo('TableB', 'fk_id', 'id');
}
public function TableC(){
return $this->hasMany('TableC');
}
How can i execute this query limiting number of registes in "TableB" and "TableC".
if i use take() it only limits the final result.
What do you want to do?
If you want to process data in chunks use
->chunk(50, function ($data) use ($variable) {
//process
});
If you want display data in tables with pages use paginate.

Laravel Eloquent Many-To-Many Query Producing Extra null WHERE clause

I'm using Eloquent to produce results from a query comprised of three tables:
photos (id)
photos_to_photosets (photo_id, photoset_id)
photosets (id)
My models have their many-to-many relationships defined as:
class Photo extends Model
{
public function photosets()
{
return $this->hasMany(PhotoSet::class, 'photos_to_photo_sets');
}
}
And
class PhotoSets extends Model
{
public function photos()
{
return $this->belongsToMany(Photo::class, 'photos_to_photo_sets');
}
}
Now, to fetch results I'm forced to use the following Eloquent code:
$photoData = $this->photoSets->photos()
->orWhere('photo_set_id', '=', $id)
->get();
This produces the following query:
SELECT * FROM `photos`
INNER JOIN `photos_to_photo_sets`
ON `photos`.`id` = `photos_to_photo_sets`.`photo_id`
WHERE `photos_to_photo_sets`.`photo_set_id` is null
OR `photo_set_id` = ?
This query works, but I can't seem to remove WHERE `photos_to_photo_sets`.`photo_set_id` is null from the query.
I've tried to just use ->where('photo_set_id', '=', $id) but the null clause still remains; even worse it produces the following WHERE clause:
... WHERE `photos_to_photo_sets`.`photo_set_id` IS NULL
AND `photo_set_id` = ?
Is there any way, utilizing Eloquent, to remove this null WHERE clause segment?
Ideally, I'd like to end up with the following query:
SELECT * FROM `photos`
INNER JOIN `photos_to_photo_sets`
ON `photos`.`id` = `photos_to_photo_sets`.`photo_id`
WHERE `photo_set_id` = ?
Thank you in advance for any help!
UPDATE
Based off #Jonas Staudenmeir's answer, the null WHERE clause has been removed.
To achieve this, I set the photoSet's model ID prior to running the query. The resulting code was:
$this->photoSets->id = $photoset_id;
$photoData = $this->photoSets->photos()->get();
Which produced:
SELECT * FROM `photos`
INNER JOIN `photos_to_photo_sets`
ON `photos`.`id` = `photos_to_photo_sets`.`photo_id`
WHERE `photo_set_id` = ?
The injected model doesn't have an id:
$this->photoSet->id = $id;
Then you don't need the additional constraint:
$photoData = $this->photoSets->photos;

Sequelize bulk update with inner join

I am currently working with Sequelize and can not figure out how to update bulk when im associating two tables together. I have the follow:
Tables:
members
user_id
channel_id
all
activities
user_id
channel_id
I am trying to update members.all when the user_ids match, members.channel_id is 2 and activities.channel_id is not 2.
Here is working Postgresql:
UPDATE members AS m
SET "all" = true
FROM activities AS a
WHERE m.user_id = a.user_id
AND m.channel_id = 2
AND a.current_channel != 2;
Is this possible to do is sequelize? How do include a.current_channel != 2 into my current update?
Member.update(
{ all: true },
{ where: { channel_id: channelId } },
)
When I try to add an include it does not work.
I think you can't do something like that using Sequelize update method. I would use the include option in a findAll method, but as far as I can see on the documentation, there is no include option for the update method.
You could use a raw query to use directly the query.
sequelize.query("UPDATE members AS m SET "all" = true FROM activities AS a WHERE m.user_id = a.user_id AND m.channel_id = 2 AND a.current_channel != 2").spread((results, metadata) => {
// Results will be an empty array and metadata will contain the number of affected rows.
});
Generally, i use this hack
models.findAll({
where: {
// which models to update
}
}).then(targets => {
models.target.update({
// your updates
},{
where : {
target_primary_key: targets.map(t => t.primary_key)
}
})
})

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