Advertisement
Guest User

Untitled

a guest
Jul 18th, 2017
107
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 16.76 KB | None | 0 0
  1. <?php
  2. /**
  3.  * Klassen används för att hantera SQL frågor/querys till MySQL.<br />
  4.  * @param String $query Själva SQL frågan som ska ställas till databasen.
  5.  * Parametern är inte obligatorisk, det går att använda funktionen
  6.  * newQuery($query) till att ställa SQL frågan vid ett senare tillfälle.
  7.  * @version 3.2.1
  8.  */
  9. final class MySQLQuery{
  10.  
  11.     /**
  12.      * Den SQL fråga som har ställts till databasen.
  13.      * @var string
  14.      */
  15.     private $query;
  16.  
  17.     /**
  18.      * Svaret från databasen efter att frågan är ställd.
  19.      * @var resource
  20.      */
  21.     private $mysqlResource;
  22.  
  23.     /**
  24.      * Resultatet som kommer från mysql_fetch_array
  25.      * @var Array
  26.      */
  27.     private $result;
  28.  
  29.     /**
  30.      * Error nr som frågan genererat
  31.      * @var int
  32.      */
  33.     private $errorNr;
  34.  
  35.     /**
  36.      * Error meddelandet som frågan genererat
  37.      * @var String
  38.      */
  39.     private $errorMessage;
  40.  
  41.     /**
  42.      * Hur många reder som vart påvärkade
  43.      * @var int
  44.      */
  45.     private $affectedRows;
  46.  
  47.     /**
  48.      * Returnerar det id nummer som genererades av MySQL AUTO_INCREMENT vid den
  49.      * senaste frågan, vanligtvis INSERT, som ställdes till databasen.<br />
  50.      * Om ingen kolumn har AUTO_INCREMENT så returneras 0 eller om frågan inte
  51.      * genererade något id. Om ingen uppkoppling är ettablerad till databasen så
  52.      * returneras false och en E_WARNING genereras..
  53.      *
  54.      * @var int
  55.      */
  56.     private $generatedId;
  57.  
  58.     /**
  59.      * Konstruktor<br />
  60.      * SQL frågan kan ställas direkt till databasen i konstruktorn om så önskas.
  61.      *
  62.      * @param string $query Mall för hur vi vill att SQL frågan ska se ut. SQL
  63.      * frågan ska ha nycklar i sig med inledande kolon tecken ':'<br />
  64.      * <br />
  65.      * <b>Exempel:</b><br />
  66.      * UPDATE users<br />
  67.      * SET pass=:password:<br />
  68.      * WHERE user=:user:<br />
  69.      * <br />
  70.      * I ovanstående exempel har vi två nycklar som är: 'password' och 'user'.
  71.      * Dessa kommer vi att byta ut mot de värden som ska vara där med hjälp av
  72.      * parametern $replaceMap.
  73.      *
  74.      * @param array $replaceMap Karta för vad som ska ersätta vad.<br />
  75.      * <br />
  76.      * <b>Exemplet:</b><br />
  77.      * UPDATE users<br />
  78.      * SET pass=:password:<br />
  79.      * WHERE user=:user:<br />
  80.      * <br />
  81.      * ...gav oss nycklarna 'password' och 'user' som båda ska ersättas med
  82.      * data. Vi gör så via denna parameter genom följande exempel:<br />
  83.      * array('password' => 'hemligt',<br />
  84.      * 'user' => 'erik')<br />
  85.      * <br />
  86.      * Detta kommer ersätta nycklarna med befintligt värde.<br />
  87.      * <b>OBS!</b> heltal ska valideras för att bli behandlade som heltal i
  88.      * SQL frågan...<br />
  89.      * <br />
  90.      * Godtagbara typer i fältet:<br />
  91.      * <b>[string , string | int]</b>
  92.      *
  93.      * @param array $escapeWildcardsMap En valfri parameter som ska finnas med
  94.      * om man vill escapa jokertecken som: '_' eller '%'.<br />
  95.      * Dessa jokertecken används bara i vissa delar av MySQL queryn, så som i
  96.      * LIKE t.ex. Det är därför inte alltid man vill escapa dessa tecken.<br />
  97.      * Vill man göra så så så låter man en tredje parameter följa med de
  98.      * nycklarna som key-value som man vill sätta escape till:<br />
  99.      * array('password' => true)<br />
  100.      * Man behöver inte sätta en fullständig karta utan bara berätta var man
  101.      * vill sätta escape tecknen. Alla nycklarna behöver därför inte följa med i
  102.      * denna parameter.
  103.      * <br />
  104.      * Användbara typer i fältet:<br />
  105.      * <b>[string , boolean]</b>
  106.      *
  107.      * @see self::composeSQL
  108.      * @see self::newQuery
  109.      */
  110.     public function __construct($query=null,$replaceMap=null,
  111.             $escapeWildcardsMap=null){
  112.  
  113.         if(!empty($query))
  114.             $this->newQuery($query,$replaceMap,$escapeWildcardsMap);
  115.     }
  116.  
  117.     /**
  118.      * Ställer själva frågan till MySQL och sparar svar.
  119.      *
  120.      * @param string $query Mall för hur vi vill att SQL frågan ska se ut. SQL
  121.      * frågan ska ha nycklar i sig med inledande kolon tecken ':'<br />
  122.      * <br />
  123.      * <b>Exempel:</b><br />
  124.      * UPDATE users<br />
  125.      * SET pass=:password:<br />
  126.      * WHERE user=:user:<br />
  127.      * <br />
  128.      * I ovanstående exempel har vi två nycklar som är: 'password' och 'user'.
  129.      * Dessa kommer vi att byta ut mot de värden som ska vara där med hjälp av
  130.      * parametern $replaceMap.
  131.      *
  132.      * @param array $replaceMap Karta för vad som ska ersätta vad.<br />
  133.      * <br />
  134.      * <b>Exemplet:</b><br />
  135.      * UPDATE users<br />
  136.      * SET pass=:password:<br />
  137.      * WHERE user=:user:<br />
  138.      * <br />
  139.      * ...gav oss nycklarna 'password' och 'user' som båda ska ersättas med
  140.      * data. Vi gör så via denna parameter genom följande exempel:<br />
  141.      * array('password' => 'hemligt',<br />
  142.      * 'user' => 'erik')<br />
  143.      * <br />
  144.      * Detta kommer ersätta nycklarna med befintligt värde.<br />
  145.      * <b>OBS!</b> heltal ska valideras för att bli behandlade som heltal i
  146.      * SQL frågan...<br />
  147.      * <br />
  148.      * Godtagbara typer i fältet:<br />
  149.      * <b>[string , string | int]</b>
  150.      *
  151.      * @param array $escapeWildcardsMap En valfri parameter som ska finnas med
  152.      * om man vill escapa jokertecken som: '_' eller '%'.<br />
  153.      * Dessa jokertecken används bara i vissa delar av MySQL queryn, så som i
  154.      * LIKE t.ex. Det är därför inte alltid man vill escapa dessa tecken.<br />
  155.      * Vill man göra så så så låter man en tredje parameter följa med de
  156.      * nycklarna som key-value som man vill sätta escape till:<br />
  157.      * array('password' => true)<br />
  158.      * Man behöver inte sätta en fullständig karta utan bara berätta var man
  159.      * vill sätta escape tecknen. Alla nycklarna behöver därför inte följa med i
  160.      * denna parameter.
  161.      * <br />
  162.      * Användbara typer i fältet:<br />
  163.      * <b>[string , boolean]</b>
  164.      *
  165.      * @return void
  166.      * @see self::composeSQL
  167.      */
  168.     public function newQuery($query,$replaceMap=null,$escapeWildcardsMap=null){
  169.  
  170.         $query = self::composeSQL($query,$replaceMap,$escapeWildcardsMap);
  171.  
  172.         $this->mysqlResource    = mysql_query($query);
  173.         $this->query            = $query;
  174.         $this->errorNr          = mysql_errno();
  175.         $this->errorMessage     = mysql_error();
  176.         $this->affectedRows     = mysql_affected_rows();
  177.         $this->generatedId      = mysql_insert_id();
  178.     }
  179.  
  180.     /**
  181.      * Ställer en enkel fråga till MySQL utan att spara svar.
  182.      *
  183.      * @param string $query Mall för hur vi vill att SQL frågan ska se ut. SQL
  184.      * frågan ska ha nycklar i sig med inledande kolon tecken ':'<br />
  185.      * <br />
  186.      * <b>Exempel:</b><br />
  187.      * UPDATE users<br />
  188.      * SET pass=:password:<br />
  189.      * WHERE user=:user:<br />
  190.      * <br />
  191.      * I ovanstående exempel har vi två nycklar som är: 'password' och 'user'.
  192.      * Dessa kommer vi att byta ut mot de värden som ska vara där med hjälp av
  193.      * parametern $replaceMap.
  194.      *
  195.      * @param array $replaceMap Karta för vad som ska ersätta vad.<br />
  196.      * <br />
  197.      * <b>Exemplet:</b><br />
  198.      * UPDATE users<br />
  199.      * SET pass=:password:<br />
  200.      * WHERE user=:user:<br />
  201.      * <br />
  202.      * ...gav oss nycklarna 'password' och 'user' som båda ska ersättas med
  203.      * data. Vi gör så via denna parameter genom följande exempel:<br />
  204.      * array('password' => 'hemligt',<br />
  205.      * 'user' => 'erik')<br />
  206.      * <br />
  207.      * Detta kommer ersätta nycklarna med befintligt värde.<br />
  208.      * <b>OBS!</b> heltal ska valideras för att bli behandlade som heltal i
  209.      * SQL frågan...<br />
  210.      * <br />
  211.      * Godtagbara typer i fältet:<br />
  212.      * <b>[string , string | int]</b>
  213.      *
  214.      * @param array $escapeWildcardsMap En valfri parameter som ska finnas med
  215.      * om man vill escapa jokertecken som: '_' eller '%'.<br />
  216.      * Dessa jokertecken används bara i vissa delar av MySQL queryn, så som i
  217.      * LIKE t.ex. Det är därför inte alltid man vill escapa dessa tecken.<br />
  218.      * Vill man göra så så så låter man en tredje parameter följa med de
  219.      * nycklarna som key-value som man vill sätta escape till:<br />
  220.      * array('password' => true)<br />
  221.      * Man behöver inte sätta en fullständig karta utan bara berätta var man
  222.      * vill sätta escape tecknen. Alla nycklarna behöver därför inte följa med i
  223.      * denna parameter.
  224.      * <br />
  225.      * Användbara typer i fältet:<br />
  226.      * <b>[string , boolean]</b>
  227.      *
  228.      * @return void
  229.      * @see self::composeSQL
  230.      */
  231.     public static function simpleQuery($query,$replaceMap=null,$escapeWildcardsMap=null){
  232.         // Sätter ihop frågan säkert
  233.         $query = self::composeSQL($query,$replaceMap,$escapeWildcardsMap);
  234.         // Ställer frågan
  235.         $mysqlResource = mysql_query($query);
  236.         // Frigör minnet
  237.         if(is_resource($mysqlResource))
  238.             mysql_free_result($mysqlResource);
  239.     }
  240.  
  241.     /**
  242.      * Funktionen används för att motverka SQL injections...
  243.      *
  244.      * @param string $query Mall för hur vi vill att SQL frågan ska se ut. SQL
  245.      * frågan ska ha nycklar i sig med inledande kolon tecken ':'<br />
  246.      * <br />
  247.      * <b>Exempel:</b><br />
  248.      * UPDATE users<br />
  249.      * SET pass=:password:<br />
  250.      * WHERE user=:user:<br />
  251.      * <br />
  252.      * I ovanstående exempel har vi två nycklar som är: 'password' och 'user'.
  253.      * Dessa kommer vi att byta ut mot de värden som ska vara där med hjälp av
  254.      * parametern $replaceMap.
  255.      *
  256.      * @param array $replaceMap Karta för vad som ska ersätta vad.<br />
  257.      * <br />
  258.      * <b>Exemplet:</b><br />
  259.      * UPDATE users<br />
  260.      * SET pass=:password:<br />
  261.      * WHERE user=:user:<br />
  262.      * <br />
  263.      * ...gav oss nycklarna 'password' och 'user' som båda ska ersättas med
  264.      * data. Vi gör så via denna parameter genom följande exempel:<br />
  265.      * array('password' => 'hemligt',<br />
  266.      * 'user' => 'erik')<br />
  267.      * <br />
  268.      * Detta kommer ersätta nycklarna med befintligt värde.<br />
  269.      * <b>OBS!</b> heltal ska valideras för att bli behandlade som heltal i
  270.      * SQL frågan...<br />
  271.      * <br />
  272.      * Godtagbara typer i fältet:<br />
  273.      * <b>[string , string | int]</b>
  274.      *
  275.      * @param array $escapeWildcardsMap En valfri parameter som ska finnas med
  276.      * om man vill escapa jokertecken som: '_' eller '%'.<br />
  277.      * Dessa jokertecken används bara i vissa delar av MySQL queryn, så som i
  278.      * LIKE t.ex. Det är därför inte alltid man vill escapa dessa tecken.<br />
  279.      * Vill man göra så så så låter man en tredje parameter följa med de
  280.      * nycklarna som key-value som man vill sätta escape till:<br />
  281.      * array('password' => true)<br />
  282.      * Man behöver inte sätta en fullständig karta utan bara berätta var man
  283.      * vill sätta escape tecknen. Alla nycklarna behöver därför inte följa med i
  284.      * denna parameter.
  285.      * <br />
  286.      * Användbara typer i fältet:<br />
  287.      * <b>[string , boolean]</b>
  288.      *
  289.      * @static
  290.      * @return string
  291.      */
  292.     private static function composeSQL($query,$replaceMap=array(),
  293.             $escapeWildcardsMap=null){
  294.  
  295.         $keys    = array();
  296.         $replace = array();
  297.  
  298.         if(count($replaceMap) > 0)
  299.             foreach($replaceMap as $key => $value){
  300.                 $keys[] = ':'.$key.':';
  301.                 switch(strtolower(gettype($value))){
  302.                     case 'string':
  303.                         // Motverkar dubbel escaping
  304.                         $value = self::antiMagicQuotes($value);
  305.  
  306.                         // Om användaren vill escapa jokertecken
  307.                         if(isset($escapeWildcardsMap[$key]))
  308.                             if(is_bool($escapeWildcardsMap[$key]))
  309.                                 if($escapeWildcardsMap[$key])
  310.                                     $value = self::escapeWildcards($value);
  311.  
  312.                         // Escapar stringen så att den är säker i databasen
  313.                         $replace[] = "'".mysql_real_escape_string($value)."'";
  314.                         break;
  315.                     case 'integer':
  316.                         $replace[] = (string)$value;
  317.                         break;
  318.                     case 'boolean':
  319.                         if($value)
  320.                             $replace[] = 'true';
  321.                         else
  322.                             $replace[] = 'false';
  323.                         break;
  324.                     case 'null':
  325.                             $replace[] = 'NULL';
  326.                         break;
  327.                     default :
  328.                         exit('ogiltligt värde till SQL fråga');
  329.                 }
  330.             }
  331.  
  332.         return str_replace($keys, $replace, $query);
  333.     }
  334.  
  335.     /**
  336.      * Om magic_quotes_sybase eller magic_quotes_gpc är påslagan av någon dum
  337.      * anledning så strippas parametern från de backslashes som dessa har
  338.      * genererat...
  339.      * @param string $string Den sträng som ska användas i databasfråga
  340.      * @return string
  341.      */
  342.     private static function antiMagicQuotes($string) {
  343.         if(get_magic_quotes_gpc())
  344.             $string = stripslashes($string);
  345.         return $string;
  346.     }
  347.  
  348.     /**
  349.      * Escape'ar de jokertecken som är relevanta i vissa frågor i MySQL.
  350.      * @param string $string Den sträng som ska användas i databasfråga
  351.      * @return string
  352.      */
  353.     private static function escapeWildcards($string){
  354.         return str_replace(array('_','%'),array('\\_','\\%'),$string);
  355.     }
  356.  
  357.     /**
  358.      * Används för att hämta rad för rad från MySQL. Returnerar true om det
  359.      * finns fler rader att hämta och false ifall det inte finns det.
  360.      * @return boolean
  361.      */
  362.     public function fetchArray(){
  363.         return ($this->result = @mysql_fetch_array($this->mysqlResource));
  364.     }
  365.  
  366.     /**
  367.      * Används för att hämta ett fält från resultatet. <br />
  368.      * OBS! Kalla på funktionen 'fetchArray' först.
  369.      * @param String $key Kolumnnamnet som eftersöks.
  370.      * @return string
  371.      */
  372.     public function field($key){
  373.         return $this->result[$key];
  374.     }
  375.  
  376.     /**
  377.      * Returnerar den ställda frågan
  378.      * @return string
  379.      */
  380.     public function getQuery(){
  381.         return $this->query;
  382.     }
  383.  
  384.     /**
  385.      * Returnerar resultatet från den ställda frågan
  386.      * @return array
  387.      */
  388.     public function getResult(){
  389.         return $this->result;
  390.     }
  391.  
  392.     /**
  393.      * Returnerar eventuellt genererat error nummer
  394.      * @return int
  395.      */
  396.     public function getErrorNr(){
  397.         return $this->errorNr;
  398.     }
  399.  
  400.     /**
  401.      * Returnerar error medelandet
  402.      * @return string
  403.      */
  404.     public function getErrorMessage(){
  405.         return $this->errorMessage;
  406.     }
  407.  
  408.     /**
  409.      * Returnerar hur många rader som var påvärkade
  410.      * @return int
  411.      */
  412.     public function getAffectedRows(){
  413.         return $this->affectedRows;
  414.     }
  415.  
  416.     /**
  417.      * Frigör minnet från resultatet
  418.      * @return void
  419.      */
  420.     public function freeResult(){
  421.         mysql_free_result($this->mysqlResource);
  422.     }
  423.  
  424.     /**
  425.      * Returnerar en väl beskriven förklaring av
  426.      * vad som har gott fel, om något har gott fel
  427.      * @return string
  428.      */
  429.     public function errorInfo(){
  430.         $errorInfo;
  431.         if(!empty($this->errorMessage) || !empty($this->errorNr)){
  432.             $errorInfo = (nl2br('<pre>
  433.            MySQL query = '.$this->query.'
  434.  
  435.            MySQL error nr = '.$this->errorNr.'
  436.  
  437.            MySQL error medelande:
  438.            '.$this->errorMessage.'
  439.            </pre>'));
  440.         }
  441.         else{
  442.             $errorInfo = (nl2br('Inget fel medelande registrerat
  443.            Påvärkade rader = '.$this->affectedRows));
  444.         }
  445.  
  446.         return $errorInfo;
  447.     }
  448.  
  449.     /**
  450.      * Returnerar false om det inte har uppstott något fel i MySQL frågan <br />
  451.      * Returnerar annars true om fel uppstod
  452.      * @return boolean
  453.      */
  454.     public function error(){
  455.         return $this->errorNr != 0;
  456.     }
  457.  
  458.     /**
  459.      * Returnerar det id nummer som genererades av MySQL AUTO_INCREMENT då
  460.      * frågan ställdes, vanligtvis INSERT, till databasen.<br />
  461.      * Om ingen kolumn har AUTO_INCREMENT eller om frågan inte genererade något
  462.      * id så returneras 0...
  463.      * @return int
  464.      * @see mysql_insert_id()
  465.      */
  466.     public function getGeneratedId(){
  467.         return $this->generatedId;
  468.     }
  469.  
  470.     /**
  471.      * Tömmer eventuell resurce
  472.      */
  473.     public function  __destruct() {
  474.         if(is_resource($this->mysqlResource))
  475.             $this->freeResult();
  476.     }
  477. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement