Yii Framework Forum: How To Factorise Named Scopes - Yii Framework Forum

Jump to content

Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

How To Factorise Named Scopes i.e. one scope depends on another Rate Topic: -----

#1 User is offline   clapas 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 39
  • Joined: 21-February 11

Posted 16 February 2013 - 08:56 AM

Hi there,

I have three models: Task, Worker and Material, where a Material BELONGS_TO a Task and a Task HAS_MANY workers. The named scope unassigned inside my Task model refers to those tasks to which no worker is assigned:
public function scopes() {
    return array(
        'unassigned' => array(
            'with' => 'workers',
            'condition' => 'workers.id is null',
            'together' => true
        )
    );
}

Similarly, the unassignedTask scope inside my Material model refers to materials belonging to those tasks to which no worker is assigned:
public function scopes() {
    return array(
        'unassignedTask' => array(
            'with' => 'task.workers',
            'condition' => 'workers.id is null',
            'together' => true
        )
    );
}

I have simplified thoroughly, but this example illustrates my main concern, that is, the code looks redundant and forces me to synchronize code in multiple files of my application.

Is there any way I could factorise to above code so that the unassignedTask scope somehow "goes" through the Task model? What would you do?
0

#2 User is offline   clapas 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 39
  • Joined: 21-February 11

Posted 18 February 2013 - 08:05 AM

No one? Any suggestion will be appreciated.
0

#3 User is offline   seenivasan 

  • Master Member
  • PipPipPipPip
  • Yii
  • Group: Members
  • Posts: 620
  • Joined: 17-June 12
  • Location:Chennai,TamilNadu,India.

Posted 18 February 2013 - 08:14 AM

Dear Friend

I think you want to acheive something like this.

$materials=Material::model()->with(array('task'=>array(

'scopes'=>array('unassigned'),

)))->findAll();


I miserably failed to acheive that.

public function scopes() {
    return array(
        'unassigned' => array(
            'with' => 'workers',
            'together' => true,
            'condition' => '`workers`.`id` is null',
        )
    );
   }


Because the where clause in the above code is attached to join clause somehow.

But the following code works fine.

tasks=Task::model()->unassigned()->findAll();


I am totally lost.

Are you expecting something different?
0

#4 User is offline   clapas 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 39
  • Joined: 21-February 11

Posted 20 February 2013 - 05:07 PM

Hello seenivasan!

thank you for your answer. I think you have understood very well my problem; as you say the where clause is somehow attached to the join clause and I cannot see how could I define the scope just once in the Task model and make use of it in the Material model.

Still looking for a way...
0

#5 User is offline   Leto 

  • Newbie
  • Yii
  • Group: Members
  • Posts: 19
  • Joined: 11-February 13

Posted 21 February 2013 - 10:48 AM

What exactly failed with this :

$materials=Material::model()->with(array('task'=>array(

'scopes'=>array('unassigned'),

)))->findAll();

0

#6 User is offline   seenivasan 

  • Master Member
  • PipPipPipPip
  • Yii
  • Group: Members
  • Posts: 620
  • Joined: 17-June 12
  • Location:Chennai,TamilNadu,India.

Posted 21 February 2013 - 01:39 PM

Dear Friend

This is the error.

Tables:
1.task(id,name)
2.worker(id,name,task_id)
3.material(id,name,task_id)

material BELONGS_TO task

task HAS_MANY workers.

Column not found: 1054 Unknown column 'workers.id' in 'on clause'. The SQL statement executed was: SELECT `t`.`id` AS `t0_c0`, `t`.`name` AS `t0_c1`, `t`.`task_id` AS `t0_c2`, `task`.`id` AS `t1_c0`, `task`.`name` AS `t1_c1`, `workers`.`id` AS `t2_c0`, `workers`.`name` AS `t2_c1`, `workers`.`task_id` AS `t2_c2` FROM `material` `t` LEFT OUTER JOIN `task` `task` ON (`t`.`task_id`=`task`.`id`) AND (`workers`.`id` is null) LEFT OUTER JOIN `worker` `workers` ON (`workers`.`task_id`=`task`.`id`)

