使用DataBase进行工作安排

时间:2011-08-16 21:08:31

标签: php mysql object architecture pdo

我在PHP中有一些expierence,但在应用程序架构中没有人 现在我想要打造自己的“自行车”。这是没用的东西,可能是迷你框架或迷你应用程序,我想在这里得到一些exp。

我现在需要编写与数据库一起工作的类和实体的classese(其中一个是User
我有以下数据库代码(省略了一些cheks和方法来缩小这个问题):

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);
    }
}

和User类的一些虚拟

<?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;
    }
  • 我想将这个道具私有化,但也希望使用$stmt->fetchUpdate($obj)我知道我可以使用
    public function __call($name,$value){
    $this->$name=$value;
    }
    ,但它是宣告道具公众而且它在路上有第一点 我也可以使用
    public function __call($name,$value){
    if($name=='id'){
        $this->id=$value;
    }
    else if($name=='status'){
        $this->status=$value;
    }
    }
    但是为每个实体类编写它并不舒服,而不是从这种方法的宣传中保存
  • 当我从数据库中获取此类时,我想将$this->hasInfo设置为true。我知道我可以将我的Database类更改为始终将某个变量设置为true,默认情况下它是假的。但它似乎并不优雅。
  • 我想在设置id时更新缓存(可能用作主流点)
  • 是否可以避免fetchRowClass直接写道具并像使用fetchUpdate一样使用setter?或者可以允许fetchUpdate直接访问?

我知道我自己写了很多代码,但我想要你的意见:

  • 我应该改进什么?
  • 什么是其他/最好的解决方案来解决以前的问题?

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

1 个答案:

答案 0 :(得分:1)

很少提示:[基于我自己使用的经验和框架]

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

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

以下是一个示例:

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,继承,“更深层次的关系”和{{ 3}}。您还需要以某种方式定义模型结构,以便ORM可以理解它,可能使用YAML / XML文件或直接从数据库的表结构中读取结构,或者在属性中使用命名约定......

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

希望这会有所帮助,祝你好运