简体   繁体   中英

Yii2 - Calling model functions on entire activeRecords?

What I am trying to do

I want to query a specific set of records using active model like so

$jobModel = Jobs::find()->select('JOB_CODE')->distinct()->where(['DEPT_ID'=>$dept_id])->all();

Then I want to assign a flag attribute to the records in this activerecord based on whether they appear in a relationship table

What I have tried

So in my job model, I have declared a new attribute inAccount . Then I added this function in the job model that sets the inAccount flag to -1 or 0 based on whether a record is found in the relationship table with the specified account_id

public function assignInAccount($account_id){
    if(JobCodeAccounts::find()->where(['JOB_CODE'=>$this->JOB_CODE])->andWhere(['ACCOUNT_ID'=>$account_id])->one() == null){
        $this->inAccount=0;
    }
    else{
        $this->inAccount = -1;
    }
}

What I have been doing is assigning each value individually using foreach like so

foreach($jobModel as $job){
    $job->assignInAccount($account_id);
}

However, this is obviously very slow because if I have a large number of records in $jobModel , and each one makes a db query in assignInAccount() this could obviously take some time if the db is slow.

What I am looking for

I am wondering if there is a more efficient way to do this, so that I can assign inAccount to all job records at once. I considered using afterFind() but I don't think this would work as I need to specify a specific parameter. I am wondering if there is a way I can pass in an entire model (or at least array of models/model-attributes and then do all the assignations running only a single query.

I should mention that I do need to end up with the original $jobModel activerecord as well

Thanks to scaisEdge's answer I was able to come up with an alternative solution, first finding the array of jobs that need to be flagged like so:

    $inAccountJobs = array_column(Yii::$app->db->createCommand('Select * from job_code_accounts where ACCOUNT_ID = :account_id')
        ->bindValues([':account_id' => $account_id])->queryAll(), 'JOB_CODE');

and then checking each job record to see if it appears in this array like so

    foreach($jobModel as $job){
        if(in_array($job->JOB_CODE, $inAccountJobs))
            $job->inAccount = -1;
        else
            $job->inAccount = 0;
    }

Does seem to be noticeably faster as it requires only a single query.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM