Ankündigung

Einklappen
Keine Ankündigung bisher.

PDO, prepared update und Rechnen?!?

Einklappen

Neue Werbung 2019

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • PDO, prepared update und Rechnen?!?

    Hallo,

    ich arbeite gerade an meiner PDO-Datenbank-Klasse und erstelle mir da soweit meine Funktionen wie ich sie brauche.

    Gerade hänge ich etwas beim update fest denn ik weiß nicht wie es dort mit dem Rechnen gehen soll.

    PHP-Code:
    $sample $tdb->update("accounts""email = 'insert4@user.de'", [
            
    'facebook' => 'lmaa',
            
    'auth_extended' => false,
            
    'wrong_logins[*]' => 3
    ]); 

    Letzter Querry schaut dann so aus:
    PHP-Code:
    Array
    (
        [
    string] => UPDATE accounts SET facebook = :facebookauth_extended 0wrong_logins = :wrong_logins WHERE email 'insert4@user.de'
        
    [values] => Array
            (
                [:
    facebook] => facebook 'lmaa'
                
    [:wrong_logins] => wrong_logins 3
            
    )


    Hatte da gehofft das es dann in der Datenbank vllt. zusammengeführt bzw. die Platzhalter ersetzt werden, früher sah das ganze ja zb dann so aus:

    "SET coins = coins - 3" oder "SET coins = coins * 2"

    Aber mit prepared bekomme ich das nciht hin, ich hoffe Jemand gibt mir da etwas Hilfe wie ich das mit Prepared hin bekomme.


    MFG: Pay

  • #2
    Vieleicht mal mehr zu der Datenbank-klasse die du nutzt?
    [QUOTE=nikosch]Macht doch alle was Ihr wollt mit Eurem Billigscheiß. Von mir aus sollen alle Eure Server abrauchen.[/QUOTE]

    Kommentar


    • #3
      Naja ne eigene =) Ganz unten ist update...

      PHP-Code:
      <?php
      class testCore
      {
          protected 
      $database_type 'mysql';

          
      // Connection
          
      protected $server 'localhost';
          protected 
      $username 'username';
          protected 
      $password 'password';
          protected 
      $database_name '';

          
      // For SQLite
          
      protected $database_file '';

          
      // Optional
          
      protected $port 3306;
          protected 
      $charset 'utf8';

          protected 
      $option = array();

          
      // Save last query with values-array on prepared
          
      protected $lastQuery;

          public function 
      __construct($options null)
          {
              try {
                  
      $commands = array();

                  if (
      is_string($options) && !empty($options))
                  {
                      if (
      strtolower($this->database_type) == 'sqlite')
                      {
                          
      $this->database_file $options;
                      }
                      else
                      {
                          
      $this->database_name $options;
                      }
                  }
                  elseif (
      is_array($options))
                  {
                      foreach (
      $options as $option => $value)
                      {
                          
      $this->$option $value;
                      }
                  }

                  if (
                      isset(
      $this->port) &&
                      
      is_int($this->port 1)
                  )
                  {
                      
      $port $this->port;
                  }

                  
      $set_charset "SET NAMES '".$this->charset."'";
                  
      $type strtolower($this->database_type);
                  
      $is_port = isset($port);

                  switch (
      $type)
                  {
                      case 
      'mariadb':
                          
      $type 'mysql';

                      case 
      'mysql':
                          
      // Make MySQL using standard quoted identifier
                          
      $commands[] = 'SET SQL_MODE=ANSI_QUOTES';

                      case 
      'pgsql':
                          
      $dsn $type.':host='.$this->server.($is_port ';port='.$port '').';dbname='.$this->database_name;
                          
      $commands[] = $set_charset;
                          break;

                      case 
      'sybase':
                          
      $dsn 'dblib:host='.$this->server.($is_port ':'.$port '').';dbname='.$this->database_name;
                          
      $commands[] = $set_charset;
                          break;

                      case 
      'oracle':
                          
      $dsn 'oci:host='.$this->server.($is_port ';port='.$port '').';dbname='.$this->database_name.';charset='.$this->charset;
                          break;

                      case 
      'mssql':
                          
      $dsn strpos(PHP_OS'WIN') !== false ?
                              
      'sqlsrv:server='.$this->server.($is_port ','.$port '').';database='.$this->database_name :
                              
      'dblib:host='.$this->server.($is_port ':'.$port '').';dbname='.$this->database_name;

                          
      // Keep MSSQL QUOTED_IDENTIFIER is ON for standard quoting
                          
      $commands[] = 'SET QUOTED_IDENTIFIER ON';
                          
      $commands[] = $set_charset;
                          break;

                      case 
      'sqlite':
                          
      $dsn $type.':'.$this->database_file;
                          
      $this->username null;
                          
      $this->password null;
                          break;
                  }

                  
      $this->pdo = new PDO(
                      
      $dsn
                      
      $this->username,
                      
      $this->password,
                      
      $this->option
                  
      );
                  

                  
      $this->pdo->setAttribute(PDO::ATTR_ERRMODEPDO::ERRMODE_EXCEPTION);

                  foreach (
      $commands as $value)
                  {
                      
      $this->pdo->exec($value);    
                  }
              }
              catch (
      PDOException $e) {
                  throw new 
      Exception($e->getMessage());
              }
          }

          public function 
      query($query$prep false)
          {
              
      $this->lastQuery['string'] = $query;

              return (
      $prep) ? $this->pdo->prepare($query) : $this->pdo->query($query);
          }

          public function 
      exec($data$stmt NULL)
          {
              
      $this->lastQuery['values'] = (!empty($stmt)) ? $data '';

              return (!empty(
      $stmt)) ? $stmt->execute$data ) : $this->pdo->exec($data);
          }

          public function 
      quote($string)
          {
              return 
      $this->pdo->quote($string);
          }

          protected function 
      column_quote($string)
          {
              return 
      '"'.str_replace('.''"."'$string).'"';
          }

          public function 
      lastQuery()
          {
              return 
      $this->lastQuery;
          }
          
          
      /**
           * A select and get function
           * 
           * $db->select( $query [string], $values [array], $fetchAll [bool] ) - with prepared
           * $db->select( $query [string], $fetchAll [bool] ) - without prepared
           * 
           * $fetchAll is default enabled and will auto disabled by find "LIMIT 1" on query!
           * Set an "<pf>" before a table name for include automatically an database präfix (... FROM <pf>accounts WHERE ...)
           */
          
      public function select()
          {
              
      $datas func_get_args();
              
      $query str_replace('<pf>'DBParray_shift($datas)); // remove the query from args
              
              
      if( !empty($datas) AND is_array($datas[0]) ) // check is the next arg an Array (values) or bool for fetch methode
              
      {
                  
      $stmt $this->query$querytrue );
                  
      $this->execarray_shift($datas), $stmt ); // remove the values array from args
              
      }
              else
              {
                  
      $stmt $this->query$queryfalse );
              }
              
              
      // set fetch methode = fetch OR fetchAll - (fetchAll is default if set not an false on args)
              
      $fetching = ( strpos($query'LIMIT 1') OR ( !empty($datas) AND $datas[0] === false )) ? 'fetch' 'fetchAll';
              
              
      // to determine whether FETCH_ASSOC or FETCH_COLUMN
              
      $splitt explode('FROM'$query);
              
      $select explode(','$splitt[0]);
              
              return ( 
      count($select) > OR strpos($splitt[0], '*') ) ? $stmt->{$fetching}(PDO::FETCH_ASSOC) : $stmt->{$fetching}(PDO::FETCH_COLUMN);
          }
          
          
      /**
           * INSERT into Database - only prepared but automatically
           * 
           * $db->insert( $table [string], $insert_action_one [array], $insert_action_two [array] etc )
           * 
           * @return numeric|array <lastid, array with last ids>
           */
          
      public function insert()
          {
              
      $datas func_get_args();
              
      $table DBP.array_shift($datas);
              
      $stmtCheck = [];
              
      $stmtInis = [];
              
              
              foreach (
      $datas as $data)
              {
                  
      // The statemant
                  
      $stmtID implode(","array_keys($data));
                  if( !
      in_array($stmtID$stmtCheck) )
                  {
                      
      $stmt $this->query("INSERT INTO ".$table." (".implode(", "array_keys($data)).") VALUES (:".implode(", :"array_keys($data)).")"true);
                      
      $stmtCheck[] = $stmtID// save the new statemant
                      
      $stmtInis[$stmtID] = $stmt;
                  }
                  else
                  {
                      
      $stmt $stmtInis[$stmtID];
                  }
                  
                  
      // Create array with prepared-keys
                  
      $data array_combinearray_map(function($k){ return ':'.$k; }, array_keys($data)), $data );
                  
                  
      // execute
                  
      $this->exec$data$stmt );
                  
      $lastId[] = $this->pdo->lastInsertId();
              }
              
              
      // return
              
      return count($lastId) > $lastId $lastId[0];
          }
          
          public function 
      update()
          {
              
      $datas func_get_args();
              
      $table DBP.array_shift($datas);
              
      $where array_shift($datas);
              
              foreach (
      $datas[0] as $key => $value)
              {
                  
      preg_match('/([\w]+)(\[(\+|\-|\*|\/)\])?/i'$key$match);
                  
                  if( isset(
      $match[3]) )
                  {
                      if( 
      is_numeric($value) )
                      {
      //                     $fields[] = $this->column_quote($match[1]).' = :'.$match[1];
                          
      $fields[] = $match[1].' = :'.$match[1];
                          
      $prep[":".$match[1]] = $match[1].' '.$match[3].' '.$value;
                      }
                  }
                  else
                  {
                      
      $column $key;
                      switch (
      gettype($value))
                      {
                          case 
      'NULL':
                              
      $fields[] = $column.' = NULL';
                              break;

                          case 
      'array':
                              
      preg_match("/\(JSON\)\s*([\w]+)/i"$key$column_match);

                              if (isset(
      $column_match[0]))
                              {
                                  
      $fields[] = $this->column_quote($column_match[1]).' = '.$this->quote(json_encode($value));
                              }
                              else
                              {
                                  
      $fields[] = $column.' = '.$this->quote(serialize($value));
                              }
                              break;

                          case 
      'boolean':
      //                         $fields[] = $this->column_quote($column).' = '.($value ? '1' : '0');
                              
      $fields[] = $column.' = '.($value '1' '0');
                              break;

                          case 
      'integer':
                          case 
      'double':
                          case 
      'string':
      //                         $fields[] = $this->column_quote($column).' = :'.$column;
                              
      $fields[] = $column.' = :'.$column;
                              
      $prep[":".$column] = $column.' = '.$this->quote($value);
                              break;
                      }
                  }
              }
      //         echo "UPDATE ".$table." SET ".implode(', ', $fields)." WHERE ".$where;
              // The statemant
              
      $stmt $this->query("UPDATE ".$table." SET ".implode(', '$fields)." WHERE ".$wheretrue);
              
      // execute
              
      return $this->exec$prep$stmt );
          }
      }

      Kommentar


      • #4
        Das was du da tust ist worst practice und ( die Sicherheit von ) prepared statements hast du irgendwo missverstanden.
        [URL="https://gitter.im/php-de/chat?utm_source=share-link&utm_medium=link&utm_campaign=share-link"]PHP.de Gitter.im Chat[/URL] - [URL="https://raindrop.io/user/32178"]Meine öffentlichen Bookmarks[/URL] ← Ich habe dir geholfen ? [B][URL="https://www.amazon.de/gp/wishlist/348FHGUZWTNL0"]Beschenk mich[/URL][/B].

        Kommentar


        • #5
          Naja davon mal ab das es weder meine Frage betrifft noch beim Problem weiterhilft, dann hättest du es auch direkt genauer erläutern können was daran falsch ist?!

          Denn für mich macht des kein Unterschied bzw. ich habe mir die Klasse so gebaut das sie das ganze händelt und ich weniger hardcoden muss bzw. übersichtlicher und so.

          Da ich ja noch nicht all zu weit bin kann ich atm z.B. folgende Abfragen durchführen.

          PHP-Code:
          /** select prepared */
          $query "SELECT email, pass, banned, reason FROM <pf>accounts WHERE email = :email ";
          $vals = [':email' => "paykoman@hotmail.com"];
          $sample $tdb->select($query$vals);

          /** select default */
          $query "SELECT email, pass, banned, reason FROM <pf>accounts WHERE email = 'paykoman@hotmail.com' ";
          $sample $tdb->select($query);

          /** insert (only prepared) */
          $sample $tdb->insert('accounts', [
                  
          'email' => 'insert4@user.de',
                  
          'pass' => 'testpw'
          ],[
                  
          'email' => 'insert5@user.de',
                  
          'pass' => 'testpw',
                  
          'banned' => '1',
                  
          'reason' => 'test'
          ],[
                  
          'email' => 'insert6@user.de',
                  
          'pass' => 'testpw'
          ]);

          /** update */
          $sample $tdb->update("accounts""email = 'insert4@user.de'", [
                  
          'facebook' => 'lmaa',
                  
          'auth_extended' => false,
                  
          'wrong_logins[*]' => 3
          ]); 

          Das ich da kein Object habe, war ja absichtlich so gemacht, das bleibt innerhalb der db-Klasse werde es mit Sicherheit eh nicht benötigen.

          Und ob ich es jetzt so wie oben machen oder so:
          PHP-Code:
          $sth $dbh->prepare($sql, array(PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY));
          $sth->execute(array(':calories' => 150':colour' => 'red'));
          $red $sth->fetchAll();
          $sth->execute(array(':calories' => 175':colour' => 'yellow'));
          $yellow $sth->fetchAll(); 
          Da gefällt mir meine Variante:
          PHP-Code:
          $query "SELECT email, pass, banned, reason FROM <pf>accounts WHERE email = :email ";
          $vals = [':email' => "paykoman@hotmail.com"];
          $user_one $tdb->select($query$vals);

          $vals = [':email' => "wer_anders@hotmail.com"];
          $user_two$tdb->select($query$vals); 
          Wo der query (statmant) und die Values getrennt sind besser... Vom Sicherheitsaspekt wüsste ich jetzt nicht was da einen Unterschied macht und wie man bei meinem insert sehen kann ist es auch bei mir möglich den Vorteil von Prepare zu nutzten in dem man nicht immer das statemant neu senden muss sondern das erst gesendete genutzt werden kann und einfach die values getauscht werden (Dies meinte ich auch das meine DB-Klasse es eben händeln soll)


          :: BACK TO TOPIC ::
          Ich glaube habe das etwas verkehrt gesehen, bei Zahlen würde prepared ja nicht unbedingt Sinn machen da eine Prüfung mit PHP gemacht werden kann (is_numeric oder so damit nichts anderes ins Zahlen Feld landen kann).
          So denke ich kann man hier dann einfach eine Kombination aus beidem machen oder?
          Oder kann man da doch wieder injectionen über ne Zahl reinschmuggeln wenn die Zahl aus nem input-feld kommt, ich denke wenn ich auf is_numeric() prüfe sollte da ne injection im feld rein geschmuggelt worden sein sollte die Funktion nen false geben oder nicht?


          Code:
          UPDATE accounts SET facebook = :facebook, auth_extended = :auth_extended, wrong_logins = `wrong_logins`+ 1 WHERE email = 'insert4@user.de'
          Weil mit preperad ists ja wohl nicht möglich zu rechnen, hmm?

          Kommentar

          Lädt...
          X