Many To Many Relationship With Same Model

Hi,

  I'm a newbie in Yii framework. I just got stuck in a relationship problem please help me to solve it. Problem is described below.





  Relationship is actually with the same model. I have an [b]Employee[/b] model. Usually a company will have only one manager per employee. But in this case there may be more than one manager per employee. He also will be another [b]Employee[/b] only who may or may not have one or more managers again. 





  So I need to define [b]Many-to-Many[/b] relationship for [b]Employee[/b] model with itself. How can I achieve that. I googled a lot, but didn't find any proper solution. 





  Hope you understand the problem. Please help me ASAP. 





 Thank you


     Prashanth

Hi Prashanth,




person

  id

  name


employee_manager

  employee_id ... FK to person.id

  manager_id  ... FK to person.id


// Person.php

'managers'  => array(self::MANY_MANY, 'Person', 'employee_manager(employee_id, manager_id)'),

'employees' => array(self::MANY_MANY, 'Person', 'employee_manager(manager_id, employee_id)'),



I changed ‘Employee’ to ‘Person’ in order to clarify the wording, because employee can have many employees.

The point is that you can create a bridge table that defines the relations between 2 persons: one is employee and the other is manager. And the Person model has 2 relations: employees and managers.

By doing this you can retrieve the managers and the employees of one person.




$person = Person::model()->findByPk($id);

foreach($person->managers as $manager)

    echo $person->name . " has manager named " . $manager->name . "\n";

foreach($person->employees as $employee)

    echo $person->name . " has employee named " . $employee->name . "\n";



Hi softark,

 Below given is my implementation. Can you please check it and confirm.



employee

  id

  name

....


subordinate_manager

  subordinate_id

  manager_id


// Employee.php

'managers' => array(self::MANY_MANY, 'Employee', 'subordinate_manager(subordinate_id, manager_id)'),

'subordinates' => array(self::MANY_MANY, 'Employee', 'subordinate_manager(manager_id, subordinate_id)')



With this situation, I was trying to create a new employee where multi select dropdownlist provides option to select managers. in actionCreate i am trying to save the employee with following code (i am using CAdvancedArBehavior extension) and





$model->attributes=$_POST['Employee'];

$model->managers = Employee::model()->findAll("`Id` IN ('" . implode("','", $_POST['Employee']['managers']) . "')");


if($model->save())

         $this->redirect(array('view','id'=>$model->Id));



that creates an error




Property "Employee.manager_id" is not defined.



I’m sorry, I’m not familiar with that extension and can not help you on it.

But according to the following comment which is on the extension’s page, it has a bug in saving MANY_MANY relation.

http://www.yiiframework.com/extension/cadvancedarbehavior#c6548

The comment was posted on 2012/01/17, and the extension was uploaded on 2011/5/25. So I think the bug is still there.

Thanks dude. Can you give me a sample code to save a Employee record along with the relationship manually without that extension.

Well, it’s boring simple.

  1. Create a CActiveRecord class for subordinate_manager.

  2. Manually set employee_id and manager_id to an instance of SubordinateManager objects and save.




$model->attributes=$_POST['Employee'];

if($model->save())

{

    foreach($_POST['Employee']['managers'] as $manager_id)

    {

         $link = new SubordinateManager();

         $link->subordinate_id = $model->id;

         $link->manager_id = $manager_id;

         $link->save();

    }

}



It needs an extra class for SubordinateManager. And my problem is fixed within the bug report (the link you gave) the reported guy has given its fix too. I applied the fix and now its perfectly fine. subordinate_manager entries are automatically added when i add the following line before saving the Employee object.


$model->managers = Employee::model()->findAll("`Id` IN ('" . implode("','", $_POST['Employee']['managers']) . "')");

I have copied the fix given by the bug reporter so that it may be useful for someone in future.