Many to many

To create "many to many" dependence between two models we need to 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 into the SQL 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 from Pre-installed models with a link of many to many in order to be able to turn on and off these blocks on each particular 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 should be built based on their names with "_id" part at the end. 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 and primary key in linking tables are not necessary.

Now in admin interface of the Pages model there will be a field to select blocks that are related to the current page. 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 Blocks 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 by this field.

When you want to display the records connected by "many to many" you may use JOIN request (in this case Direct queries are being used), or to break records extraction 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 ids of all blocks, related to this page
    $blocks_ids = $this -> selectColumn(array("fields->" => "blocks_id", 
                                              "pages_id" => $page_id, 
                                              "table->" => "pages_blocks"));

    //If you don’t validate this, an empty value might go to "id->in" operator and cause an SQL error
    if(!count($blocks_ids))
        return;

    $html = "";

    //Gets the 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