1
votes

OK. Trying to articulate my issue as concisely as possible. I've got this massive project, for which the main purpose is generating a configuration file from Model data. I'm at a loss on how to get the appropriate information in an efficient way when gleaning the db for config info. The Models: District, Department, User, Carrier.

  • District
    • hasMany Department
    • | id | name |
  • Department
    • hasMany User through DepartmentPosition
    • | id | name | district_id | tone_name | tone_length |
  • User
    • hasMany Department through DepartmentPosition
    • belongsTo Carrier
    • | id | name | phone | email | carrier_id | notify_method (tiny int) |
  • Carrier
    • hasMany User
    • | id | name | mms_gateway |
  • DepartmentPosition
    • belongsTo User, Department
    • | id | user_id | department_id | role |

A configuration file is to generated for each district, using fields associated with all models above. For each department in a district the following is to be added to a string which, when finished, will be saved to the configuration file:

[tone_name] //comes from department name
    tone = 123 //from department tone
    tone_length = 4 //from department tone_length
    mp3_emails = [email protected], [email protected] ... //comes from user email
    amr_emails = [email protected] //concat of user phone and carrier mms_gateway

Basically, the lists for a department's mp3_emails and amr_emails should be generated based on the users in that department, based on the notify_method User field. I've been able get everything but these email fields into the config file with the following:

//districts controller
public function generate_config(){
    $districts = $this->District->find('All'); 
    $this->set(compact('districts'));
}  

Now, for the view file:

    <?php
    $output = '';
    $br = " \r\n";
    $unrelated = array('id', 'name', 'district_id', 'tone_name');
    foreach($districts as $district){
        $name = $district['District']['name'];
        $output .= "#{$name} configuration".$br;
        $departments = $district['Department'];
        foreach($departments as $department){
            $output .= "[".$department['tone_name']."]".$br;
            foreach($department as $key => $value){
                if(!empty($value)&&(!in_array($key, $unrelated))){
                    $output .= $key." = ".$value.$br;   
                }

            }
            $output .= $br;
        }
    }
    echo nl2br($output);
    ?>

That outputs something like this

#District 1 config
[Department1]
    tone = 123
    tone_length = 4

[Department2]
    tone = 24.7
    tone_length = 2

What I need to do is generate the email lists for each department, but I can't figure out a sensible way to do this. I feel it would be much easier if the departments and users used a HABTM relationship, rather than the hasMany through, which i felt i had to use instead because i'm saving additional data for the relationship. Any suggestions?? Don't hesitate to ask if i should be clearer about anything, but i've tried to give all relevant information while minimizing overwhelming details. THANK YOU!!!

EDIT

Thanks to @Drewdiddy611, my sanity has been spared. Containable behavior is perfect for this issue. So, hopefully someone will avoid a complete project overhaul -- something which I was moments away from doing -- and use the containable behavior.

Simply adding the following to my models: public $actsAs = array('Containable'); I was able to then run the find query, implementing the containable behavior just as suggested below, i was able to add greater depth to my iteration over each District/Department. It was extremely easy because the returned array was just as written in the answer chosen below!!! thanks!

1

1 Answers

1
votes

I think you were right to use the 'hasMany through' relationship based on your tables/data. In cakephp 2.1, they added a 'unique' key for HABTM relationships which you can set to 'keepExisting' and it's supposed to circumvent lost data.

http://book.cakephp.org/2.0/en/models/associations-linking-models-together.html#hasmany-through - Look at the "Changed in 2.1" section below the main header.

Maybe give that a try?

You could also look at containable behavior. Then you could do the following:

<?php
//model
var $actsAs = array('Containable');

//controller
$this->District->contain(array(
    'Department' => array(
        'DepartmentPosition' => array(
            'User' => array(
                'Carrier'
            )
        )
    )
));
$districts = $this->District->find('all');
$this->set(compact('districts'));

// I believe this will be the outcome after the find.
///////////////////////////////////////////////////////
// array(
//     [0] => array(
//        'District' => array(...),
//        'Department' => array(
//            [0] => array(
//                '...' => '...', // repeated...
//                'DepartmentPosition' => array(
//                    [0] => array(
//                        '...' => '...', // repeated...
//                        'User' => array(
//                            '...' => '...', // repeated...
//                            'Carrier' => array(
//                                '...' => '...', // repeated...
//                            )
//                        )
//                    )
//                ) 
//            )
//        )
//    )
// )

?>

-Andrew