Salut Co-k-ine,
la définition des tables que tu me présentes là, ne contient pas de clef étrangère, et donc d’un point de vue SQL, il n’y a pas de relation entre la table ‘discipline’ et le table ‘sous_discipline’, par conséquent il est normal que yii ne découvre aucune relation.
Là on quitte le sujet ‘Yii Framework’ pour le sujet ‘Architecture des base de données’, et dans ce domaine je suis loin d’être un expert. Alors du coup, la solution que j’ai trouvé, c’est d’utiliser une application qui fait le boulot à ma place ! Notamment pour ce qui concerne le SQL. J’utilise “MySQL Workbench” qui est gratuit et téléchargeable ici. Avec cette application, tu peux dessiner tes tables, les lier entre elles, et tout ça de façon graphique, sans avoir à te soucier du SQL, qui sera généré automatiquement en fonction du schema que tu aura créé.
Tu peux essayer de voir si cela te convient, mais si tu veux aller plus loin, je crains que tu ne puisses faire l’économie de la lecture de quelques documentation sur le sujet (qui va du ‘tout simple’ au ‘bien complexe’).
Revenons à ta question. J’ai donc modélisé tes tables avec MySQL WorkBench (1 minute), puis j’ai demander à récupérer le SQL qui créé ce modèle (2 secondes), et voilà le résultat :
SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0;
SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='TRADITIONAL';
-- -----------------------------------------------------
-- Table `discipline`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `discipline` (
`id` INT NOT NULL AUTO_INCREMENT ,
`nom` VARCHAR(150) NOT NULL ,
PRIMARY KEY (`id`) )
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `sous_discipline`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `sous_discipline` (
`id` INT NOT NULL AUTO_INCREMENT ,
`id_discipline` INT NOT NULL ,
`nom_sous_discipline` VARCHAR(150) NOT NULL ,
PRIMARY KEY (`id`) ,
INDEX `fk_sous_discipline_discipline1` (`id_discipline` ASC) ,
CONSTRAINT `fk_sous_discipline_discipline1`
FOREIGN KEY (`id_discipline` )
REFERENCES `discipline` (`id` )
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `tutorial`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `tutorial` (
`id` INT NOT NULL AUTO_INCREMENT ,
`id_sous_discipline` INT NOT NULL ,
`titre` VARCHAR(150) NOT NULL ,
`contenu` TEXT NOT NULL ,
`valide` INT(11) NOT NULL ,
PRIMARY KEY (`id`) ,
INDEX `fk_tutorial_sous_discipline1` (`id_sous_discipline` ASC) ,
CONSTRAINT `fk_tutorial_sous_discipline1`
FOREIGN KEY (`id_sous_discipline` )
REFERENCES `sous_discipline` (`id` )
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
SET SQL_MODE=@OLD_SQL_MODE;
SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;
SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;
Comme tu le vois, cette génération automatique est bien utile aussi pour ce former au SQL et à ce titre, permet d’apprendre comment créer des relations entre tables.
Bon, la prochaine étape c’est de réellement créer ces tables dans ta base de données de test (sur ton PC). Pour ça, MySQL WorkBench dispose d’une fonction ‘forward enginering’ toute prête (à configurer un peu quand même). En un petit click, c’est fait.
Dernière étape : laisser Yii créer les modèles correspondants. C’est facile avec un module Gii bien configuré. Le résultat est le suivant :
[size="5"]table discipline[/size]
<?php
/**
* This is the model class for table "discipline".
*/
class Discipline extends CActiveRecord
{
/**
* The followings are the available columns in table 'discipline':
* @var integer $id
* @var string $nom
*/
/**
* Returns the static model of the specified AR class.
* @return Discipline the static model class
*/
public static function model($className=__CLASS__)
{
return parent::model($className);
}
/**
* @return string the associated database table name
*/
public function tableName()
{
return 'discipline';
}
/**
* @return array validation rules for model attributes.
*/
public function rules()
{
// NOTE: you should only define rules for those attributes that
// will receive user inputs.
return array(
array('nom', 'required'),
array('nom', 'length', 'max'=>150),
// The following rule is used by search().
// Please remove those attributes that should not be searched.
array('id, nom', 'safe', 'on'=>'search'),
);
}
/**
* @return array relational rules.
*/
public function relations()
{
// NOTE: you may need to adjust the relation name and the related
// class name for the relations automatically generated below.
return array(
'sousDisciplines' => array(self::HAS_MANY, 'SousDiscipline', 'id_discipline'),
);
}
/**
* @return array customized attribute labels (name=>label)
*/
public function attributeLabels()
{
return array(
'id' => 'ID',
'nom' => 'Nom',
);
}
/**
* Retrieves a list of models based on the current search/filter conditions.
* @return CActiveDataProvider the data provider that can return the models based on the search/filter conditions.
*/
public function search()
{
// Warning: Please modify the following code to remove attributes that
// should not be searched.
$criteria=new CDbCriteria;
$criteria->compare('id',$this->id);
$criteria->compare('nom',$this->nom,true);
return new CActiveDataProvider(get_class($this), array(
'criteria'=>$criteria,
));
}
}
[size="5"]table sous_discipline[/size]
<?php
/**
* This is the model class for table "sous_discipline".
*/
class SousDiscipline extends CActiveRecord
{
/**
* The followings are the available columns in table 'sous_discipline':
* @var integer $id
* @var integer $id_discipline
* @var string $nom_sous_discipline
*/
/**
* Returns the static model of the specified AR class.
* @return SousDiscipline the static model class
*/
public static function model($className=__CLASS__)
{
return parent::model($className);
}
/**
* @return string the associated database table name
*/
public function tableName()
{
return 'sous_discipline';
}
/**
* @return array validation rules for model attributes.
*/
public function rules()
{
// NOTE: you should only define rules for those attributes that
// will receive user inputs.
return array(
array('id_discipline, nom_sous_discipline', 'required'),
array('id_discipline', 'numerical', 'integerOnly'=>true),
array('nom_sous_discipline', 'length', 'max'=>150),
// The following rule is used by search().
// Please remove those attributes that should not be searched.
array('id, id_discipline, nom_sous_discipline', 'safe', 'on'=>'search'),
);
}
/**
* @return array relational rules.
*/
public function relations()
{
// NOTE: you may need to adjust the relation name and the related
// class name for the relations automatically generated below.
return array(
'idDiscipline0' => array(self::BELONGS_TO, 'Discipline', 'id_discipline'),
'tutorials' => array(self::HAS_MANY, 'Tutorial', 'id_sous_discipline'),
);
}
/**
* @return array customized attribute labels (name=>label)
*/
public function attributeLabels()
{
return array(
'id' => 'ID',
'id_discipline' => 'Id Discipline',
'nom_sous_discipline' => 'Nom Sous Discipline',
);
}
/**
* Retrieves a list of models based on the current search/filter conditions.
* @return CActiveDataProvider the data provider that can return the models based on the search/filter conditions.
*/
public function search()
{
// Warning: Please modify the following code to remove attributes that
// should not be searched.
$criteria=new CDbCriteria;
$criteria->compare('id',$this->id);
$criteria->compare('id_discipline',$this->id_discipline);
$criteria->compare('nom_sous_discipline',$this->nom_sous_discipline,true);
return new CActiveDataProvider(get_class($this), array(
'criteria'=>$criteria,
));
}
}
[size="5"]table tutorial[/size]
<?php
/**
* This is the model class for table "tutorial".
*/
class Tutorial extends CActiveRecord
{
/**
* The followings are the available columns in table 'tutorial':
* @var integer $id
* @var integer $id_sous_discipline
* @var string $titre
* @var string $contenu
* @var integer $valide
*/
/**
* Returns the static model of the specified AR class.
* @return Tutorial the static model class
*/
public static function model($className=__CLASS__)
{
return parent::model($className);
}
/**
* @return string the associated database table name
*/
public function tableName()
{
return 'tutorial';
}
/**
* @return array validation rules for model attributes.
*/
public function rules()
{
// NOTE: you should only define rules for those attributes that
// will receive user inputs.
return array(
array('id_sous_discipline, titre, contenu, valide', 'required'),
array('id_sous_discipline, valide', 'numerical', 'integerOnly'=>true),
array('titre', 'length', 'max'=>150),
// The following rule is used by search().
// Please remove those attributes that should not be searched.
array('id, id_sous_discipline, titre, contenu, valide', 'safe', 'on'=>'search'),
);
}
/**
* @return array relational rules.
*/
public function relations()
{
// NOTE: you may need to adjust the relation name and the related
// class name for the relations automatically generated below.
return array(
'idSousDiscipline0' => array(self::BELONGS_TO, 'SousDiscipline', 'id_sous_discipline'),
);
}
/**
* @return array customized attribute labels (name=>label)
*/
public function attributeLabels()
{
return array(
'id' => 'ID',
'id_sous_discipline' => 'Id Sous Discipline',
'titre' => 'Titre',
'contenu' => 'Contenu',
'valide' => 'Valide',
);
}
/**
* Retrieves a list of models based on the current search/filter conditions.
* @return CActiveDataProvider the data provider that can return the models based on the search/filter conditions.
*/
public function search()
{
// Warning: Please modify the following code to remove attributes that
// should not be searched.
$criteria=new CDbCriteria;
$criteria->compare('id',$this->id);
$criteria->compare('id_sous_discipline',$this->id_sous_discipline);
$criteria->compare('titre',$this->titre,true);
$criteria->compare('contenu',$this->contenu,true);
$criteria->compare('valide',$this->valide);
return new CActiveDataProvider(get_class($this), array(
'criteria'=>$criteria,
));
}
}
Comme tu peux le constater, les tables ‘sous_discipline’ et ‘tutorial’ contiennent toutes les deux cette fameuse méthode relations qui défini les relations existantes entre les tables.
Pour comprendre leur signification, tu dois te référer à la documentation de Yii, mais la lecture seule du code est déjà claire :
-
un tutoriel appartient (BELONGS_TO) une sous-discipline
-
une sous-discipline a plusieurs (HAS_MANY) tutoriels, et appartient (BELONGS_TO) a une discipline
-
une discipline a plusieurs (HAS_MANY) sous-discipline
La définition d’un schéma de base de données est extrêmement importante, car c’est le socle sur lequel s’appuiera ton application, donc il faut bien y réfléchir avant de commencer tout développement. C’est sur ce point que la lecture de documentation sur le sujet s’avère payante (surtout le jour ou tu voudra rajouter des tables …). Bref, c’est un vaste sujet, et comme je l’ai dit, je suis loin d’avoir suffisamment de connaissance pour te donner un autre conseil que celui de te documenter
J’espère que tout cela t’aura aidé, et bon courage pour la suite …
ciao