【问题标题】:how to call method with "::" in the first and "->" for the rest in method chaining如何在第一个中使用“::”调用方法,在方法链接中使用“->”调用其余的方法
【发布时间】:2017-12-10 06:02:04
【问题描述】:

我想创建自己的类,用于与数据库交互, 如果我使用方法链接,我认为它会很容易和可读。 但是我在静态调用第一个方法时遇到了问题。

代码如下:

<?php

class Crud
{

    protected static $action;
    protected static $instance = null;
    protected static $columns  = [];
    protected $data;
    protected $db;
    protected $query;
    protected $table;

    public function __construct()
    {
        $this->db = new mysqli('localhost', 'root', '', 'bahan_belajar');
        if (!$this->db) {

            echo "error";
        }
        return $this;
    }

    public static function getInstance()
    {
        if (self::$instance === null) {
            self::$instance = new self;
        }
        return self::$instance;
    }

    public function select()
    {
        if (empty(func_get_args())) {
            // $this->columns = "*";
            self::$columns = "*";
        } else {
            if (is_array(func_get_args())) {
                // self::columns = join(', ', func_get_args());
                self::$columns = join(', ', func_get_args());
            } else {
                // self::columns = func_get_args();
                self::$columns = func_get_args();
            }
        }

        self::$action = "SELECT";
        return $this;
    }

    public function from($tableName)
    {
        $this->table = ' FROM ' . $tableName;
        return $this;
    }

    public function get($getName = 'object')
    {
        $this->query = self::$action . ' ' . self::$columns . ' ' . $this->table;
        switch ($getName) {
            case 'object':
                $this->data = $this->db->query($this->query)->fetch_object();
                break;
            case 'array':
                $this->data = $this->db->query($this->query)->fetch_array();
                break;
            case 'count':
                $this->data = $this->db->query($this->query)->num_rows;
                break;
        }
        return $this->data;
    }
}

$chat = Crud::getInstance()->select('nama', 'teks')->from('chat')->get();


echo '<pre>';
print_r($chat);
echo '</pre>';

实际上,如果我首先使用getInstance() 方法,如上所示,此代码可以正常工作。但是,当我直接调用 select() 方法作为静态方法时,如何使它工作,例如:

$chat = Crud::select('nama', 'teks')->from('chat')->get();

如果我运行上面的代码,我会得到一个错误,例如:

致命错误:未捕获的错误:在 C:\xampp\htdocs\bahan_belajar\chat\classes.php:47 的对象上下文中使用 $this 堆栈跟踪:#0 C:\xampp \htdocs\bahan_belajar\chat\classes.php(74): Crud::select('nama', 'teks') #1 {main} 在 C:\xampp\htdocs\bahan_belajar\chat\classes 中抛出。 php上线47

我知道 select() 方法应该是静态方法,然后才能使用 :: 调用(我认为),但我怎样才能使其成为静态方法?

【问题讨论】:

  • 您只能将:: 与静态方法一起使用,-&gt; 与实例方法一起使用。您需要使用静态方法获取一个实例,然后使用-&gt; 进行链接,如下所示:Crud::getInstance()-&gt;select('nama', 'teks')-&gt;from('chat')-&gt;get();
  • 是的,感谢您的评论。目前我仍然想知道如何在 select() 方法上应用静态,并且可以跟 -&gt; 分配其他方法。我仍然不知道如何解决这个问题:(
  • 查看我更详细的答案。简短的版本是可以使用魔术方法让您在需要时假装实例方法是静态方法,但这并不容易。

标签: php oop static-methods method-chaining


【解决方案1】:

您只能将:: 与静态方法一起使用,-&gt; 与实例方法一起使用。这给您留下了 2 个选择:

选项 1:在链接之前显式获取实例

你需要用你的静态方法获取一个实例,然后使用-&gt;链接,像这样:

Crud::getInstance()->select('nama', 'teks')->from('chat')->get();

选项 2:使用魔术方法获得乐趣

您的另一个选择是喜欢magic methods。如果您将方法设为protectedprivate,则可以使用__call()__callStatic() 魔术方法从类外部拦截对这些方法的调用。当您在__callStatic() 中时,您可以通过调用self::getInstance() 切换到使用实例。

这种方法可以让你做类似的事情

Crud::select('nama', 'teks')->from('chat')->get();

这里有一些非常简化的示例代码来演示这个想法 (demo on 3v4l):

class Test
{
    public static $instance;
    protected $myVar = 'foo';

    // This intercepts instance calls ($testObj->whatever()) and handles them
    public function __call($name, $args)
    {
        return call_user_func_array(array($this, $name), $args);
    }

    // This intercepts instance calls ($testObj->whatever()) and handles them
    // The use of self::getInstance() lets us force static methods to act like instance methods
    public static function __callStatic($name, $args)
    {
        return call_user_func_array(array(self::getInstance(), $name), $args);
    }

    public static function getInstance()
    {
        return self::$instance ? : new self;
    }

    protected function getMyVar()
    {
        echo $this->myVar;
    }

    protected function setMyVar($value)
    {
        $this->myVar = $value;
        return $this;
    }
}

echo Test::setMyVar(15)->getMyVar(); // successfully echoes 15

所有这一切的一个重要说明:你所做的看起来很像重新发明Eloquent, the ORM that ships with Laravel。从以前构建过自己的 ORM 的人那里得到它:你最好使用像 Eloquent 这样的现有系统,它已经被编写并经过全面测试(并且可以在不需要你使用整个 Laravel 框架的情况下使用)。构建 ORM 比看起来要困难得多,而且一旦开始,兔子洞就会越来越深。

【讨论】:

  • 谢谢..它的工作符合预期。我只是想尝试创建我自己的,我可以开发并从中学习:)。很抱歉没有按时回复,因为某事..
猜你喜欢
  • 1970-01-01
  • 2021-11-14
  • 1970-01-01
  • 2012-08-19
  • 1970-01-01
  • 1970-01-01
  • 2013-11-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多