developer.jelix.org is not used any more and exists only for history. Post new tickets on the Github account.
developer.jelix.org n'est plus utilisée, et existe uniquement pour son historique. Postez les nouveaux tickets sur le compte github.

Opened 13 years ago

Last modified 9 years ago

#361 delayed new feature

Etendre jDao pour le rendre plus souple.

Reported by: Torgan Owned by:
Priority: normal Milestone:
Component: jelix:dao Version: 1.0 beta 3.1
Severity: normal Keywords: dao, sql
Cc: Blocked By:
Blocking: Documentation needed: no
Hosting Provider: Php version:

Description

Deux axes à mon avis seraient parfaits :

  • permettre d'avoir des données ne faisant pas partie de la définition de la dao au sein de l'objet de façon transparente.
  • permettre de créer de méthode de typse 'sql' ou l'utilisateur a la possibilité d'écrire dans le fichier dao sa requete sql en direct.

L'idée derrère tout ça serait de permettre de rendre jDao plus souple sur certains cas particuliers, et en particulier, éviter d'avoir à créer une nouvelle dao dès que l'on veut la moindre requete un peu spécifique.

Mais un court exemple valant mieux qu'un long discours, imaginons le cas suivant :

On a une table _blog de blogs qui contiennent des articles (table _article) qui eux même contiennent des commentaires (table _comment) (ouais je sais que c'est pas original mais je bosse chez Over-blog :))

Pour simplifier, on dira que les tables sont définies ainsi :

#sql
CREATE TABLE _blog
(
  id serial
);

CREATE TABLE _article
(
  id serial,
  blog_id bigint
);

CREATE TABLE _comment
(
  id serial,
  article_id bigint
);

On a donc nos 3 daos pour accéder à nos données et ça c'est chouette. Dans la plupart des cas, on veut certains articles d'un blog ou certains commentaires d'un article et cout va bien.

Mais parfois on veut plus. Par exemple, on veut les articles d'un blog avec leur nombre de commentaires. Alors on peut toujours faire une requete pour récupérer les articles plus un requete par article pour avoir le nombre de commentaires, mais en fait non, ça le fait pas, la base de données s'écroule rapidement à cause du traffic et de l'explosion du nombre de requetes. La solution c'est de faire ça en une seule requete :

SELECT 
    _article.*, 
    (
        SELECT COUNT (id)
        FROM _comment
        WHERE article_id = _article.id
    ) AS nb_comments
FROM  _article
WHERE blog_id = 12

Ca c'est chouette, ça se fait aussi avec des jointures, donc c'est faisable avec une dao, mais le problème c'est que je ne veux pas tout le temps le nombre de commentaires. Donc il faut créer une autre dao.

La proposition serait d'avoir un type de méthode 'sql' qui se présenteait de la façon suivante dans notre dao d'articles :

<method type="sql_select" name="getArticlesWithNbComments">
    <parameter name="blog_id" />
    <sql><![CDATA[
SELECT 
    _article.*, 
    (
        SELECT COUNT (id)
        FROM _comment
        WHERE article_id = _article.id
    ) AS nb_comments
FROM  _article
WHERE blog_id = $blog_id
    ]]></sql> 
</method>

Mais là le problème évident qui se pose, c'est que le champ nb_comments n'existe pas pour l'object jDao. Comme il ne fait pas partie des champs de base de la dao, lors de l'exécution de la requete, cette (ou ces) donnée(s) externe(s) sont rangées dans un attribut public de l'object (->ext par exemple) permettant d'y accéder naturellement par la suite sans polluer l'objet dao :

Après l'exécution de la requete précédente par exemple, on pourrait utiliser :


print $article->id;
print $article->blog_id;
print $article->ext->nb_comments;

Change History (3)

comment:1 Changed 13 years ago by Torgan

Pour aider, actuellement, on fait à peu près un truc similaire :

<?php 

abstract class DatabaseElement 
{
        protected $_dao_record = null; 

        /**
        * setFrom
        *
        * set the element from another object
        *
        * @param object $newElement
        * @param array  $except
        *
        * @return boolean
        *
        * @access public
        * @author Yannick Le Guédart (yannick at over-element dot com)
        * @version 1.0
        */
        
        public function setFrom (
                $newElement,
                $except = array ())
        {
                $validFields = array_keys (get_object_vars ($this->_dao_record));

                if (empty ($except) and isset ($newElement->_dao_record))
                {
                        $this->_dao_record = $newElement->_dao_record;
                }
                else
                {
                        if (isset ($newElement->_dao_record))
                        {
                                $newElement = $newElement->_dao_record;
                        }                       
                        
                        foreach ($newElement as $varName => $varValue)
                        {
                                if (! in_array ($varName, $validFields))
                                {
                                        if (empty ($this->external))
                                        {
                                                $this->external = new StdClass ();
                                        }

                                        $this->external->{$varName} = $varValue;
                                }
                                elseif (! in_array ($varName, $except))
                                {
                                        if (in_array ($varName, $validFields))
                                        {
                                                $this->_dao_record->{$varName} = $varValue;
                                        }
                                }
                        }
                }
        }
?>

comment:2 Changed 13 years ago by Torgan

  • Component changed from jelix to jelix:dao
  • Keywords dao sql added

comment:3 Changed 9 years ago by laurentj

  • Documentation needed unset
  • Status changed from new to delayed
Note: See TracTickets for help on using tickets.