简体   繁体   English

从静态方法中的另一个类调用非静态方法

[英]Call non static method from another class in static method

I wanna call a non static method from my Database Class in a static method. 我想以静态方法从数据库类中调用非静态方法。

Uncaught Error: Call to a member function select() on null in E:\\xampp\\htdocs\\danacrm\\libs\\Setting.php:32 未捕获的错误:在E:\\ xampp \\ htdocs \\ danacrm \\ libs \\ Setting.php:32中以null调用成员函数select()

what is my solution?! 我的解决方案是什么?

This is my Database class : [ path : ../libs/Database.php ] 这是我的数据库类:[path:../libs/Database.php]

    class Database extends PDO
    {
        function __construct($DB_TYPE, $DB_HOST, $DB_NAME, $DB_USER, $DB_PASS)
        {
            parent::__construct($DB_TYPE . ':host=' . $DB_HOST . ';dbname=' . $DB_NAME, $DB_USER, $DB_PASS,array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'utf8'"));
        }

        public function select($SQL,$array=array(),$fetch_style=  PDO::FETCH_ASSOC) {

            $query = $this->prepare($SQL);
            foreach ($array as $key => $value) {
                $query->bindvalue(":$key", $value);
            }
            $query->execute();

            return $query->fetchAll($fetch_style);
        }
        public function insert($table, $data) {
            ksort($data);

            $fieldkey = implode('`, `', array_keys($data));
            $fieldvalue = ':' . implode(', :', array_keys($data));

            $query = $this->prepare("INSERT INTO  $table
                  ( `$fieldkey` )
           VALUES ( $fieldvalue )");

            foreach ($data as $key => $value) {
                $query->bindvalue(":$key", $value);
            }

            return $query->execute();

        }

        public function update($table, $data, $where) {
            ksort($data);
            $fieldDetails = "";
            foreach ($data as $key => $value) {
                $fieldDetails .= " `$key`= :$key ,";
            }
            $fieldDetails = rtrim($fieldDetails, ' ,');

            $query = $this->prepare("UPDATE $table  SET $fieldDetails  WHERE $where");


            foreach ($data as $key => $value) {

                $query->bindvalue(":$key", $value);
            }
            if($query->execute())
                return true;

            return false;
        }
        public function delete($table,$where) {
            $query = $this->prepare("DELETE FROM  $table  WHERE $where");
            return   $query->execute();
        }
    }

and my Setting class : [ path : ../libs/setting.php ] 和我的设置类:[path:../libs/setting.php]

class Setting
{

    protected static $db;

    function __construct()
    {
        self::$db = new Database(DB_TYPE,DB_HOST,DB_NAME,DB_USER,DB_PASS);
    }

    // I wanna use this method in whole of my project
    public static function options($option_name = false)
    {
        if ($option_name) {
            $options = self::$db->select("SELECT * FROM `options` WHERE `option_name` = '$option_name'");
            if(!empty($options[0]))
            {
                return $options[0];
            }
            else
            {
                return false;
            }
        } else {
            $options = self::$db->select("SELECT * FROM `options`");
        }
        return $options;
    }

}

You are doing quite a lot things wrong there. 您在这里做错了很多事情。

Don't wrap PDO class 不要包装PDO类

PDO already is a DB acces abstraction. PDO已经是数据库访问的抽象。 You do not need to abstract the abstraction. 您不需要抽象该抽象。 You are also doing the prepared statements wrong in your code, which makes your code vulnerable to SQL injections. 您还在代码中错误地执行了准备好的语句 ,这使您的代码容易受到SQL注入的攻击。 Please check the linked manual article and pay specific attention to use of bindParam() and bindValue() methods. 请检查链接的手册文章,并特别注意使用bindParam()bindValue()方法。 You could also watch this video (it's uses mysqli in the examples, but the core mechanic is the same), which should explain where to injection vulnerability actually comes from. 您也可以观看此视频 (示例中使用mysqli,但核心机制相同),该视频应说明注入漏洞的真正来源。

Use dependency injection 使用依赖注入

Your current code relies on the global state. 您当前的代码依赖于全局状态。 Instead you should inject the PDO instance as a dependency in your Settings service. 相反,您应该将PDO实例作为依赖项注入到Settings服务中。

In practice it would looks something like this: 实际上,它看起来像这样:

class Setting {
    privare $connection;

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

    public function options($option_name) {
        // codes here
    }
};

The idea basically is: 这个想法基本上是:

$db = new PDO;
$foo = new Foo($db);
$bar = new Bar($db);

This way the both Foo and Bar instance have the same DB connection. 这样, FooBar实例都具有相同的数据库连接。

Watching this lecture would be highly recommended. 强烈建议观看此讲座

Based on what Sahil Gulati and Yupik mentioned in the comments, you need first to instantiate the Database class before you can actually call it's methods. 根据注释中提到的Sahil Gulati和Yupik,您需要首先实例化Database类,然后才能实际调用它的方法。

Since static classes doesn't need to be instantiated (can be), it should be noted that all property inside Static classes that needs to be instantiated before usage are called first. 由于静态类不需要实例化(可以),因此应注意,在使用之前需要实例化静态类中所有需要实例化的属性。 One option for this one is to have some initiator function that will set the necessary objects into motion. 一种选择是拥有一些启动器功能,该功能可以将必要的对象设置为运动状态。 :) :)

class Database {
    public function select($sql) {
        //code here
    } 
};

class Setting {
    protected static $db;

    public static function initiate() {
        self::$db = new Database();
    }

    public static function options($option_name) {
        // codes here
    }
};

usage: 用法:

Setting::initiate();
Setting::options('some option name');

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM