php - 数据库工作的组织

标签 php mysql object architecture pdo

我有一些 PHP 经验,但没有应用程序架构方面的经验
现在我想组织自己的“自行车”。这是一些没有用的东西,也许是迷你框架或迷你应用程序,我想在这里得到一些经验。

我现在需要编写用于处理数据库的类和用于实体的类(其中之一是User)
我有以下数据库代码(省略了一些检查和方法来缩小这个问题):

namespace DataBase;
class DataBase {
    /**
     *
     * @var \PDO $pdo
     */
    public $pdo;
    public function __construct($host, $dbname, $username, $password=''){

        $this->pdo = new \PDO('mysql:host='.$host.';dbname='.$dbname, $username, $password,
            array(\PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'UTF8'"));
        $this->pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);

    }
    /**
     *
     * @param string $statement
     * @return Statement
     */
    public function prepare($statement){
        return new Statement($this->pdo->prepare($statement));
    }
}


namespace DataBase;

class Statement {
    private $stmt;

    public function __construct(\PDOStatement $stmt) {
        $this->stmt = $stmt;
    }

    public function query() {
    try {
        $this->stmt->execute();
        return $this; //for chaining
    }

    public function bind($key, $value) {
        $this->stmt->bindValue($key, $value, $this->typeof($value));
        return $this; //for chaining
    }
        //some methods for fetching data(works with fetch,fetchAll, fetchColumn and different PDO::FETCH_ methods

    public function fetchUpdate($obj) {
        $this->stmt->setFetchMode(\PDO::FETCH_INTO, $obj);
        $this->stmt->fetch();
    }

    public function fetchRow() {
        return $this->stmt->fetch(\PDO::FETCH_OBJ);
    }
    public function fetchRowClass($class) {
        return $this->stmt->fetchObject($class);
    }
}

还有一些用户类的虚拟对象

<?php

/**
 * Description of User
 *
 * @author riad
 */
class User {
    private $id;

    private $name = null;

    private $status = null;

    private $hasInfo = false;

    private static $cache=array();
    public function __construct() {

    }
    public function getId() {
        return $this->id;
    }
    public function getName() {
        if(!$this->hasInfo)
            $this->getInfo ();
        return $this->name;
    }
    public function isAuthorized(){
        return $this->status!="noauth";
    }
    public static function createById($id) {
        // I want this method to cerate user from id, then get info only I will use it after that
        if(array_key_exists($id,self::$cache)){
            return self::$cache[$id];
        }
        $user = new User;
        $user->id = $id;
        return $user;
    }
    private function getInfo(){
        try{
            \FrontController::getInstance()->getDB()->
                prepare('SELECT * FROM `users` WHERE `id`=:id')->
                bind('id', $this->id)->query()->fetchUpdate($this);
            $this->hasInfo = true;
        }
        catch(\DataBase\NotFoundException $dbe){
            $this->status = "deleted";
        }
    }
    public static function createFromRequest($request){
        $user = new User;
        try{
            //try get data from cookie
            \FrontController::getInstance()->getDB()->
                prepare('SELECT * FROM `users` WHERE `session` = :session AND `id`= :id')->
                bind('id', $id)->bind('session',$session)->query()->
                fetchUpdate($user);
        }
        catch(... $e){
            $user->status = "noauth";
            $user->id = 0;
            // make it unregged
        }
        return $user;
    }
}

?>
<小时/>

我遇到了一些问题。

  • 我不想从数据库设置属性,这些属性未在类列表的属性中列出(当然,这不是那么重要)。我知道我可以使用
    public function __call($name,$value){
    //do nothing;
    }
  • 我想将此 Prop 私有(private)化,但也想使用 $stmt->fetchUpdate($obj) 我知道我可以使用
    public function __call($name,$value){
    $this->$name=$value;
    }
    ,但它是作为公开 Prop 声明的,并且它在第一个点的路上 我也可以使用
    public function __call($name,$value){
    if($name=='id'){
        $this->id=$value;
    }
    else if($name=='status'){
        $this->status=$value;
    }
    }
    但是为每个实体类编写它而不是从该方法的公开中保存它是不舒服的
  • 当我从数据库获取此类时,我想将 $this->hasInfo 设置为 true。我知道我可以更改我的 Database 类,以便始终将某些变量设置为 true (默认情况下它为 false)。但似乎不太优雅。
  • 我想在设置id时更新缓存(它可能用作以前的点)
  • 是否可以避免 fetchRowClass 直接写入 props 并像 fetchUpdate 一样使用 setter?或者允许fetchUpdate直接访问?

我知道我自己编写了很多代码,但我想听听您的意见:

  • 我应该改进什么?
  • 对于之前列表中的问题,还有哪些其他/最佳可能的解决方案?

希望,阅读和理解并不难。
很高兴看到任何建议
关于亚历克斯

最佳答案

一些提示:[基于我自己的经验和我已经使用的框架]

基本上,您应该/想要/可能做的是为模型中的所有类创建一个父类(super class)。此类将包含对数据库实例的引用,并且它将具有模型的所有常用方法,即 getById($id)getAll()getPaginated()

此父类(super class)的另一个目标是将数据库中的结果映射到模型类的实例中。因此最终,您的用户类将仅具有特定于该类的属性、访问器和方法,例如特殊查询或类似的东西。

下面是一个示例:

Class Model{
    protected function getById($_id){
        $_table = get_class($this);
        $anonymous = $this->_getObjectById($_table,$_id); //this method will execute a query (unsing PDO) and return a StdClass object with the results
        $this->mapTable($anonymous,$_table); //this method will take the StdClass instance and will transform it into a $_table Instance
    }

    private function mapTable($stdInstance,$model_name){
        foreach($stdInstance as $key => $value){
            try{
                if(property_exists($this,$key)){
                    $this->$key = $value; //you could declare the model's properties     as protected... or you could create accessors and call them here
                }
            } catch(Exception $ex) {
                /* something went wrong o_O */
            }
     }

Class User extends Model{
     protected $id;
     protected $name;
     .....
}

Class Controller{
    public function index(){
         $user = new User();
         $user->getById($_GET['id']);
         print_r($user);
         //now you can pass the $user object to the View to display it
    }
}

简而言之... Model 类是一个非常小的 ORM 。您可以尝试创建自己的 ORM(就像我一样),但是在尝试映射对象之间的关系时您将面临很多问题: Nx1,1xN,NxN,1x1、继承、“更深层次的关系”和 n+1 problem 。您还需要以某种方式定义模型结构,以便您的 ORM 可以理解它,可能使用 YAML/XML 文件或直接从数据库的表结构中读取结构,或者在属性中采用命名约定...

这是一个非常有趣的领域:)

希望这有帮助,祝你好运

关于php - 数据库工作的组织,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7085043/

相关文章:

php - 从 mysql 数据库刷新多个 Div

mysql - 如何在mysql中使用左外连接来获得我想要的结果?

javascript - 关于代码执行和javascript阻塞/非阻塞性质的问题

php - 处理查询结果中的引号 PHP

object - 为什么 HTML anchor 标记不包装可缩放的 SVG <object>?

java - 对象数组 For 循环

javascript - Object.create() 未完全创建;

php - mysql concat字符串与结果

php - 如何删除 WordPress 中导航栏的这种 jquery 效果?

php - 如何将 PHP 变量传递给 WordPress 中的 JavaScript 函数?