2016-05-19 11 views
-1

Ich benutze eine Datenbank-Klasse aus einem Tutorial auf codecourse.com (Ich beginne gerade die Migration von prozeduralen zu PDO) und ich bin langsam erweitern, um meine Bedürfnisse zu erfüllen. Die einzige Sache, die ich nicht verwalten kann, ist, die lastInsertId() zurückzugeben, um global verwendet zu werden.returning lastInsertId() aus Datenbank Klasse

Mit dem Register Beispiel aus diesem Tutorial

$user = new User(); 
$salt = Hash::salt(32); 
try { 
$user->create(array(
    'username' => Input::get('username'), 
    'password' => Hash::make(Input::get('password'), $salt), 
    'salt' => $salt, 
    'firstname' => Input::get('first_name'), 
    'lastname' => Input::get('last_name'), 
    'joined' => date('Y-m-d H:i:s'), 
    'group' => 1 
)); 
} catch(Exception $e) { 
    die($e->getMessage()); 
} 

Es ist an dieser Stelle, dass ich die lastInsertId() erhalten möge - die eine der nur für registrierte Benutzer. Ich bin nicht sicher, ob es über die Insert-Funktion

require_once 'core/init.php'; 

class DB { 
private static $_instance = null; 
private $_pdo, 
     $_query, 
     $_error = false, 
     $_results, 
     $_count = 0; 

private function __construct() { 
    try { 
     $this->_pdo = new PDO('mysql:host=' . Config::get('mysql/host') . ';dbname=' . Config::get('mysql/db'), Config::get('mysql/username'), Config::get('mysql/password')); 

    } catch(PDOException $e) { 
     die($e->getMessage()); 
    } 
} 
public static function getInstance() { 
    if(!isset(self::$_instance)) { 
     self::$_instance = new DB(); 
    } 
    return self::$_instance; 
} 


public function query ($sql, $params = array()) { 
    $this->error = false; 
    if ($this->_query = $this->_pdo->prepare($sql)) { 
     $x = 1; 
     if(count($params)) { 
      foreach($params as $param) { 
       $this->_query->bindValue($x, $param); 
       $x++; 
      } 
     } 

     if($this->_query->execute()) { 
      $this->_results = $this->_query->fetchAll(PDO::FETCH_OBJ); 
      $this->_count = $this->_query->rowCount(); 
     } else { 
      $this->_error = true; 
     } 
    } 

    return $this; 
} 

public function action ($action, $table, $where = array()) { 
    if (count($where) === 3) { 
     $operators = array('=', '>', '<', '>=', '<='); 

     $field = $where[0]; 
     $operator = $where[1]; 
     $value = $where[2]; 

     if (in_array($operator, $operators)) { 
      $sql = "{$action} FROM {$table} WHERE {$field} {$operator} ?"; 
      if(!$this->query($sql, array($value))->error()) { 
       return $this; 
      } 
     } 
    } 
    return false; 
} 

public function get ($table, $where) { 
    return $this->action('SELECT *', $table, $where); 
} 

public function delete ($table, $where) { 
    return $this->action('DELETE', $table, $where); 

} 

public function insert ($table, $fields = array()) { 

     $keys = array_keys($fields); 
     $values = ''; 
     $x = 1; 

     foreach($fields as $field) { 
      $values .= '?'; 
      if ($x < count($fields)) { 
       $values .= ', '; 
      } 

      $x++; 
     } 


     $sql = "INSERT INTO {$table} (`" . implode('`,`', $keys) . "`) VALUES ({$values})"; 

     if (!$this->query($sql,$fields)->error()) { 
      return true; 
     } 

     echo $sql; 
    } 
    return false; 

} 

public function update ($table, $id, $fields = array()) { 

     $set = ''; 
     $x = 1; 

     foreach ($fields as $name => $value) { 
      $set .= "{$name} = ?"; 
      if ($x < count($fields)) { 
       $set .= ', '; 
      } 

      $x++; 
     } 

     $sql = "UPDATE {$table} SET {$set} WHERE id = {$id}"; 

     if (!$this->query($sql,$fields)->error()) { 
      return true; 
     } 

    } 
    return false; 

} 


public function first() { 
    return $this->results()[0]; 
} 

public function results() { 
    return $this->_results; 
} 

public function count() { 
    return $this->_count; 
} 

public function error() { 
    return $this->_error; 
} 

} 

Oder die Benutzerklasse über die Funktion erstellen aus der Datenbank-Klasse kommt

