感觉比直接弄SQL语句高级,但还不到ORM的封装。
一步一步进化。
app.json
{ "db": { "user": "root", "password": "xxxx", "host": "10.2.3.4", "port": "3306", "dbname": "bookstore" } }
config.php
<?php namespace Bookstore\Utils; use Bookstore\Exceptions\NotFoundException; require_once __DIR__ . '/NotFoundException.php'; class Config { private $data; //类静态变量,保证变量唯一性 private static $instance; //构造函数私有化,类外部不可以调用. private function __construct() { $json = file_get_contents(__DIR__ . '/app.json'); $this->data = json_decode($json, true); } //单例模式,保证只实例化一个类. public static function getInstance() { if (self::$instance == null) { //是可以自己实例化自己的. self::$instance = new Config(); } return self::$instance; } public function get($key) { if (!isset($this->data[$key])) { throw new NotFoundException("Key $key not in config."); } return $this->data[$key]; } } ?>
test.php
<?php //使用命名空间,易于在大型应用中管理和组织php类. use Bookstore\Utils\Config; //命名空间可以直接use,但如果这个命名空间没有在标准约定位置,且没有自动载入的话,需要使用require来手工定位一下. require_once __DIR__ . '\Config.php'; header("content-type:text/html;charset=utf-8"); $dbConfig = Config::getInstance()->get("db"); $connStr = "mysql:host={$dbConfig['host']};port={$dbConfig['port']};dbname={$dbConfig['dbname']};charset=utf8"; $db = new \PDO($connStr, $dbConfig['user'], $dbConfig['password']); $db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC); $query = 'SELECT * FROM book WHERE author = :author'; $statement = $db->prepare($query); $statement->bindValue('author', 'George Orwell'); $statement->execute(); $rows = $statement->fetchAll(); foreach ($rows as $row) { var_dump($row); } echo "<br/>"; $query = <<<SQL INSERT INTO book(isbn, title, author, price) VALUES(:isbn, :title, :author, :price) SQL; $statement = $db->prepare($query); $params = [ 'isbn' => '9781413108614', 'title' => 'Iliad', 'author' => 'Homer', 'price' => 9.25 ]; $statement->execute($params); $result = $db->exec($query); echo $db->lastInsertId(); echo "<br/>"; function addBook(int $id, int $amount=1):void { $query = 'UPDATE book SET stock = stock + :n WHERE id = :id'; $statement = $db->prepare($query); $statement->bindValue('id', $id); $statement->bindValue('n', $amount); if (!$statement->execute()) { throw new Exception($statement->errorInfo()[2]); } } function addSale($db, int $userId, array $bookIds):void { $db->beginTransaction(); try { $query = 'INSERT INTO sale(customer_id, date)' . 'VALUES(:id, NOW())'; $statement = $db->prepare($query); if (!$statement->execute(['id'=> $userId])) { throw new Exception($statement->errorInfo()[2]); } $saleId = $db->lastInsertId(); $query = 'INSERT INTO sale_book(book_id, sale_id)' . 'VALUES(:book, :sale)'; $statement = $db->prepare($query); $statement->bindValue('sale', $saleId); foreach ($bookIds as $bookId) { $statement->bindValue('book', $bookId); if (!$statement->execute()) { throw new Exception($statement->errorInfo()[2]); } } $db->commit(); } catch (Exception $e) { $db->rollback(); throw $e; } } try { addSale($db, 1, [1, 2, 300]); } catch (Exception $e) { echo 'Error adding sale: ' . $e->getMessage(); } try { addSale($db, 1, [1, 2, 3]); } catch (Exception $e) { echo 'Error adding sale: ' . $e->getMessage(); } ?>
输出
array(6) { ["id"]=> string(1) "1" ["isbn"]=> string(13) "9780882339726" ["title"]=> string(4) "1984" ["author"]=> string(13) "George Orwell" ["stock"]=> string(2) "12" ["price"]=> string(3) "8.7" } array(6) { ["id"]=> string(1) "3" ["isbn"]=> string(13) "9780736692427" ["title"]=> string(11) "Animal Farm" ["author"]=> string(13) "George Orwell" ["stock"]=> string(1) "8" ["price"]=> string(4) "4.06" } 0 Error adding sale: Cannot add or update a child row: a foreign key constraint fails (`bookstore`.`sale_book`, CONSTRAINT `sale_book_ibfk_2` FOREIGN KEY (`book_id`) REFERENCES `book` (`id`))