Many to many

To create "many to many" dependence between two models we need add a code of a new field in "$model_elements" array and create a linking table in a database. The new field doesn't need to be added to the table of model. Additional settings for this field are presented in description of Many to many data type.

For example we want to link Pages and Blocks of Pre-Installed Models with a link of many to many in order to be able to turn the blocks on and off on each specific page.

class Pages extends Model
{
    protected $name = "Pages menu";
 
    protected $model_elements = array(

        ...

        array("Text blocks ", "many_to_many", "blocks", array("related_model" => "Blocks", 
                                                              "linking_table" => "pages_blocks"))
    );
}
//Linking table "pages_blocks" (attention to the names of fields!)
CREATE TABLE "pages_blocks" (
    "pages_id" INTEGER, 
    "blocks_id" INTEGER
);

Attention! The linking table for two models is to be built based on their names. For example there are 2 Models - Albums and Images, then the table will be called as "albums_images", and columns in as "albums_id" and "images_id" accordingly. The id field in linking tables isn't necessary.

Now in Admin Interface of the Pages model there will be a field to select blocks that are related to the model. In the Blocks model there is no such a field so far. If we want it to be in the second model then we need to add the code to the file of model.

class Blocks extends Model
{
    protected $name = "Text blocks";
 
    protected $model_elements = array(
            ...

            array("Menu pages", "many_to_many", "pages", array("related_model" => "Pages", 
                                                               "linking_table" => "pages_blocks"))
    );
}

Attention! When a backlink of "many to many" is created (for example from the Blocks model to the Pages model) the name of a field ("pages") should match the name of the linked model. See the previous example. Then in Admin Panel in the general table the links will be created to the second model to launch a filter on this field.

When you want to display the records connected by a ratio "many to many" you may use JOIN request (in this case Direct queries are being used), or to break records retrieval into 2 requests as on the example below where all active blocks of the current page are displayed.

//Adding a new method in "Blocks" model 
public function getRelatedBlocks($page_id)
{
    //Select id of all blocks ,related to this page
    $blocks_ids = $this -> selectColumn(array("fields->" => "blocks_id", 
                                              "pages_id" => $page_id, 
                                              "table->" => "pages_blocks"));
 
    //Id you don’t validate this, an empty record will go to "id->in" operator to cause SQL  error
    if(!count($blocks_ids))
        return;
 
    $html = "";
 
    //Retrive content of active blocks 
    $rows = $this -> select(array("id->in" => implode(",", $blocks_ids), "active" => 1));
 
    foreach($rows as $row)
    {
        $html .= "<h3>".$row["name"]."</h3>";
        $html .= "<div>".$row["content"]."</div>";
    }
 
    return $html;
}

Previous

Trees

Next

Group