Flourish PHP Unframework
This is an archived copy of the forum for reference purposes

fActiveRecord -- Deep related records in forms

posted by vena 9 years ago

In the documentation for fActiveRecord, you describe how to craft input field names so that related records are populated automagically by fActiveRecord's link methods. My question is, how might this work for deep relations?

For example, say I have a Survey model which has Groups, Groups have Fields, Fields have Dependents.

Thank you!

please tell me if you succed to use populate related field because i try and i did't.

posted by mungiu 9 years ago

This works for deep relations by using nested foreach loops and fRequest::filter(). Here is a rough outline of what you would need to do.

Your inputs would all need to be named in the following form. $key, $key_2, etc should be replaced which integer keys. All fields and dependents that are part of the same group would use the same $key and all field columns and dependents that are part of a field would use the same $key_2, etc.

groups::group_id[$key]
groups::name[$key]
...
groups::fields::field_id[$key][$key_2]
groups::fields::group_id[$key][$key_2]
groups::fields::type[$key][$key_2]
...
groups::fields::dependents::dependent_id[$key][$key_2][$key_3]
groups::fields::dependents::field_id[$key][$key_2][$key_3]
groups::fields::dependents::column[$key][$key_2][$key_3]

fRequest::filter() is an internal function so you'll need to click the "Show Protected/Internal" link on the API docs page to see it. It takes a prefix and a key and replaces $_GET and $_POST with only the key/value pairs that start with $prefix and that match the $key specified. Once the request is filtered, you can then use a normal fActiveRecord::populate().

Here is some code that may help in your understanding. I know what I have presented isn't a complete working example, I just don't have time to write it all out.

$survey = new Survey();
$survey->populate();

$groups = array();

// This gets the keys to use with fRequest::filter()
$groups_keys = array_keys(fRequest::get('groups::group_id'));
foreach ($groups_keys as $group_key) {
    fRequest::filter('groups::', $group_key);
    $group = new Group();
    $group->populate();
    
    $fields = array();    

    $fields_keys = array_keys(fRequest::get('fields::field_id'));
    foreach ($fields_keys as $field_key) {
        fRequest::filter('fields::', $field_key);
        $field = new Field();
        $field->populate();
        
        // continue nesting for dependents

        $fields[] = $field;
        fRequest::unfilter();
    }
    $group->associateFields($fields);
    $groups[] = $group;
    fRequest::unfilter();
}
$survey->associateGroups($groups);

$survey->store();

The store operation will validate all the way down the stack and should create friendly error messages for any level of relations. Similarly, all related records will be stored when you call the $survey->store().

Let me know if you need any clarification beyond this.

posted by wbond 9 years ago

ah, thank you! brilliant as always.

posted by vena 9 years ago

No problem. I wouldn't be opposed to implementing some sort of functionality that could handle this in fORMRelated, I'm just not sure how the API would look. If anyone has any ideas about how this could work, I'd be open to hearing them.

posted by wbond 9 years ago