2 votes

PHP Transformez la fonction tableau récursif en classe

J'ai une fonction simple de tableau récursif qui ressemble à ceci :

function recursive_array($results) {
    global $DBH;
    if (count($results)) {
        echo $res - > Fname;
        foreach($results as $res) {
            $STH = $DBH - > query("SELECT FID,FParentID,Fname FROM list WHERE FParentID  = ".$res - > FID."");
            $fquerycount = $STH - > rowCount();
            $STH - > setFetchMode(PDO::FETCH_OBJ);
            recursive_array($STH);
        }
    }
}

$FID = isset($_GET['FID']) ? $_GET[' FID'] : 0;
$STH = $DBH - > query("SELECT FID,FParentID,Fname FROM list WHERE FParentID ='0' ");
$STH - > setFetchMode(PDO::FETCH_OBJ);
recursive_array($STH);

J'ai également créé une classe de requête simple qui ressemble à ceci :

class queryloop {
    function __construct($args) {
        global $DBH;
        $table = $args['tbl'];
        if (array_key_exists('orderby', $args)): $orderby = 'ORDER BY '.$args['orderby'];
        else: $orderby = '';endif;
        if (array_key_exists('groupby', $args)): $groupby = 'GROUP BY '.$args['groupby'];
        else: $groupby = '';endif;
        if (array_key_exists('start', $args)): unset($orderby);$start = $args['start'].' , ';
        else: $start = '';endif;
        if (array_key_exists('limit', $args)): $limit = 'LIMIT '.$start.' '.$args['limit'];
        else: $limit = '';endif;
        // UNSET the previously used array keys so they are not use again to create the query string
        unset($args['tbl']);
        unset($args['orderby']);
        unset($args['groupby']);
        unset($args['start']);
        unset($args['limit']);
        // Checks if args still an array after UNSET above.  If not empty create the query string
        if (!empty($args)): foreach($args as $k = > $v): $querystr. = 'AND '.$k.' = \''.$v.'\'';endforeach;
        // If args array empty return empty query string
        else: $querystr = '';endif;$STH = $DBH - > query("SELECT * FROM ".$table." WHERE key = '".KEY."'  ".$querystr."  ".$groupby." ".$orderby."  ".$limit." ");
        if ($STH): $STH - > setFetchMode(PDO::FETCH_OBJ);
        while ($row = $STH - > fetch()): foreach($row as $key = > $val):
        // check if value is numeric //        
        if (is_numeric($row - > $key)): $data[$row - > ID][$key] = $row - > $key;
        // check if value is array //
        elseif(is_array($row - > $key)): $data[$row - > ID][$key] = $row - > $key;
        // check if value is not numeric or array convert to html entities //
        else: $data[$row - > ID][$key] = htmlentities($row - > $key);endif;endforeach;endwhile;$this - > data = json_encode($data); // return json array if data
        else: $this - > data = ''; // return 'null' if no data
        endif;
    }
}

$args = array('tbl' = > 'atable', 'limit' = > '5', 'start' = > '200', 'orderby' = > 'ID DESC');
$loop = new queryloop($args) // run the loop etc.

Comment puis-je transformer mon tableau récursif en quelque chose comme la classe queryloop afin de pouvoir "extraire" des données codées en json ? Je sais que cela (ci-dessous) est totalement erroné mais quoi que je fasse, je n'arrive pas à obtenir un tableau json correctement formé ou même quelque chose à retourner depuis ma tentative de classe ci-dessous. Une aide serait très appréciée. Merci d'avance.

class recloop {
    function __construct() {}

    function recursive_array($results) {
        global $DBH;
        if (count($results)) {
            foreach($results as $res) {
                echo $res - > Name;
                $STH = $DBH - > query("SELECT * FROM atable WHERE ParentID  = ".$res - > ID."");
                $fquerycount = $STH - > rowCount();
                $STH - > setFetchMode(PDO::FETCH_OBJ);
                recursive_array($STH);
            }
        }
    }

    function recursive_start() {
        global $DBH;
        $ID = isset($_GET['ID']) ? $_GET['ID'] : 0;
        $STH = $DBH - > query("SELECT * FROM atable WHERE ParentID  = '".$ID."' ");
        $STH - > setFetchMode(PDO::FETCH_OBJ);
        recursive_array($STH);
    }
}

2voto

hakre Points 102271

