Page 1 sur 1

GETTER 2 le retour 4

Posté : 06 nov. 2010, 00:08
par Nours312
Salut !...

A y est, je me colle aux Objets complexes !... et ça va pas être joli-joli !...

Donc, je vous expose mes contraintes !

Nous avons actuellement un logiciel (dont je ne suis pas le codeur initial :@) qui est un cafarnaum complet !...
un espèce de POO PHP3 ... pour dire !..

des classes mal montées qui appellent des global à tout bout de champs des scripts en vrac dans tous les sens, et des pages dont personne ne sais si elles servent encore !... mais ça fonctionne !...
et près de 10 000 personnes l'utilisent quotidiennement !...

je dois donc participer à une refonte Globale tout en migrant progressivement vers une structure cohérente rigide !..
On s'est donné 1 ans pour effectuer cette migration tout en continuant à le faire évoluer, ce qui va nous obliger à envisager de mettre en place une logique rigide rapidement pour ne plus continuer à coder tels qu'actuellement !..

On a aussi deux soucy majeur :
1. des codeurs qui ne pigent pas tout ... et qui font des boulettes à tour de bras (requête dans la bdd en directe depuis le HTML sans prendre en considération les droits de l'utilisateur ... )
2. un BDD ... comment dire ... exotique ^^
il nous est impossible d'envisager de la refondre sans avoir stabiliser le comportement des classes php car ce serait trop long à recoder ^^ ...

Donc, la mission que je suis sur le point d'accepter est d'envisager, 1 l'introduction d'une logique MVC, 2 la refonte progressive de l'ensemble des objets PHP et leurs stabilisation (un objet de 4 000 lignes de script est forcément instable ^^), 3 : trouver un moyens pour permettre aux codeurs consciencieux de perdre moins de temps en contrôlant le code des autres !... ceci avant de l'auto-détruire, cela va de soit :)


Donc, nous avons envisagé la mise en place d'interfaces, de tests unitaires, et autres namespaces pour les futurs contrôleurs de notre MVC, et j'envisage de les faire héritée d'une classe Mère en charge de dispatcher les getter et les setters afin d'assurer le typage des données interfaçant avec la BDD !...

je vous propose donc cet exemple (fonctionnel sous php > 5.3) et vous pri de me dire ce qui va et ce qui ne va pas avec ce principe de fonctionnement :D
<?php
class A {
	protected $dataType = array(
		"boolean" => array('is'),
		"integer" => array('id'),
		"float" => array('num'),
		"string" => array('name'),
		"array" => array('table'),
		"object" => array('data')
	);
  // comportement STATIC de la classe !... utiliser pour récupérer des groupes d'objets
    public static function __callStatic($name, $arguments) {
        if (method_exists(self::clName(), $name))
            return call_user_func_array(array(self::clName(), $name), (array)$arguments);
        if (strpos($name, 'get') == 0){
            return call_user_func_array(array(self::clName(), '_getListe'), array(substr($name, 3), $arguments));
        }
    }
    /**
     *
     * @param string $value nom de la methode apelée en get
     * @param array $arguments arguments envoyés dans la fonction mis en tableau
     * @return array retuourne un tableau de données
     */
    protected static function _getListe($value, $arguments) {
        if(method_exists(self::clName(), 'load'.$value))
            call_user_func_array (array(self::clName(), 'load'.$value), (array)$arguments) ;
        $arrayReturn = array();
        // mise en minuscule de la premiere lettre du nom de la variable
        $value = strtolower(substr($value, 0,1)).substr($value, 1);
        $objName = self::clName() ;
        if(isset($objName::${$value})){
            foreach ($objName::${$value} as $value) {
                $arrayReturn[] = new $objName($value) ; // creation des objets peux etre une option soumise au filtrage du typage
            }
            return $arrayReturn;
        }
    }
	/**
	 *
	 * @return string le nom de la classe appelée
	 */
	private static function clName(){
		return get_called_class() ;
	}

// comportement OBJET de la classe pour travailler purement avec un objet défini
    function __construct($param) {
//        $this->bdd = getBd();
        if(method_exists($this, "load".$this->className()))
            $this->{"load".$this->className()}((int)$param);
    }
	private function className(){
		return get_class($this) ;
	}
    public function __call($method, $arguments) {
        if (method_exists($this, $method))
            return call_user_func_array(array($this, $method), $arguments);
        if (strpos($method, 'get') === 0)
            return call_user_func_array(array($this, '_get'), array(substr($method, 3), $arguments));
        if (strpos($method, 'set') === 0)
            return call_user_func_array(array($this, '_set'), array(substr($method, 3), $arguments));
        if (strpos($method, 'sav') === 0)
            return call_user_func_array(array($this, '_sav'), array(substr($method, 3), $arguments));
        if (strpos($method, 'add') === 0)
            return call_user_func_array(array($this, '_add'), array(substr($method, 3), $arguments));
        if (strpos($method, 'del') === 0)
            return call_user_func_array(array($this, '_del'), array(substr($method, 3), $arguments));
    }