class User { 
private $_db, 
     $_data, 
     $_sessionName, 
     $_cookieName, 
     $_isLoggedIn; 
public function __construct($user = null) { 
    $this->_db = DB::getInstance(); 
    $this->_sessionName = Config::get('session/session_name'); 
    $this->_cookieName = Config::get('remember/cookie_name'); 
    if (!$user) { 
     if (Session::exists($this->_sessionName)) { 
      $user = Session::get($this->_sessionName); 
      if ($this->find($user)) { 
       $this->_isLoggedIn = true; 
      } else { 
       //Logged out 
      } 
     } 
    } else { 
     $this->find($user); 
    } 
} 
public function update($fields=array(), $id = null) { 
    if (!$id && $this->isLoggedIn()) { 
     $id = $this->data()->id; 
    } 
    if (!$this->_db->update('users', $id, $fields)) { 
     throw new Exception('There was a problem updating the account!'); 
    } 
} 
public function create($fields) { 
    if (!$this->_db->insert('users', $fields)) { 
     throw new Exception('There was a problem creating an account!'); 
    } 
} 
public function find($user=null) { 
    if ($user) { 
     $field = (is_numeric($user)) ? 'id' : 'username'; 
     $data = $this->_db->get('users', array($field, '=', $user)); 
     if ($data->count()) { 
      $this->_data = $data->first(); 
      return true; 
     } 
    } 
    return false; 
} 
public function login($username=null, $password=null, $remember = false) { 
    if(!$username && !$password && $this->exists()) { 
     Session::put($this->_sessionName, $this->data()->id); 
    } else { 
     $user = $this->find($username); 
     if ($this->data()->password === Hash::make($password, $this->data()->salt)) { 
      Session::put($this->_sessionName, $this->data()->id); 
      if ($remember) { 
       $hash = Hash::unique(); 
       $hashCheck = $this->_db->get('users_session', array('user_id', '=', $this->data()->id)); 
       if (!$hashCheck->count()) { 

        $this->_db->insert('users_session', array(
         'user_id' => $this->data()->id, 
         'hash' => $hash 
        )); 
       } else { 
        $hash = $hashCheck->first()->hash; 
       } 
       Cookie::put($this->_cookieName, $hash, Config::get('remember/cookie_expiry')); 
      } 
      return true; 
     } 
     return false; 
     } 
} 
public function hasPermission ($key) { 
    $group = $this->_db->get('groups', array('id', '=', $this->data()->group)); 
    if($group->count()) { 
     $permissions = json_decode($group->first()->permissions, true); 
     if ($permissions[$key] == true) { 
      return true; 
     } 
    } 
    return false; 
} 
public function exists() { 
    return (!empty($this->_data)) ? true : false; 
} 
public function logout() { 
    Session::delete($this->_sessionName); 
} 
public function data() { 
    return $this->_data; 
} 
public function isLoggedIn() { 
    return $this->_isLoggedIn; 
} 
} 

ich in beide versucht haben, aber wenn ich versuche, das Echo lastInsertId() zurück, nichts wird zurückgegeben. Jeder Rat wäre sehr willkommen. Wenn das Problem außerhalb dieser Bereiche liegt, habe ich das gesamte Skript auf https://github.com/MargateSteve/login hochgeladen.

Vielen Dank im Voraus

Steve

+0

Wo versuchen Sie, das PDO :: lastInsertId() aus der DB-Klasse zu ziehen? –

+0

Ich habe es sowohl in der DB-Klasse als auch in der User-Klasse versucht. Der letzte Versuch wurde in insert() in der DB durchgeführt, indem eine $ ins_id-Variable erstellt und global gemacht wurde. 'öffentliche Funktion einfügen ($ Tabelle, $ Felder = Array()) { global $ ins_id; $ keys = array_keys ($ fields); $ values ​​= ''; $ x = 1; foreach ($ fields als $ field) { // etc } $ sql = "xxx"; if (! $ This-> query ($ sql, $ fields) -> error()) { return true; } $ ins_id = $ this-> db-> lastInsertId(); Rückgabe false; } ' –

+0

Ich denke, Sie müssen es auf die Abfrage-Funktion direkt nach $ this -> _ query-> ausführen(), dann rufen Sie die lastInsertId() PDO-Funktion, speichern Sie es in eine Variable auf Ihrer DB-Instanz und dann können Sie Greife darauf in der User-Klasse mit $ this -> _ db-> lastInsertId oder wie immer du es nennst –

Antwort

-1