Comment puis-je transformer mon tableau récursif en quelque chose comme la classe queryloop afin de pouvoir "extraire" des données codées en json ? Je sais que cela (ci-dessous) est totalement erroné mais quoi que je fasse, je n'arrive pas à obtenir un tableau json correctement formé ou même quelque chose à retourner depuis ma tentative de classe ci-dessous. Une aide serait très appréciée. Merci d'avance.

Pour répondre à votre question, je dirais que le fait que vous encapsuliez ou non vos routines dans des objets n'est pas très important, mais que vous veillez à ce que chaque objet soit là dans un but unique. Par exemple :

  • Un objet va chercher les données dans la base de données.
  • Un objet/composite/rayon est la structure de données, représentant les données.
  • Un objet ou une fonction prend en charge le travail de conversion/encodage des données en json.

Dans votre code, je vois que vous n'exécutez pour l'instant que des requêtes SQL. Les données récupérées du serveur de base de données ne sont pas du tout stockées dans une variable de retour, elles sont directement consommées lors du traitement récursif. Je suppose que vous faites cela pour des raisons de débogage.

La vraie question est donc : que voulez-vous faire ? Vous écrivez que vous voulez encoder un objet en sortie json, ce qui est parfaitement possible avec json_encode Docs Cependant, je pense que vous vous référez à des données spécifiques, comme l'entité (données) du plus parentId ou autre.

Voici une maquette de code basée sur votre code à des fins de lecture (non testé, ne doit pas correspondre à vos besoins) qui peut fournir tous les objets parents de celui spécifié par l'ID en utilisant la récursion. La récursion a été critiquée parce qu'elle peut entraîner l'exécution d'un grand nombre de requêtes - et de plus, il y a un risque de créer une boucle sans fin qui entraînera un dépassement de la pile de récursion - votre programme se bloque alors.

Pour gérer cela de manière alternative, cela est lié à la conception de la base de données (qui devrait être faite avant la conception du code, et je ne connais pas la conception de votre base de données ni ce que vous voulez réellement faire, donc je ne peux pas ajouter d'hypothèses pour cela). Ainsi, le code suivant s'occupe uniquement des objets déjà interrogés tout en utilisant la récursion comme stratégie d'interrogation de votre base de données.

Pour la structure de données proprement dite, j'ai opté pour un tableau de vieux objets PHP, dont les clés sont les suivantes ID de la base de données (je suppose qu'il existe par enregistrement) :

/**
 * HTTP Get Parameter (Input)
 */
class HTTPGetParameter {
    private $name;
    private $default;
    public function __construct($name, $default = '') {
        $this->name = (string) $name;
        $this->default = (string) $default;   
    }
    /**
     * @return string
     */
    public function getValue()
    {
        return isset($_GET[$name]) ? $_GET[$name] : $this->default;
    }
    /**
     * @return int
     */
    public function getValueInt()
    {
        return (int) $this->getValue();
    }
    /**
     * @link http://www.php.net/manual/en/language.oop5.magic.php#language.oop5.magic.tostring
     */
    public function __toString()
    {
        return $this->getValue();
    }
}

/**
 * Data Provider
 */
class PDODataProvider
{
    private $pdo;
    public function __construct(PDO $pdo)
    {
        $this->pdo = $pdo;
    }
    /**
     * @return array
     */
    public function findAllATableParents($id)
    {
        return $this->findAllOn('atable', 'ParentID', $id);
    }
    public function findAllBTableParents($id)
    {
        return $this->findAllOn('btable', 'ParentID', $id);
    }
    private function findAllOn($table, $field, $id)
    {
        $id = (int) $id;

        $objects = array();

        $sql = sprintf("SELECT * FROM %s WHERE %s  = '%d'", $table, $field, $id);
        $pdoStatement = $this->pdo->query($sql);
        $pdoStatement->setFetchMode(PDO::FETCH_OBJ);

        foreach($pdoStatement as $parent)
        {
             $parentId = $parent->ID;

             # parents that had been queried are skipped
             if (isset($objects[$parentId]))
                 continue;

             $objects[$parentId] = $parent;

             # add parent objects by recursion
             $objects += $this->findAllParents($parentId);
        }
        return $objects;
    }
}

/**
 * main
 */
$data = new PDODataProvider($DBH);

$id = new HTTPGetParameter('ID', 0);

$objects = $data->findAllParents($id->getValueInt());

echo json_encode($objects);

J'espère que cet exemple vous aidera à répondre à votre question.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X