    /**
     *
     * @param string $value nom de la propriété et typage à récupérer
     * @param array $arguments arguments envoyés dans la fonction mis en tableau
     * @return <type> retourne les données protected de l'objet mis en forme
     */
    protected function _get($value, $arguments) {
		$pos = strpos($value, '_');
        if ($pos !== false) {
            $d = substr($value, $pos + 1);
            if (isset($this->{$d})) {
                $data = $this->{$d};
                if (settype($data, $this->getTypeData(substr($value, 0, $pos))))
                    return $data;
            }
        }
        // return false ;
    }

    /**
     *
     * @param string $value nom de la propriété et typage à affecter à l'objet
     * @param array $arguments valeurs devant être affectées à l'objet
     * @return boolean retourne un boolean indiquant si les données ont bien été affectées à l'objet
     */
    protected function _set($value, $arguments) {
		$pos = strpos($value, '_');
        if ($pos !== false) {
            $d = substr($value, $pos+1);
            $data = current($arguments);
            if (settype($data, $this->getTypeData(substr($value, 0, $pos)))) {
                $this->{$d} = $data;
                return $this;
            }
        }
    }

    /**
     *
     * @param string $param valeur de typage demandée.
     * @return string retourne le nom du type demandé
     */
    protected function getTypeData($param) {
        $type = 'NULL';
        foreach ($this->dataType as $t => $v)
            if (in_array($param, $v))
                return $t;
        return $type;
    }
}
class B extends A {
    protected static $bs ; // en charge de recevoir le tableau d'objets B
		protected $idB ;
    protected $nB ;
    protected function loadB($id){
        $this->setid_idB($id) ;
        $this->setname_nB("monId_".$id) ;
    }
    protected static function loadBs(){
        self::$bs = array() ;
        for($i=0;$i<4;$i++)
            self::$bs[] = "".$i."" ;
    }
}

/*
 * Nous pourrions simplifier en faisant en sorte de typer les données issue de la BDD
 * et utiliser idB au lieux de id_idB, ce serait bien plus simple à l'utilisation et
 * certainement plus sécurisant, mais ça oblige à structurer de façon drastique l'ensemble
 * des noms de champs de la bdd !...
 *
 * Autre chose ::
 *
 * j'ai ajouter les methodes _add / _save / _del qui aurait pour utiliter les transimitions
 * avec la BDD

 *
 */

foreach (B::getBs() as $k => $B){
	echo 'Object : '.$k.' name : '.$B->getname_nB().', id : '.$B->getid_idB().'<br />';
}
?>
cette version aurait pour principe de permettre de récupérer toutes les données de l'objet chargées automatiquement suivant un typage passé en paramètre dans le nom du getter !...
à plus ou moins long termes, en refondant la BDD nous modifierons tous les noms des champs (et par la même occasion le nom des méthodes les appelants pour intégrer à la source dans le nom de la colonne de la table de la bdd plus d'éléments sur son typage (int/string / ... nom de l'objet auquel il appartient / ... conditions d'utilisations, ...
Ainsi nous aurions juste avec le nom du champs de la bdd des moyens de contrôle et de test pour vérifier les conditions de son utilisation !...
mais ce n'est actuellement pas le cas :D


donc ... dans le script fournis, il y a deux utilisation de l'objet B
- une static qui sert à retourner des collections d'objets (exemple mails::getMails($dateMin) retournerais dans un tableau tous les Objets mails dont la date de référence serait supérieure à $dateMin, on pourrait aisément transmettre ça à la vue qui ferait un tableau de présentation agréable ! :)
- une non-static qui est celle que l'on utilise classiquement pour les objet et qui correspondrait à toutes les méthodes que pourrait avoir l'objet new mail($id) ex :: $mail->response() / $mail->getDestinataire() / ... ... ..

Voila !..

sur le papier cela semble bien, fonctionnel, agréable ... mais dans la pratique !?
actuellement je découpe 3/4 fois les noms de chaque méthode appelée pour en extraire les contraintes ! si ça continu, il va y avoir surement plus de traitement encore pour extraire les droits, les conditions d'utilisation, des vérifications extérieur avec les sessions, ... ... Est-ce qu'il y aurait plus souple pour le serveur ? ou est-ce que c'est une des meilleurs solutions envisageable dans les conditions actuelle, et un simple 16 cœur 3Ghz couplé à 24 G de ram seront plus rentables que de recoder les 10 000 fichiers qui composent le logiciel ?? :D


Merci Beaucoup si vous avez réussi à me lire jusqu'ici, et encore plus si vous avez une réponse qui puisse m'aider .. (et pour info, j'ai déjà testé la corde, c'est pas top ^^)

@++

Re: GETTER 2 le retour 4

Posté : 06 nov. 2010, 06:44
par stealth35
de toutes façons tout projet par de données a formater/editer, ces données sont visiblement dans une base, qui dit base dit ORM, qui dit ORM dit Doctrine et compagnie,.
Ton concept est deja fait, tes vues aussi, ca devrai allé pour la suite, a mon boulot j'ai du adapter un projet qui avait 15 ans avec une espèce de sous base type Access, la logique était plutôt bonne, les page étant déjà existante, j'ai pas mis longtemps a l'adapter sous le ZF, donc si ta la base (model) si t'as les vues ... il manque plus que le controller :wink:

Re: GETTER 2 le retour 4

Posté : 06 nov. 2010, 13:34
par Nours312
Merci stealth, mais t'en fais pas je saurais mettre en place une structure MVC, meme si actuellement les vues sont en vracs (melange HTML/PHP/MYSQL/CSS/JS... et heureusement qu'on est +/- obligé de de coder en AS dans des fichiers séârés, sinon, il y en aurait surement aussi :) ) et que le model .. n'est pas structuré !... et qu'il faille repenser l'ensemble des controlleurs !

