Bonjour à tous, Avant de me lancer dans le code php, j'ai décidé de modéliser les tables SQL pour pouvoir créer un forum. Je me suis dit que c'était comme un blog avec des commentaires et qu'une catégorie comportait plusieurs blogs (avec ses commentaires), et donc que le forum comportait plusieurs catégories. Si on regarde bien le forum de grafikart, on voit : Une catégorie avec ses forums : [url=http://imgbox.com/JmfOD7pZ]Lien vers l'image[/url] Un forum avec ses sujets : [url=http://imgbox.com/0lJnxZNR]Lien vers l'image[/url] Un sujet avec ses messages : [url=http://imgbox.com/7vMmimUO]Lien vers l'image[/url] Un message est donc lié à un sujet, qui lui même est lié à une catégorie. Voici donc la modélisation avec Workbench de MySQL que j'ai pu réaliser : [url=http://imgbox.com/DpN200XI]Lien vers l'image[/url] Pensez vous que mes tables sont bien pensées ? Par contre, je pense qu'il me manque quelque chose pour réaliser les choses suivantes : dans le forum avec ses catégories (première image), on voit que chaque catégorie présente le titre du dernier sujet** dans la catégorie avec ses sujets (deuxième image), on voit pour chaque sujet listé le nom de l'auteur du dernier message** Manque-t-il un champs dans une des tables dans ma modélisation pour parvenir à réussir ceci ? Ou est-ce avec cakephp que je pourrai le faire ? Et dernières questions : dans mes différentes tables, j'ai mis un champs appelé number_* pour enregistrer à chaque enregistrement le nombre total de sujets, de messages ou de vues. Est-ce la meilleure chose à faire plutôt que de faire une requête supplémentaire pour compter ? A moins que dans cakephp, on puisse afficher et compter en même dans dans une seule requête sans perdre trop de performance.. Merci d'avance, j'espère avoir détaillé au mieux. P.S : je viens de me rendre compte que number_views était obligatoire comme champs, mais par forcément pour number_threads/posts (voir question au dessus). Pour montrer que le sujet est résolu, il faudrait un champs resolved dans la table 'threads' et pour un message qui a aidé l'auteur du sujet, un champs helped dans la table 'posts'.

6 réponses


JeremyB, je travail exactement sur le même projet en ce moment (à quelques détails js près), si tu as des souçis n'hésites pas à me contacte :)

JeremyB
Auteur

@ taskone : Si tu prends la premier photo avec ce que tu dis (le titre du dernier sujet), on voit que pour chaque catégorie, on liste les différents forums avec le titre du dernier sujet pour chaque forum. Ma question est : est-ce qu'on peut arriver à afficher tout ça en une seule requête avec des jointures ou avec deux ? (je ne vois pas le lien avec l'update car avec ma modélisation dans la quatrième image, je n'ai pas besoin d'effectuer plusieurs update) Idem pour le listing des sujets avec le nom de l'auteur du dernier message.

@ Benjamin : oui j'ai bien des soucis de conception sur mes tables et des possibles requêtes pour afficher selon les 3 images ci-dessus. Si tu as des idées ou une meilleure vision que ce que j'ai pu émettre dans ma modélisation, partage ! ;)

Pour récupérer l'heure du dernier post, tu peux très bien aller chercher l'heure du dernier post en faisant une jointure sur ta table threads qui fera elle même une jointure sur la table forum dont le nom du forum est celui que tu souhaite.

C'est écris en français mais c'est facilement faisable en sql avec ce que je t'ai dis.

Taskone t'a parlé d'update parce que si cette date n'est pas une informations que tu "calcule" en faisant pleins de jointures, alors tu peux la stocker.
Par exemple tu as une table last_posts avec l'id du forum, l'id du post et l'heure du post. (pour avoir sur un forum donné, l'heure du dernier post)

