Действительно, создание экземпляра с использованием new
и присвоение ему свойства не допускается.Вы можете сделать это назначение внутри конструктора, но вы получите нежелательную тесную связь между двумя классами.Правильные решения включают внедрение зависимости.Поэтому вы должны либо внедрить уже созданный экземпляр в конструктор (и назначить его внутри конструктора), либо внедрить его через метод установки (и назначить его внутри метода).Конструктор инъекций лучше.Основываясь на вашем коде, вот как вы можете разделить обязанности.
core / others / DatabaseAdapter.php
<?php
namespace core\others;
interface DatabaseAdapter {
public function select($params);
public function setTable($table = []);
public function groupBy($columns = []);
public function where($whereClause = [], $operator = '=', $operand = 'AND');
public function generateSQL();
public function run();
public function create($data = ['key' => 'value'], $table = null);
public function update($data = []);
public function delete($id, $table = null);
}
core / others / PdoAdapter.php
<?php
namespace core\others;
use core\others\DatabaseAdapter;
class PdoAdapter implements DatabaseAdapter {
private $connection;
private $selectParams = '*';
protected $table = '';
protected $lastTable = '';
protected $groupByColumns = '';
protected $where = '';
/**
* @param \PDO $connection Database connection.
*/
public function __construct(\PDO $connection) {
$this->connection = $connection;
}
/**
* Setting select parameters
* @param $params
* @return $this
*/
public function select($params) {
$this->selectParams = implode(",", $params);
return $this;
}
/* ... */
}
core / models / BaseModel.php
<?php
namespace core\models;
use core\others\DatabaseAdapter;
/**
* Class BaseModel
* @package core\models
*/
class BaseModel {
/**
* Database adapter.
*
* @var DatabaseAdapter
*/
protected $dbAdapter;
/**
* Table name.
*
* @var string|array
*/
protected $table = 'default';
/**
* @param DatabaseAdapter $dbAdapter Database adapter.
*/
public function __construct(DatabaseAdapter $dbAdapter) {
$this->dbAdapter = $dbAdapter;
}
/**
* Fetch all records from table.
*
* @return array
*/
public function all() {
return $this->dbAdapter
->setTable($this->table)
->select(["*"])
->run()
;
}
/**
* Find record by given id
* @param int $id
* @return array
*/
public function find($id = 1) {
return $this->dbAdapter
->setTable($this->table)
->select(["*"])
->where(['id' => $id])
->run()
;
}
/**
* Create a new record.
*
* @param array $columns (optional) The list of column name/value pairs, like:
* array(
* 'name' => 'example name',
* 'phone' => 'example phone number',
* )
* @return int Last insert id.
*/
public function create($columns = []) {
return $this->dbAdapter->create($columns, $this->table);
}
/**
* Update a record.
*
* @param array $columns (optional) The list of column name/value pairs, like:
* array(
* 'id' => 123,
* 'name' => 'example name',
* 'phone' => 'example phone number',
* )
* @return $this
*/
public function update($columns = []) {
$this->dbAdapter
->setTable($this->table)
->update($columns)
;
return $this;
}
/**
* Remove a record.
*
* @param int $id Record id.
* @return $this
*/
public function delete($id) {
$this->dbAdapter->delete($id, $this->table);
return $this;
}
/**
* Get table name.
*
* @return string|array
*/
public function getTable() {
return $this->table;
}
/**
* Set table name.
*
* @param string|array $table
* @return $this
*/
public function setTable($table = []) {
$this->table = $table;
if (is_array($table)) {
$tableNames = '';
foreach ($table as $table) {
$tableNames .= $table . ", ";
}
$this->table = rtrim($tableNames, ", ");
}
return $this;
}
}
core / models / ModelFactory.php
<?php
namespace core\models;
use core\others\PdoAdapter;
use app\models\DefaultModel;
use core\others\DependencyContainer;
/**
* Class ModelFactory
* @package core\models
*/
class ModelFactory {
/**
* @param $model
* @param null $pdo
* @return DefaultModel
*/
public static function build($model, $pdo = null) {
$model = 'app\models\\' . ucfirst($model) . 'Model';
$dbInstance = ($pdo) ? $pdo : DependencyContainer::getInstance("Database");
$pdoAdapterInstance = new PdoAdapter($dbInstance);
if (class_exists($model)) {
return new $model($pdoAdapterInstance);
}
return new DefaultModel($pdoAdapterInstance);
}
}