May be some simple things could be at fault.

I hope you will solve the issue.

Regards.
0

#7 User is offline   Leto 

  • Newbie
  • Yii
  • Group: Members
  • Posts: 19
  • Joined: 11-February 13

Posted 21 February 2013 - 03:24 PM

Try this :

public function scopes() {
    return array(
        'unassigned' => array(
            'with' => 
			array(
				'workers' => array(
					'condition' => '`workers`.`id` is null',
				)
			),
            'together' => true
        )
    );
}


Previous code was setting a condition on the task table but we want to set it on the workers table.
2

#8 User is offline   seenivasan 

  • Master Member
  • PipPipPipPip
  • Yii
  • Group: Members
  • Posts: 620
  • Joined: 17-June 12
  • Location:Chennai,TamilNadu,India.

Posted 21 February 2013 - 03:38 PM

Ya! Ya! Ya!

That is working!

Many THANKS! I lost half of the sunday on that.

I was reluctant to put condition on workers table as there was no workers for the task.

My notion is entirely wrong.

Regards.
0

#9 User is offline   clapas 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 39
  • Joined: 21-February 11

Posted 13 March 2013 - 11:25 AM

View PostLeto, on 21 February 2013 - 03:24 PM, said:

Try this :

public function scopes() {
    return array(
        'unassigned' => array(
            'with' => 
			array(
				'workers' => array(
					'condition' => '`workers`.`id` is null',
				)
			),
            'together' => true
        )
    );
}


Previous code was setting a condition on the task table but we want to set it on the workers table.


This looks just like the code that I originally posted, doesn't it? I am looking for I way to factorise this code as explained.
0

#10 User is offline   clapas 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 39
  • Joined: 21-February 11

Posted 13 March 2013 - 11:51 AM

View PostLeto, on 21 February 2013 - 10:48 AM, said:

What exactly failed with this :

$materials=Material::model()->with(array('task'=>array(

'scopes'=>array('unassigned'),

)))->findAll();



I think this sets me on the right direction, but need an additional value in the with array. It'd be something like:

function scopes() {
    return array(
        'unassignedTask' => array(
            'with' => array(
                'task.taskWorkers',
                'task' => array(
                    'scopes' => 'unassigned'
                )
            )
        )
    )
}


What would be perfect is:
function scopes() {
    return array(
        'unassignedTask' => array(
            'with' => array(
                'task' => array(
                    'scopes' => 'unassigned'
                )
            )
        )
    )
}


But unfortunately this gives an error:

Undefined table: 7 ERROR: missing FROM-clause entry for table "taskWorkers"
LINE 1: ..."task" "task" ON ("t"."task_id"="task"."id") AND ("taskWorke...
^. The SQL statement executed was: SELECT COUNT(DISTINCT "t"."id") FROM "material_requisition" "t" LEFT OUTER JOIN "task" "task" ON ("t"."task_id"="task"."id") AND ("taskWorkers".id is null) LEFT OUTER JOIN "task_worker" "taskWorkers" ON ("taskWorkers"."task_id"="task"."id") WHERE (task.tenant_id = :tenant_id)


I find the solution quite acceptable as it saves me having to change the 'unassignedTask' scope in Material model whenever 'unassigned' scope in Task changes, which is what I was after.

Thanks very much for your help seenivasan and Leto. Best regards.
0

#11 User is offline   clapas 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 39
  • Joined: 21-February 11

Posted 13 March 2013 - 12:29 PM

Sorry, although it was apparently working ok because it gave no errors, the last proposed approach does not produce the desired results, i.e. the scope is bound to Task model but has no effect on Material model.
0

#12 User is offline   deez 

  • Newbie
  • Yii
  • Group: Members
  • Posts: 19
  • Joined: 04-January 12

Posted 22 May 2013 - 02:38 PM

Thanks Leto! Your idea worked for me.
0

Share this topic:


Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

1 User(s) are reading this topic
0 members, 1 guests, 0 anonymous users