En faite ma question porte surtout sur l'exemple de script que j'ai mis en place tout le blabla autour n'est present que pour situer le pourkoi et le comment j'ai fais des choix sur le montage de la structure de cet exemple ...

donc je reprends mon explicatif :

ici je fait : B::getBs()
et ça me retourne un tableau contenant l'ensemble de mes objets B instanciés

ensuite que je fasse $b->setid_idB("1") ou $b->setid_idB(1) ou $b->setid_idB(true)
lorsque j'appelle $b->getid_idB() il me retourne automatiquement (int)1 ;

ce qui est le but recherché !...

MAIS :: est_ce une bonne méthode ? tant au niveau de la sécurité des données qu'au niveau des ressources serveur consommées par cette analyse constante des méthodes employées ??

Re: GETTER 2 le retour 4

Posté : 09 nov. 2010, 08:32
par Nours312
bon !.... il semblerait que personne n'ai plus d'idée que ça sur les biens fait de cette méthode .. :s
il faudrait que je fasses des tests chrono pour mieux voir au niveau de l'immobilisation ressources ...

Si quelqu'un a un avis, je suis toujours preneur !...

Re: GETTER 2 le retour 4

Posté : 09 nov. 2010, 11:12
par stealth35
oui le statique pour récupérer tout tes objets pourquoi pas, vu que de tout façon il renvoie des objets instanciés, je te conseil d'utilsie les methode __get et __set quitte a les renvoyés vers _get et _set, ce que sera pratique par exemple au niveau de PDO, un FETCH_CLASS te renverra direct un object de la classe correspondante avec les valeurs qui vont avec.
Apres c'est un simple CRUD qui tu souhaite faire non ?

Re: GETTER 2 le retour 4

Posté : 09 nov. 2010, 20:35
par Nours312
Merci de ta réponse :D

un CRUD ... ? j'ai peut-être pas toutes les notions, mais il me semble que oui !...
ce que je souhaites c'est créer des méthodes qui seront en charge de garantir l'intégrité des données et/ou d'effectuer des opérations en liaison avec le Model (PDO_etendu à continuer d'étendre) tels que des save et autres ...

Cette classe serait étendue à tous les controller du logiciels et ainsi au fur et a mesure, on aurait une structure plus stable qu'actuellement ...

mais mon interrogation principal est sur le traitement, le fait découper plusieurs fois et systématiquement le nom des méthodes, ça ne risquerait pas à termes de trop alourdir le traitement des scripts ??
considérant que les objets en interne travaillent aussi avec les getters (pour uniformiser le code et rendre modulable le nom des propriétés, et par conséquence celui des méthodes) on va rapidement avoir plusieurs centaines d'appels à la methode __call() et donc d'autant plus d'analyses et découpages ...
c'est une chose qui à termes m'inquiète !..
Et je me demande si il ne serait pas préférable de passer par des interfaces lourdes, couplées à une analyse minutieuse du code source pour s'assurer que les codeurs types bien leurs données tant en entrée qu'en sortie de méthode ...

Qu'en penses tu ?