[英]OOP PHP with Mysql Database
如果我们有这样的代码:
class Game {
private $_id;
private $_name;
private $_url;
public function __construct($_id,$_name,$_url){
$this->_id = $_id;
$this->_name = $_name;
$this->_url = $_url;
}
}
我们想简单地连接到我们的数据库以通过id获取游戏,我们在哪里放置'getByID'功能?
我们将它作为“静态函数”放在“游戏类”中,我们将它作为“公共函数”放在“数据库连接类”中,还是将该方法放在主索引中的'常规函数中? '作为'功能'?
我当前已选择'游戏类'中的'静态功能':
public static function getByID($id,$db){
$query = "SELECT * FROM game WHERE id = :id LIMIT 1";
$prepare = array(":id"=>$id);
$result = $db->Precute($query,$prepare);
foreach($result as $r) return new Game($r['id'],$r['name'],$r['url']);
return null;
}
(Precute是数据库类中的自定义函数,用于准备和执行查询)您将如何处理此问题?
在适当的OOP中,返回特定类的实例的DAL函数在该类中应该是静态的。 作为基本规则,与特定对象相关的所有功能都应该是该特定对象的一部分,如果在实例上调用则为实例方法,如果是创建或管理实例,则为静态方法('工厂模式')。
您的功能目前不是静态的,正确的用法是:
class Game
{
..other functions..
public static function getById($id)
{
..implementation, which can either access central storage or retrieve
the object itself if concurrent edits are not an issue..
}
}
其他地方:
$myGame = Game::getById(684);
你可能想看看Doctrine,而不是重新发明轮子。 即使您确实想要制作一个新的轮子,它的代码样本都遵循正确的OOP原则。
本答案采用另一种方法。 而不是从静态工厂获取对象。 此解决方案采用创建空白对象的方法,然后调用数据库方法以使对象成为实际行的实时表示。
首先是你问题的观察结果 -
Game
类的对象/实例表示一排桌面game
。 Game类本身可以作为“游戏”表的表示。
如果上述观察结果是正确的,并假设在类层次结构中有更多具有表示的表。 你应该有一个类来表示泛型'Table'
class Table { //The class itself can be made abstract depending upon the exact implementation
protected $_tableName;
protected $_connectionParams;
protected $idAttribute = 'id';
public function __construct($tableName, $connectionParams, $idAttribute){
$this->_connectionParams = $connectionParams;
$this->_tableName = $tableName;
if(isset($idAttribute)) {
$this->idAttribute = $idAttribute;
}
};
private function _getConnection() {
//return $db using $_connectionParams
};
public function getByID($id) {
$this->getByKeyVal($this->idAttribute, $id);
};
public function getByKeyVal($key, $val) {
$query = "SELECT * FROM ". $this->_tableName ." WHERE `". $key ."` = :key LIMIT 1";
$prepare = array(":key"=> $val);
$result = $this->_getConnection()->Precute($query,$prepare);
$this->processRow($result[0]);
};
//This needs to be overridden
public function processRow($row) {
return true;
};
}
现在扩展Game Table的通用Table类
class Game extends Table {
private $_id;
private $_name;
private $_url;
public function __construct($defaults) {
if(isset($defaults) {
if(is_array($defaults)) {
$this->processRow($defaults);
} else {
$this->getByID($defaults);
}
} else {
//Some default setup here if requried
}
$connectionParams = []; //Prepare Connection Params here
parent::__construct('game', $connectionParams);
};
//Override processRow
public function processRow($row) {
if(isset($row['id']) {
$this->_id = $row['id'];
}
$this->_name = $row['name'];
$this->_url = $row['url'];
};
}
以上是一个非常粗略的例子。 实际的类结构将取决于您的要求。 但一般的经验法则是将Class视为具体对象的蓝图。 与通用分类相关的所有方法都应该在自己的类中。
getConnection方法本身可以放入一个单独的DB连接类,并通过mixin模式或泛型类继承插入到表中。
像这样使用上面的设置
$game_new = new Game(); // for blank object --- for a new row
$game_435 = new Game(435); //row with 435 ID
$game_default = new Game(array( //new row with defaults
'name' => 'Some Name',
'url' => 'Some Url'
));
你想要的是一个装满Game对象的“桶”。 当你想要一个游戏对象(代表数据库中的数据)时,你会要求你的“桶”给你。 让我举一个Doctrine2如何实现这个的例子: http : //docs.doctrine-project.org/en/2.0.x/reference/working-with-objects.html
因此,您想要放置“getById”(或者我将“findById”)放在您的“桶”中。
// lets presume that the em is an instance of \Doctrine\ORM\EntityManager
// The entity manager does what the name says.
$id = 1234;
$game = $entity_manager->find('MyNamespace\Entity\Game', $id);
$game->setName('My first game!');
// We now tell the em to prepare the object for pushing it back to the "bucket" or database
$entity_manager->persist($game);
// Now we tell the em to actually save stuff
$entity_manager->flush();
这应该会告诉您如何使用它。 对象遵循单一责任原则 。 您不要求对象检索自己。 你要求“桶”检索一个对象。
http://en.wikipedia.org/wiki/Single_responsibility_principle
如果我告诉你有更多美丽的方式把东西放在他们的位置怎么办? 一个非常简单的案例可能包含3个基本组件:
为了更好地理解,您可以设想数据库对象映射器框架。 该框架可能非常复杂,但我们可以用几行来证明它的基本概念是如何工作的。
所以'框架':
<?php
//This class is for making link for db framework
class link
{
public $link;
public function __construct ($hostname, $database, $gamename, $password)
{
$this->link = new \PDO ('mysql:host='.$hostname.';dbname='.$database, $gamename, $password);
$this->link->query('use '.$database);
}
public function fetch ($query)
{
$result = $this->link->query($query)->fetch();
}
public function query ($query)
{
return $this->link->query($query);
}
public function error ()
{
return $this->link->errorInfo();
}
}
//This class collects table repositories and connections
class database
{
public $link;
public $tables = array ();
public function __construct ($link)
{
$this->link = $link;
table::$database = $this;
}
}
//This is basic table repositor class
class table
{
public static $database;
}
?>
现在我们有了db框架,让我们制作一些知道如何保存/加载/删除游戏的表格存储库:
class games extends table
{
public function create ($row)
{
$return = new game ();
$return->id = $row[0];
$return->name = $row[1];
var_export($row);
return $return;
}
public function load ($id=null)
{
if ($id==null)
{
$result = self::$database->link->fetch("select * from games");
if ($result)
{
$return = array();
foreach ($result as $row)
{
$return[$row[0]] = $this->create($row);
}
return $return;
}
}
else
{
$result = self::$database->link->fetch("select * from games where id='".$id."'");
if ($result)
{
return $this->create(reset($result));
}
else
{
echo ("no result");
}
}
}
public function save ($game)
{
if (is_array($save))
{
foreach ($save as $item) $this->save ($item);
}
if ($game->id==null)
{
return self::$database->link->query("insert into games set
name='".$game->name."'");
}
else
{
return self::$database->link->query("update games set name='".$game->name."'
where id='".$game->id."'");
}
}
public function delete ($game)
{
self::$database->link->query ("delete from games where id='".$game->id."'");
}
}
现在我们可以制作我们的模型,在这种情况下将包含实际的游戏类。
class game
{
public $id;
public $name;
public function __construct ($name=null)
{
$this->name = $name;
}
}
而实际使用它:
$database = new database (new link('127.0.0.1', 'system_db', 'root', '1234'));
$database->tables['games'] = new games();
if (!$database->tables['games']->save (new game('Admin')))
{
var_export($database->link->error());
}
var_export($database->tables['games']->load(2));
目前,我喜欢这种模式,以便在我的项目中使用db。 使用它我可以实现我的实际业务对象(在这种情况下类游戏)将不知道它们的保存位置和方式。 这使我能够独立于实际存储并专注于项目逻辑。
还有一个轻量级框架,所谓的db.php( http://dbphp.net ),它甚至让我能够避免编写表存储库,甚至创建/修改我的业务类所需的表,但使用几乎相同我在这里描述的概念。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.