Simple PDO wrapper
Problem #1, verbosityProblem #2, availability
The code
Examples
Comments
Problem #1, verbosity
The main flaw of either PDO's and mysqli's design is that both extensions were primarily aimed to the least used scenario - single prepare/multiple execute. Although this scenario has extremely limited use, it spoils most frequent scenario - just running some SQL query with parameters once. As a result, to get data from one single query, one invariably have to write three separate lines:
$stmt = $pdo->prepare($sql);$stmt->execute($params);$data = $stmt->fetch();
Besides that, PDO authors made things even more shitty, by making execute() return.. boolean! Boolean, Carl! If only it was returning statement itself instead, we were able to use neat method chaining at least:
$data = $pdo->prepare($sql)->execute($params)->fetch();
But alas, it's impossible at the moment. Anyway, it's too verbose already, as we don't need neither prepare nor execute in the most cases. All we need is to execute that bloody query and get the result.
So, let's make a function called run(), that will accept query and optional parameters, doing prepare and execute internally, and returning old good PDO statement, from which we can retrieve data in any form we want.
Problem #2, availability
The most disappointing surprise for the php users, who are accustomed with old mysql_query, is PDO's general unavailability. Let's make a singleton out of DB class, and let's make it to pretend being PDO in any way, save for an addition of our run() function.
I know that singleton is a taboo in your internets - so, if you don't like it, just add whatever getInstance() method or your favorite IoC call.
The code
<?phpdefine('DB_HOST', 'localhost');define('DB_NAME', 'test');define('DB_USER', 'root');define('DB_PASS', '');define('DB_CHAR', 'utf8');class DB{ protected static $instance = null; public function __construct() {} public function __clone() {} public static function instance() { if (self::$instance === null) { $opt = array( PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, PDO::ATTR_EMULATE_PREPARES => TRUE, ); $dsn = 'mysql:host='.DB_HOST.';dbname='.DB_NAME.';charset='.DB_CHAR; self::$instance = new PDO($dsn, DB_USER, DB_PASS, $opt); } return self::$instance; } public static function __callStatic($method, $args) { return call_user_func_array(array(self::instance(), $method), $args); } public static function run($sql, $args = []) { $stmt = self::instance()->prepare($sql); $stmt->execute($args); return $stmt; }}
Examples
Can be copy pasted in your code and run.
# Creating test tableDB::query("CREATE temporary TABLE pdowrapper (id int auto_increment primary key, name varchar(255))");# single prepare/multiple execute$stmt = DB::prepare("INSERT INTO pdowrapper VALUES (NULL, ?)");foreach (['Sam','Bob','Joe'] as $name){ $stmt->execute([$name]);}var_dump(DB::lastInsertId());//string(1) "3"# A loop$stmt = DB::run("SELECT * FROM pdowrapper");while ($row = $stmt->fetch(PDO::FETCH_LAZY)){ echo $row['name'],","; echo $row->name,","; echo $row[1], PHP_EOL;}/*Sam,Sam,SamBob,Bob,BobJoe,Joe,Joe*/# Getting single row$id = 1;$row = DB::run("SELECT * FROM pdowrapper WHERE id=?", [$id])->fetch();var_export($row);/*array ( 'id' => '1', 'name' => 'Sam',)*/# Getting single column$name = DB::run("SELECT name FROM pdowrapper WHERE id=?", [$id])->fetchColumn();var_dump($name);//string(3) "Sam"# Getting all the rows in array$all = DB::run("SELECT name, id FROM pdowrapper")->fetchAll(PDO::FETCH_KEY_PAIR);var_export($all);/*array ( 'Sam' => '1', 'Bob' => '2', 'Joe' => '3',)*/# Update$new = 'Sue';$stmt = DB::run("UPDATE pdowrapper SET name=? WHERE id=?", [$new, $id]);var_dump($stmt->rowCount());//int(1)
Add a comment
Please refrain from sending spam or advertising of any sort.
Messages with hyperlinks will be pending for moderator's review.
Markdown is now supported:
>
before and an empty line after for a quote