Шаблон DataMapper PHP: моему классу нужен экземпляр PDO, я хочу обернуть его внутри класса Db

вот что у меня есть:

class Entry { public $id; public $name; public $seoName; public $timeCreated; public function someFunction() { } } class EntryMapper { protected $db; public function __construct(PDO $db) { $this->db = $db; } public function saveEntry(Entry &$entry) { if($entry->id){ $sql = ""; } else { $sql = "INSERT INTO tbl_entry (name, seo_name, time_created) VALUES (:name, :seo_name, :time_created)"; $stmt = $this->db->prepare($sql); $stmt->bindParam("name", $entry->name); $stmt->bindParam("seo_name", $entry->seoName); $stmt->bindParam("time_created", $entry->timeCreated); $stmt->execute(); $entry->id = $this->db->lastInsertId(); } } } 

Теперь, вот как я использую его в своем файле просмотра (в настоящее время просто тестирую команду вставки):

 $entry = new Entry(); $entry->name = "Kartonaža ad Gradačac"; $entry->seoName = "kartonaza-ad-gradacac"; $entry->timeCreated = date("Ymd H:i:s"); $entryMapper = new EntryMapper(new PDO("mysql:host=.....")); $entryMapper->saveEntry($entry); 

Я хочу иметь строку $ entryMapper следующим образом:

 $entryMapper = new EntryMapper(new Database()); 

что я должен иметь отдельный класс Database.php, где я бы установил соединение.

Я пробовал это, но так как моему классу EntryMapper.php нужен экземпляр PDO напрямую, я получаю сообщение об ошибке. Я пробовал Database расширить от PDO, но также вызывает ошибку, заявив, что конструктор PDO не был вызван в EntryMapper

Есть предположения?

EDIT: если вы видите какие-либо признаки кодовой связи или аналогичные, сообщите мне, потому что я хочу научиться правильно кодировать. Большое спасибо!

Вы можете использовать шаблон Factory и создать объект PDO внутри функции в классе Database.

 class Database { private const connStr = 'mysql:host=.....'; public static function createPDODatabase() { return new PDO(connStr); } } 

Поэтому вы можете вызвать конструктор EntryMapper следующим образом:

 $entryMapper = new EntryMapper(Database::createPDODatabase()); 

EDIT: если вы хотите сделать это, создав экземпляр объекта Database, вы должны вызвать конструктор PDO в конструкторе класса Database.

 class Database extends PDO { public function __construct($dbname='db_name', $server='localhost', $username='db_user', $password='db_password') { parent::__construct("mysql:host=$server;dbname=$dbname", $username, $password); parent::setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC); } } 

Затем вы можете просто создать экземпляр объекта базы данных.

 $entryMapper = new EntryMapper(new Database()); 

Вот как я, наконец, решил это (если появится лучшая реализация, я обязательно перекодирую). Реализация решения в соответствии с принятым ответом здесь: Global или Singleton для подключения к базе данных?

Мой ConnFactory.php

 include('config/config.php'); class ConnFactory { private static $factory; public static function getFactory() { if(!self::$factory){ self::$factory = new ConnFactory(); return self::$factory; } } private $db; public function pdo() { if(!$this->db){ $options = array( PDO::ATTR_PERSISTENT => true, PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_EMULATE_PREPARES => false, PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8" ); $this->db = new PDO("mysql:host=".DB_HOST.";port=".DB_PORT.";dbname=".DB_SCHEMA."", DB_USER, DB_PASS, $options); } return $this->db; } } в include('config/config.php'); class ConnFactory { private static $factory; public static function getFactory() { if(!self::$factory){ self::$factory = new ConnFactory(); return self::$factory; } } private $db; public function pdo() { if(!$this->db){ $options = array( PDO::ATTR_PERSISTENT => true, PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_EMULATE_PREPARES => false, PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8" ); $this->db = new PDO("mysql:host=".DB_HOST.";port=".DB_PORT.";dbname=".DB_SCHEMA."", DB_USER, DB_PASS, $options); } return $this->db; } } 

Использование в моем представлении / html-файле (просто проверка функции вставки):

 $entry = new Entry(); $entry->name = "Kartonaža ad Gradačac"; $entry->seoName = "kartonaza-ad-gradacac"; $entry->timeCreated = date("Ymd H:i:s"); $entryMapper = new EntryMapper(ConnFactory::getFactory()->pdo()); $entryMapper->saveEntry($entry);