Par contre, à chaque fois que qqun va créer ou modifier un post, des requêtes updates vont être faites pour mettre à jour la date du dernier post dans ta table last_posts.

JeremyB
Auteur

Merci Pewel pour les explications. Avec ce que vous avez tous dit et mes recherches sur le net, j'ai essayé de modéliser différemment. Qu'en dites vous ?

-- -----------------------------------------------------
-- Table `users`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `users` (
  `id` INT NULL AUTO_INCREMENT,
  `username` VARCHAR(255) NULL,
  `password` VARCHAR(255) NULL,
  `mail` VARCHAR(255) NULL,
  `created` DATETIME NULL,
  `last_visit` DATETIME NULL,
  `posts_count` INT NULL,
  PRIMARY KEY (`id`));

-- -----------------------------------------------------
-- Table `f_categories`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `f_categories` (
  `id` SMALLINT NULL AUTO_INCREMENT,
  `name` VARCHAR(255) NULL,
  `order` SMALLINT NULL,
  PRIMARY KEY (`id`),
  UNIQUE INDEX `cat_ordre` (`order` ASC));

-- -----------------------------------------------------
-- Table `f_forums`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `f_forums` (
  `id` SMALLINT NULL AUTO_INCREMENT,
  `category_id` SMALLINT NULL,
  `last_topic_id` INT NULL,
  `last_post_id` INT NULL,
  `last_user_id` INT NULL,
  `name` VARCHAR(255) NULL,
  `description` VARCHAR(255) NULL,
  `order` SMALLINT NULL,
  `topics_count` INT NOT NULL DEFAULT 0,
  PRIMARY KEY (`id`),
  INDEX `fk_forums_categories_idx` (`category_id` ASC),
  UNIQUE INDEX `order_UNIQUE` (`order` ASC));

-- -----------------------------------------------------
-- Table `f_topics`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `f_topics` (
  `id` INT NULL AUTO_INCREMENT,
  `forum_id` INT NULL,
  `first_post_id` INT NULL,
  `last_post_id` INT NULL,
  `last_user_id` INT NULL,
  `user_id` INT NULL,
  `title` VARCHAR(255) NULL,
  `slug` VARCHAR(255) NULL,
  `views_count` INT NOT NULL DEFAULT 0,
  `posts_count` INT NOT NULL DEFAULT 0,
  `created` DATETIME NULL,
  `modified` DATETIME NULL,
  PRIMARY KEY (`id`),
  INDEX `fk_threads_forums1_idx` (`forum_id` ASC),
  INDEX `fk_f_topics_users1_idx` (`user_id` ASC),
  INDEX `fk_f_topics_f_forums1_idx` (`last_post_id` ASC),
  INDEX `fk_f_topics_f_forums2_idx` (`last_user_id` ASC));

-- -----------------------------------------------------
-- Table `f_posts`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `f_posts` (
  `id` INT NULL AUTO_INCREMENT,
  `forum_id` INT NULL,
  `topic_id` INT NULL,
  `user_id` INT NULL,
  `content` LONGTEXT NULL,
  `created` DATETIME NULL,
  `modified` DATETIME NULL,
  PRIMARY KEY (`id`),
  INDEX `fk_posts_threads1_idx` (`topic_id` ASC),
  INDEX `fk_posts_users1_idx` (`user_id` ASC),
  INDEX `fk_f_posts_f_forums1_idx` (`forum_id` ASC));
JeremyB
Auteur

1/ Je me suis dit qu'il n'y aura pas plus de 10 catégories, idem pour les forums par catégorie. D'où les SMALLINT. Est-ce inutile ?

