Guest User

PDO Select + Object Tree build

a guest
Sep 25th, 2021
78
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 5.34 KB | None | 0 0
  1.     //******************************************************************************************************************
  2.  
  3.     /**
  4.      * Builds a PDO prepared statement with the given parameters
  5.      *
  6.      * @param array $args
  7.      * Holds the WHERE clause
  8.      * Expected Format: array("Column Name" => array("Comparison Operator", "Value"))
  9.      *
  10.      * @param bool $fetchImmediately
  11.      * Defines whether or not the value is to be fetched immediately. If given FALSE the prepared statement is returned instead.
  12.      *
  13.      * @param bool $alwaysFetchArray
  14.      * Defines whether or not there's always an array to be returned, even if the executed statement would only return one row.
  15.      * Handy when multiple results are expected but when single ones are possible as well.
  16.      */
  17.     public static function select($columns,
  18.                                   $table,
  19.                                   $args = array(),
  20.                                   $alwaysFetchArray = false,
  21.                                   $orderBy = "",
  22.                                   $orderDirection = "ASC",
  23.                                   $limit = "",
  24.                                   $groupBy = "",
  25.                                   $fetchImmediately = true)
  26.     {
  27.         //The base query string.
  28.         $sql = "SELECT ".$columns." FROM ".$table;
  29.  
  30.         //Adds the WHERE-clause and the necessary placeholders if specified
  31.         if ($args)
  32.         {
  33.             $sql = $sql." WHERE ";
  34.  
  35.             $columnNames = array_keys($args);
  36.             $columnVals = array();
  37.  
  38.             for ($i = 0; $i < count($columnNames); $i++)
  39.             {
  40.                 $compOperator = array_values($args)[$i][0];
  41.  
  42.                 array_push($columnVals, array_values($args)[$i][1]);
  43.  
  44.                 if ($i == 0)
  45.                 {
  46.                     $sql .= $columnNames[$i]." ".$compOperator." ?";
  47.                     continue;
  48.                 }
  49.  
  50.                 $sql .= " AND ".$columnNames[$i]." ".$compOperator." ?";
  51.             }
  52.         }
  53.  
  54.         //Adds the GROUP BY-clause, if specified
  55.         if ($groupBy)
  56.         {
  57.             $sql .= " GROUP BY ".$groupBy;
  58.         }
  59.  
  60.         //Adds the ORDER BY-clause, if specified
  61.         if ($orderBy)
  62.         {
  63.             $sql .= " ORDER BY ".$orderBy." ".$orderDirection;
  64.         }
  65.  
  66.         //Adds the LIMIT-clause, if specified
  67.         if ($limit)
  68.         {
  69.             $sql .= " LIMIT ".$limit;
  70.         }
  71.  
  72.         //Prepares the built statement
  73.         $stmt = self::$db->prepare($sql);
  74.  
  75.         //Executes the statement either with the specified values or without any.
  76.         if (count($args))
  77.         {
  78.             $stmt->execute(array_values($columnVals));
  79.         }
  80.         else
  81.         {
  82.             $stmt->execute();
  83.         }
  84.  
  85.         //Determines that the result is to be fetched as an instance of a class. Table names are expected as T[classname]
  86.         $stmt->setFetchMode(PDO::FETCH_CLASS, substr($table, 1));
  87.  
  88.         if (!$fetchImmediately)
  89.         {
  90.             return $stmt;
  91.         }
  92.  
  93.         return self::buildComplexObjectTree($stmt, $alwaysFetchArray);
  94.     }
  95.  
  96.     //**********************************************************************************************************
  97.  
  98.     public static function buildComplexObjectTree($stmt, $alwaysFetchArray)
  99.     {
  100.         //Fetches the query result
  101.         $result = $stmt->fetchAll();
  102.  
  103.         foreach ($result as $obj)
  104.         {
  105.             //Look through columns to find potential foreign keys columns.
  106.             $fkCols = array();
  107.             for ($i = 0; $i < $stmt->columnCount(); $i++)
  108.             {
  109.                 $m = $stmt->getColumnMeta($i);
  110.  
  111.                 if (str_starts_with($m['name'], "fk"))
  112.                 {
  113.                     array_push($fkCols, $m['name']);
  114.                 }
  115.             }
  116.  
  117.             //Loops through all found foreign key columns and sets the respective values.
  118.             foreach ($fkCols as $fkCol)
  119.             {
  120.                 //Takes the fk columns name and returns substring representing the classname for the object
  121.                 $objName = substr($fkCol, 2);
  122.  
  123.                 //Helps dealing with edge cases in which a table has multiple forein keys referencing the same table
  124.                 //e.g. private messages.
  125.                 //Expected Format: fkUserRecipient and fkUserSender
  126.                 if (preg_match("^(.*?[A-Z]){2,}.*$^", $objName))
  127.                 {
  128.                     $arr = preg_split('#([A-Z][^A-Z]*)#', $objName, null, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
  129.                     $objName = $arr[0];
  130.                     $propertyName = $arr[1];
  131.                 }
  132.  
  133.                 //Holds the name of the setter function
  134.                 $setterFunc = isset($propertyName) ? "set".$propertyName : "set".$objName;
  135.  
  136.                 //Holds the current foreign key value in the format expected from the select method
  137.                 $argArray = array("pk".$objName => array("=", $obj->$fkCol));
  138.  
  139.                 //Queries the Database for the entry with the specified foreign key
  140.                 $obj->$setterFunc(Database::select("*", "T".$objName, $argArray));
  141.             }
  142.  
  143.             if (count($result) == 1 && !$alwaysFetchArray)
  144.             {
  145.                 return $obj;
  146.             }
  147.         }
  148.  
  149.         return $result;
  150.     }
Advertisement
Add Comment
Please, Sign In to add comment