IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage PHP Discussion :

conseil sur les requêtes SQL en MVC [PHP 5.3]


Sujet :

Langage PHP

  1. #21
    Membre actif Avatar de grinder59
    Inscrit en
    Septembre 2005
    Messages
    707
    Détails du profil
    Informations forums :
    Inscription : Septembre 2005
    Messages : 707
    Points : 215
    Points
    215
    Par défaut
    ok, j'ai toujours un peu de mal à voir comme cela pourrait s'implémenter. Cet exemple ci-dessous va-t-il dans le bon sens selon toi ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
     
    class where{
        private $type = 'where';
        $detail;
        public function __construct($p){
    	$detail = $p;
        }
    }
     
    class select{
     
    	$sel = array();
    	$table;
    	$where;
    	$orderby;
    	$limit;
     
    	public function __contruct($p){
    		foreach ($p as $v){
    			$sel .= ($sel != '') ? ', ' : '';
    			$sel .= $v;
    		}
    	}
    	public function setWhere($p){
                $where = new where($p);
            }
    }
     
    class categorieModel extends model{
     
    	$tab = array('col1', 'col2');
    	$tab2 = array('col1');
     
     
            // recherche générale
    	$s = new select($tab);
    	$s->setTable(...);
    	$s->execute();
     
            // recherche restreinte
    	$s = new select($tab);
    	$s->setTable(...);
    	$s->setWhere(...); 
    	$s->execute();
     
            // recherche avec une liste de champs différents des requêtes précédentes
            $s = new select($tab2);
            ....
     
    }

  2. #22
    Expert éminent sénior
    Avatar de rawsrc
    Homme Profil pro
    Dev indep
    Inscrit en
    Mars 2004
    Messages
    6 142
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Dev indep

    Informations forums :
    Inscription : Mars 2004
    Messages : 6 142
    Points : 16 545
    Points
    16 545
    Billets dans le blog
    12
    Par défaut
    Il faut que tu poses avec un papier et un crayon pour modéliser le système en suivant la spec SQL.
    Si tu vas à tâtons tu n'y arriveras pas.

    N'oublie pas que les couches d'abstraction de bases de données sont généralement complexes.
    Si tes connaissances en SQL sont trop basses, prends le temps d'améliorer la théorie sinon tu ne t'en sortiras pas.

    Enfin, vu que le sujet à modéliser est complexe, le code PHP qui va implémenter tout ceci sera lui aussi du même niveau. Tu dois avoir un bon niveau dans les 2 mondes pour y arriver.
    Si cela est problématique, regarde du côté de ce qui existe déjà, inspire-toi en ou à la rigueur utilise le produit tel quel et avec la pratique tu devrais y arriver à le dépiauter pour bien comprendre son architecture.
    Ce qui devrait te fournir une base de travail pour la conception personnalisée de ta propre couche.

    Si tu étudies le SQL tu verras que les clauses Where et Having fonctionnent de manière semblable à un ou deux détails près.
    Chez moi pour la clause Where cela donne ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
        class Where
        extends Filter
        {
            /**
             * @param  Statement $statement
             * @param  ParamsExt $params
             * @return Where
             */
            public function __construct(Statement $statement, ParamsExt $params = null)
            {
                parent::__construct($statement, 'where', $params);
            }
        }
    C'est parce que derrière il y a une vraie architecture posée

  3. #23
    Membre actif Avatar de grinder59
    Inscrit en
    Septembre 2005
    Messages
    707
    Détails du profil
    Informations forums :
    Inscription : Septembre 2005
    Messages : 707
    Points : 215
    Points
    215
    Par défaut
    Ok...

    merci d'avoir pris le temps de me guider... En fait, je pensais que tes réponses faisaient références à des outils précis ou des implémentations références alors qu'en fait, c'est quelque chose de personnel que je vais devoir mettre en oeuvre et qui sera guidé par mes besoins...

    dernier truc, pourrais-tu me montrer ton implémentation de ta classe Filter stp ?

    Merci encore !

  4. #24
    Expert éminent sénior
    Avatar de rawsrc
    Homme Profil pro
    Dev indep
    Inscrit en
    Mars 2004
    Messages
    6 142
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Dev indep

    Informations forums :
    Inscription : Mars 2004
    Messages : 6 142
    Points : 16 545
    Points
    16 545
    Billets dans le blog
    12
    Par défaut
    Comme je te l'ai dit c'est péchu, j'suis pas sûr que tu y comprennes des masses :
    mon système s'adapte aussi bien à du MySql que de Postgresql qui lui utilise des types de données non compatible avec PDO, d'où la petite complexité en plus...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
        abstract
        class Filter
        extends Clause
        {
            /**
             * Par défaut la clause n'accèpte pas les multiples jeux de données
             *
             * @param Statement $statement
             * @param string    $role
             * @param ParamsExt $params
             */
            public function __construct(Statement $statement, $role, ParamsExt $params = null)
            {
                parent::__construct(
                    $statement,
                    (($params === null) ? new ParamsExt() : $params),
                    $role
                );
            }
     
            /**
             * Indique si le statement accepte et possède plusieurs jeux de données
             *
             * @return bool
             */
            public function isMultiLevel()
            {
                return ($this->statement()->data()->isMultiLevels() && $this->params()->acceptsMultipleSetsOfData());
            }
     
            /**
             * Constructeur standard de la clause
             * Le builder renvoie une instance de SqlFragment() ou EECollector
             *
             * @return \Closure
             */
            protected function standardBuilder()
            {
                return
                    function()
                    {
                        // si plusieurs jeux de critères sont autorisés : on les récupère tous sinon que le premier
                        if ($this->statement()->data()->isEmpty())
                        {
                            $levels = [];
                        }
                        elseif ($this->isMultiLevel())
                        {
                            $levels = $this->statement()->data()->arrayOfLevels();  // [level]
                        }
                        else
                        {
                            $levels = [$this->statement()->data()->firstLevelKey()];
                        }
     
                        // contrôle de la présence des alias obligatoires au niveau de la clause
                        $valid_levels = [];                         // [level]
                        $required     = $this->requiredAliases();
     
                        if ( ! empty($required))
                        {
                            // [passed => [levels], failed => [level => missing alias]]
                            $test = $this->statement()->tools()->checkRequiredAliases($required, $levels);
                            if ( ! empty($test['failed']))
                            {
                                return EECollector::init()->addAlert('alias.missing');
                            }
     
                            $valid_levels = $test['passed'];
                        }
                        else
                        {
                            $valid_levels = $levels;
                        }
     
                        if (empty($valid_levels))
                        {
                            return new SqlFragment();
                        }
     
     
                        // alias utilisables au niveau de la clause
                        $usable_aliases = $this->usableAliases();
                        if (empty($usable_aliases))
                        {
                            return new SqlFragment();
                        }
     
                        $ucs = array_intersect($this->params()->ucs(), $usable_aliases);
                        $mcs = array_intersect($this->params()->mcs(), $usable_aliases);
     
                        // validation des données
                        $test = $this->statement()->tools()->validateData($usable_aliases, $valid_levels, $ucs, $mcs);
                        if ( ! empty($test['failed']['levels']))
                        {
                            return EECollector::init()->addAlert('invalid.data.type');
                        }
     
                        /*
                        on renvoit la chaine SQL avec champ operateur :tag
                        les critères au sein de chaque jeu sont séparés par AND et les jeux de critères sont séparés par OR
                        ( (ligne1) OR (ligne2) ) => ( ((bloc11) AND (bloc12) AND (...)) OR ((bloc21) AND (bloc22) AND (...)) )
                        on gère les ucs et mcs
                        à l'exécution et en fonction des autres clauses, PDO pourra être utilisé ou pas
                            => les :tag pourront être remplacés par leurs valeurs plates si le statement est incompatible avec PDO
                        */
                        $formatter     = $this->statement()->formatter();
                        $func          = ($this->role() === 'where') ? 'resolvedDefinition' : 'definition';
                        $sql           = [];
                        $params        = [];    // [level => [alias => :tag]]
                        $no_preparable = [];    // liste des alias utilisés et non compatibles avec PDO::prepare() [alias]
     
                        foreach ($valid_levels as $level)
                        {
                            // [alias => my_var]
                            $data          = $this->statement()->data()->valuesOfLevel($level, $usable_aliases);
                            $tags          = $this->statement()->tools()->generateTagsForAliases(array_keys($data));   // [alias => :tag]
                            $no_preparable = array_merge($no_preparable, $this->usedAliases($level, false));           // alias non compatible avec PDO::prepare()
                            $filter        = [];
     
                            foreach ($data as $alias => $my_var)
                            {
                                // nom du champ
                                $field = $this->statement()->structure()->$func($alias);
                                // détermine l'opérateur final
                                $operator = $formatter::paramOperator(
                                    $my_var,
                                    in_array($alias, $ucs, true),
                                    in_array($alias, $mcs, true)
                                );
     
                                $filter[] = $field.$operator.$tags[$alias];
                            }
     
                            $sql[]          = '('.implode(' AND ', $filter).')';
                            $params[$level] = $tags;
                        }
     
                        return SqlFragment::init()
                                          ->setSql(implode(' OR ', $sql))
                                          ->setParams($params)    // [level => [alias => :tag]]
                                          ->setNoPreparableAliases(array_unique($no_preparable))
                                          ->setUcs($ucs)
                                          ->setMcs($mcs);
                    };
            }
     
            /**
             * Synchronise le paramétrage de la clause avec celui en paramètre
             *
             * @param ExecParams $p
             * @param array      $stpi Tableau des groupes interdits au niveau du statement
             */
            public function syncParams(ExecParams $p, array $stpi)
            {
                $actions = $p->actions();
     
                if (in_array('m', $stpi, true))
                {
                    $this->params()->setMcs([]);
                }
     
                if (in_array('u', $stpi, true))
                {
                    $this->params()->setUcs([]);
                }
     
                $key = ($this->role() === 'where') ? 'w' : 'h';
     
                if (in_array($key, $stpi, true))
                {
                    $allowed = $this->params()->allowed();
                    $this->params()->setAllowed([]);
                    $this->params()->addForbidden($allowed);
                }
                else
                {
                    // alias autorisés
                    $list = $p->listOfAliases("{$key}a");
                    if ( ! empty($list))
                    {
                        $this->params()->addAllowed($list['aliases'], $list['ext']);
                    }
     
                    // alias interdits
                    $list = $p->listOfAliases("{$key}i");
                    if ( ! empty($list))
                    {
                        $this->params()->addForbidden($list['aliases']);
                    }
     
                    // alias obligatoires
                    $list = $p->listOfAliases("{$key}o");
                    if ( ! empty($list))
                    {
                        $this->params()->addRequired($list['aliases']);
                    }
     
                    // alias gérant les métacaractères
                    $list = $p->listOfAliases("{$key}mcs");
                    if ( ! empty($list))
                    {
                        $this->params()->addMcs($list['aliases'], $list['ext']);
                    }
     
                    // alias gérant les signes de comparaison
                    $list = $p->listOfAliases("{$key}ucs");
                    if ( ! empty($list))
                    {
                        $this->params()->addUcs($list['aliases'], $list['ext']);
                    }
     
                    // multiples jeux de données
                    if (isset($actions["{$key}msd"]))
                    {
                        $this->params()->setMultipleSetsOfData($actions["{$key}msd"]);
                    }
                }
            }
        }

  5. #25
    Membre actif Avatar de grinder59
    Inscrit en
    Septembre 2005
    Messages
    707
    Détails du profil
    Informations forums :
    Inscription : Septembre 2005
    Messages : 707
    Points : 215
    Points
    215
    Par défaut
    En effet, c'est pas simple...
    mais peu importe, l'essentiel, en conclusion, est que je développe mes propres classes gérant la création et l'exécution des requêtes en fonction de mon besoin.
    Merci pour ta patience !

+ Répondre à la discussion
Cette discussion est résolue.
Page 2 sur 2 PremièrePremière 12

Discussions similaires

  1. Réponses: 6
    Dernier message: 22/08/2014, 15h57
  2. [Débutant] Question sur les requêtes SQL
    Par Genyuumaru dans le forum ASP.NET MVC
    Réponses: 4
    Dernier message: 08/10/2012, 08h43
  3. Réponses: 4
    Dernier message: 21/04/2012, 12h56
  4. [MySQL] [POO] Sécurité sur les requêtes SQL
    Par Sh4dow49 dans le forum PHP & Base de données
    Réponses: 3
    Dernier message: 24/10/2008, 10h51

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo