0

这一直困扰着我一段时间的 PHP,我仍然无法弄清楚我会怎么做。基本上,目前对于我的 SQL 类,我将结果转储到一个数组中并将它们转换为一个对象以给出如下内容:

$first_post = $Post->find(1);

(我也一直试图让语法看起来像: $Post::find(1); 但这完全是一个不同的纯粹审美问题)

然后你可以像这样使用 first_post :

$first_post->title;

这是通过将内容转换为$post->find(1)对象来完成的,如下所示:

$first_post = (object) array("title" => "blah");

我知道它实例化了一个新的 STDClass,但我不知道如何将方法绑定到 STDClass 的新实例。这主要是因为我可以做类似的事情:

$posts = $Post->all();
$last_post = $posts->last();
$specific  = $posts->find("name" => "hello");

有什么想法可以让 PHP 做这样的事情吗?

4

5 回答 5

1

您不能将方法绑定到,StdClass因为您可以使用 JavaScript 动态添加方法。

您需要使用所需的方法创建一个类。(您可以使用extends,或者trait如果您将有不同类的通用方法。)

例如:

class Post
{
    static function find()
    {
        $post = new Post();
        $array = array('title' => 'First Post');
        foreach ($array as $key => $value)
        {
            $post->$key = $value;
        }
        return $post;
    }

    public function do_something()
    {
        echo $this->title;
        return $this;
    }
}
于 2012-06-18T14:09:14.610 回答
1

(我也一直试图让语法看起来像: $Post::find(1); 但这完全是一个不同的纯粹审美问题)

使用范围解析运算符时,您正在访问静态方法和/或常量。这些是作用于类而不是类的实例的方法。例如:

// the find method retuns a new Post instance and 
// does not try to access $this
$post = Post::find(1);  

至于从数组为帖子创建对象,最好创建自己的Post类并相应地填充它,或者使用将表数据作为对象而不是数组返回的数据库函数之一,例如mysqli_result::fetch_objector mysql_fetch_object

如果创建您自己的 Post 类,您可以将数据库信息存储在一个数组中并使用__call(),__get()__get() 魔术方法来访问该数据。例如:

class Post() {
    protected $data;

    public function __construct($data) {
        $this->data = $data;
    }

    // access data with a getFoobar() style call
    public function __call($name, $args) {
        if (substr($name, 0, 3) == 'get') {
            $key = strtolower(substr($name, 3));
            if (array_key_exists($key, $this->data)) {
                return $this->data[$key];
            }
        }

        $class = get_class($this);
        throw new Exception("Call to undefined method $class::$name");
    }

    // access data like a class property
    public function __get($key) {
        if (array_key_exists($key, $this->data)) {
            return $this->data[$key];
        }

        throw new Exception("Attempt to access non-existant property $class::$name");
    }

    // set the data like a class property
    public function __set($name, $value) {
        $this->data[$name] = $value;
    }
}
于 2012-06-18T14:12:41.110 回答
0

您可以但需要在每次实例化时每次都这样做:

$obj = new stdClass();
$obj->myMethod = function($name) {echo 'Hello '.$name;};

好的,上面不起作用...我已经成功地使用了文档中的这种方法,这与相同的思路:http: //uk3.php.net/manual/en/reserved.classes.php#105404

于 2012-06-18T13:55:58.843 回答
0

我想你可以创建一个Post

实例化后,它可以获取所有帖子并存储为数组。

它可以有一个 find 方法来搜索指定查询的所有帖子。

它还可以有一个 last 和 first 方法,分别获取最后一个项目或第一个项目。

我相信您可以使用该方法动态创建类属性__get。这接受一个属性名称,它可以搜索您的帖子数组并返回该值(如果存在)。

您可以在 PHP 中动态创建实例属性吗?

于 2012-06-18T13:57:11.603 回答
0

如果您正在使用PDO从数据库中检索数据,请查看此方法PDOStatement::setFetchMode。您可以告诉 PDO 为结果中的每一行实例化一个新类PDO::FETCH_CLASS。确切的方法定义是这样的:

bool PDOStatement::setFetchMode ( int $PDO::FETCH_CLASS , string $classname , array $ctorargs )

并将其放入您的上下文中:

namespace My\Web;

class Post {
    public function __construct($arg) {
        var_dump($arg);
    }

    public function getTitle() {
        return $this->title;
    }

    public function getFormatedContent() {
        return whatever($this->content);
    }
}

获取对象:

$stmt = $conn->query($sql);
$posts = $stmt->setFetchMode(PDO::FETCH_CLASS, 'My\Web\Post', array(rand()));
print_r($posts);
// print array of My\Web\Post objects, each will print some random number in it's constructor.

所以我想向您展示的是,您不必将属性数组转换为 stdClass 然后绑定一些方法。
您可以根据需要创建类,并让 PDO 使用该类包装查询结果。

顺便说一句,它也适用于最新的 Doctrine DBAL(因为它是建立在 PDO 之上的)。

于 2012-06-18T14:28:54.237 回答