eine öffentliche Variable in Ihre DB Klasse hinzufügen, die die zuletzt eingefügten Datensatz-ID halten werden:

class DB { 
    public $lastInsertId = null; 

Im gleichen DB Klasse modifizieren, um die Abfragemethode, wo die tatsächliche Einfügung geschieht, so dass Sie die ID von PDO greifen können:

public function query ($sql, $params = array()) { 
    $this->error = false; 
    if ($this->_query = $this->_pdo->prepare($sql)) { 
     $x = 1; 
     if(count($params)) { 
      foreach($params as $param) { 
       $this->_query->bindValue($x, $param); 
       $x++; 
      } 
     } 

     if($this->_query->execute()) { 
      $this->lastInsertId = $this->_pdo->lastInsertId(); 
      $this->_results = $this->_query->fetchAll(PDO::FETCH_OBJ); 
      $this->_count = $this->_query->rowCount(); 
     } else { 
      $this->_error = true; 
     } 
    } 

    return $this; 
} 

Auf dem obigen Code das ist die wichtige Linie:

$this->lastInsertId = $this->_pdo->lastInsertId(); 

Sie den Wert von PDO::lastInsertId() auf Ihre lastInsertId Instanz Variablen zugewiesen wird, auf diese Weise Sie es aus, wo immer Sie instanziieren ein DB Objekt zugreifen können.

Ändern Sie jetzt die Benutzerklasse, um eine Variable namens id auch zu halten, nennen Sie es nicht lastInsertId, weil es verwirrend ist; in diesem Zusammenhang haben Sie eine einzelne Instanz eines Benutzers, die einen einzelnen Benutzer und somit id einfach bezieht sich auf diese Instanz Benutzer-ID darstellt:

class User { 

    public $id = null; 

Modify in derselben User Klasse die create Methode als auch greifen die lastInsertId Wert von Ihrer db Objektinstanz:

public function create($fields) { 
    if (!$this->_db->insert('users', $fields)) { 
     throw new Exception('There was a problem creating an account!'); 
    } 

    $this->id = $this->_db->lastInsertId; 

} 

Dann können Sie die Benutzer-ID in Ihrer register.php Datei zugreifen einfach den Benutzer Instanzvariable zB accesing $user->id:

try { 
    $user->create(array(
     'username' => Input::get('username'), 
     'password' => Hash::make(Input::get('password'), $salt), 
     'salt' => $salt, 
     'firstname' => Input::get('first_name'), 
     'lastname' => Input::get('last_name'), 
     'joined' => date('Y-m-d H:i:s'), 
     'group' => 1 
    )); 

    Session::flash('home', "You have registered with user ID $user->id"); 
    Redirect::to('index.php'); 
} catch(Exception $e) { 
    die($e->getMessage()); 
} 
+0

Nailed it! Funktioniert perfekt und danke für die Erklärung, wie es funktioniert. Einer meiner vorherigen Versuche war tatsächlich in diesen Zeilen, aber ich habe $ lastInsertId nie öffentlich gemacht. –

+0

@SteveBall froh, dass es funktioniert hat! –

0

Der Einsatz() -Methode einer Datenbank-Klasse sollte Insert-ID zurück.Hier ist ein relevanter Teil dafür:

public function insert ($table, $fields = array()) { 
    $this->query($sql,$fields); 
    return $this->_db->lastInsertId; 
} 

während create() Methode einer Benutzerklasse sollte eine Benutzerinstanz erstellen.

public function create($fields) { 
    $id = $this->_db->insert('users', $fields); 
    $this->find($id); 
} 

Beachten Sie, dass die Methode insert() vulnerable to SQL injection ist.

Und jetzt können Sie Ihre neu erstellten Benutzer verwenden alles in Ordnung

$user = new User(); 
$user->create(array(
    'username' => Input::get('username'), 
    'password' => Hash::make(Input::get('password')), 
    'firstname' => Input::get('first_name'), 
    'lastname' => Input::get('last_name'), 
    'joined' => date('Y-m-d H:i:s'), 
    'group' => 1 
)); 
echo $user->data['id']; 

Ich hoffe, Sie sind nicht auf der Suche nach dem Code, aber für das Verständnis zu kopieren und einzufügen. Und ich hoffe, Sie verstehen die obige Logik.

+0

Leider gibt es immer noch nichts zurück. Sie haben jedoch Recht, dass es hier mehr um das Verstehen als um das Schreiben geht. Dinge wie die SQL-Injektion sind meine nächsten Schritte, sobald ich den Dreh raus habe, was ich vom Unterricht bekommen will. –