2/ Pour last_post_id et last_user_id, je me suis dit que c'était plus rapide à les retrouver lors d'une requête. Pour post_count, c'était ma question initiale : doit on l'enregistrer dans la base pour éviter deux faire deux requêtes (une qui sélectionne et l'autre qui compte) ou est-ce possible de le faire en une seule requête (sélectionner et compter) tout en conservant les meilleures performances ? Idem alors pour topics_count dans f_forums.

Je travaille avec cakephp et je sais qu'il faudra faire des associations. Je sais qu'il faudra dire :

  • categories hasMany
    forums et forums belongsTo categories
  • forums hasMany
    topics et topics belongsTo forums
  • topics hasMany
    posts et posts belongsTo topics

Doit-il y avoir un hasAndBelongsToMany quelque part ? Perso je ne pense pas.

J'aimerai juste savoir au final si avec le code SQL ci-dessous, plus les associations montrées au-dessus, je peux arriver avec un minimum de requêtes à afficher un forum/sujet/message comme sur les images ci-dessous :

Image 1 : Catégorie avec ses forums (et indique le dernier sujet)
Image 2 : Forum avec ses sujets (et indique l'auteur du dernier message)
Image 3 : Sujet avec ses messages

-- -----------------------------------------------------
-- Table `users`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `users` (
  `id` INT NULL AUTO_INCREMENT,
  `username` VARCHAR(255) NULL,
  `password` VARCHAR(255) NULL,
  `mail` VARCHAR(255) NULL,
  `created` DATETIME NULL,
  `last_visit` DATETIME NULL,
  `posts_count` INT NULL,
  PRIMARY KEY (`id`));

-- -----------------------------------------------------
-- Table `f_categories`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `f_categories` (
  `id` INT NULL AUTO_INCREMENT,
  `name` VARCHAR(255) NULL,
  `order` SMALLINT NULL,
  PRIMARY KEY (`id`),
  UNIQUE INDEX `cat_ordre` (`order` ASC));

-- -----------------------------------------------------
-- Table `f_forums`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `f_forums` (
  `id` INT NULL AUTO_INCREMENT,
  `category_id` SMALLINT NULL,
  `last_topic_id` INT NULL,
  `last_post_id` INT NULL,
  `last_user_id` INT NULL,
  `name` VARCHAR(255) NULL,
  `description` VARCHAR(255) NULL,
  `order` SMALLINT NULL,
  `topics_count` INT NOT NULL DEFAULT 0,
  PRIMARY KEY (`id`),
  INDEX `fk_forums_categories_idx` (`category_id` ASC),
  UNIQUE INDEX `order_UNIQUE` (`order` ASC));

-- -----------------------------------------------------
-- Table `f_topics`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `f_topics` (
  `id` INT NULL AUTO_INCREMENT,
  `forum_id` INT NULL,
  `user_id` INT NULL,
  `title` VARCHAR(255) NULL,
  `slug` VARCHAR(255) NULL,
  `views_count` INT NOT NULL DEFAULT 0,
  `posts_count` INT NOT NULL DEFAULT 0,
  `created` DATETIME NULL,
  `modified` DATETIME NULL,
  PRIMARY KEY (`id`),
  INDEX `fk_threads_forums1_idx` (`forum_id` ASC),
  INDEX `fk_f_topics_users1_idx` (`user_id` ASC);

-- -----------------------------------------------------
-- Table `f_posts`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `f_posts` (
  `id` INT NULL AUTO_INCREMENT,
  `forum_id` INT NULL,
  `topic_id` INT NULL,
  `user_id` INT NULL,
  `content` LONGTEXT NULL,
  `created` DATETIME NULL,
  `modified` DATETIME NULL,
  PRIMARY KEY (`id`),
  INDEX `fk_posts_threads1_idx` (`topic_id` ASC),
  INDEX `fk_posts_users1_idx` (`user_id` ASC),
  INDEX `fk_f_posts_f_forums1_idx` (`forum_id` ASC));

Info : j'ai mis INT à la place des SMALLINT, j'ai enlevé first\_post\_id, last\_post\_id et last\_user\_id de f\_topics.

JeremyB
Auteur

Petit up s'il vous plait.