致命错误:无法重新声明已经尝试过的class CLASSNAME错误require_once() [英] Fatal error: Cannot redeclare class CLASSNAME error already tried require_once()

查看:55
本文介绍了致命错误:无法重新声明已经尝试过的class CLASSNAME错误require_once()的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我来自Java编程,我试图将自己的知识应用于PHP的OOP风格编程.

I'm coming from Java programming and I'm trying to apply my knowledge in OOP style programming in PHP.

因此,我试图创建一个实用程序类来连接数据库,就像我通常在Java中创建一个静态方法来获取数据库连接的方式一样.

So, I tried to create a utility class to connect to database just like how I usually do it in Java where I create a static method to get the database connection.

但是,花了几个小时后,我仍然无法修复该错误.

However, after spending hours I still can't fix the error.

DBHelper.php

<?php

class DBHelper
{
    protected $db_name = 'myDb';
    protected $db_user = 'root';
    protected $db_pass = '';
    protected $db_host = 'localhost';

    public function obtainConnection()
    {

        $mysqli_instance = new mysqli($this->db_host, $this->db_user, $this->db_pass, $this->db_name);

        /* check connection */
        if (mysqli_connect_errno()) {
            printf("Connect failed: %s\n", mysqli_connect_error());
            exit();
        }
        return $mysqli_instance;
    }
}
?>

此文件中没有错误

然后我尝试在另一个名为login.php

Then I tried to use it on another file called login.php

login.php

<?php
if (isset($_POST['submit'])) {
    include "/DBUtility/DBHelper.php";
    $username = $_POST['username']; //s means string
    $password = $_POST['password']; // s means string
    echo "<br/> Username value: " . $username;
    echo "<br />Password value: " . $password;
}

if (empty($username) || empty($password) ) {
    echo "Fill out the fields!";
} else {

    //PREPARE THE PreparedStatment or Stored Procedure


    $dbHelper = new DBHelper();
    $connection = $dbHelper->obtainConnection();
    $preparedStatement = $connection->prepare('CALL getUserRoleByLogin(?, ?)'); //getUserRoleByLogin() is the name of stored proc in mysql db
    $preparedStatement->bind_param('ss', $username, $password); //assign arguments to ? ?
    $preparedStatement->execute();//execute the stored procedure. This will return a result

    $userRole = $preparedStatement->store_result();
    $countOfRows = $preparedStatement->num_rows;

?>

我阅读了有关Fatal error: Cannot redeclare class CLASSNAME错误的所有相关问题.我尝试按照许多人给出的使用require_once("DBHelper.php");而不是include("DBHelper.php");的说明进行操作 但仍然无法摆脱错误.

I read every related question about the Fatal error: Cannot redeclare class CLASSNAME error. I tried following the instructions given by many which is to use require_once("DBHelper.php"); instead of include("DBHelper.php"); but still can't get rid of the error.

我尝试将obtainConnection()设为静态,并通过DBHelper::obtainConnection();调用它,但是没有运气.相同的错误消息.

I tried making the obtainConnection() static and called it via DBHelper::obtainConnection(); but with no luck. Same error message.

我在打开class DBHelper {

希望您能对此有所帮助.

I hope you can help me with this.

谢谢.

推荐答案

在PHP中进行OOP时应做的几点提示:

A couple tips you should do when doing OOP in PHP:

1)我可能会重新考虑不要将db凭据直接烘焙到您的类中,如果您想直接实现UI控制机制,那么通过UI修改它们将变得更加困难/麻烦.相反,请尝试制作一个定义或一个json首选项文件或一个动态创建的php文件,其中包含一个数组,类似这样.我将进行定义,因为它最容易演示:

1) I would maybe rethink about not baking the db credentials into your class directly, it makes it harder/more cumbersome to modify them via UI if you wanted to implement a UI control mechanism down the line. Instead, try making a define or maybe a json pref file or a dynamically-created php file that contains an array, something like that. I will do a define because it's the easiest to demonstrate:

/config.php

# You can create a series of defines including the database
define('DB_HOST','localhost');
define('DB_NAME','dbname');
define('DB_USER','root');
define('DB_PASS','dbpassword');
# To maximize compatibility it's helpful to define fwd/back slash
define('DS',DIRECTORY_SEPARATOR);
# It is helpful to create path defines for easy file inclusion
define('ROOT_DIR',__DIR__);
define('CLASSES',ROOT_DIR.DS.'classes');

# Start session
session_start();

2)在config.php文件,这样您就不必在页面中手动包含/要求类.它将自动包括它们:

2) Create a class autoloader in the config.php file which then allows you to not have to manually include/require classes in pages. It will automatically include them:

spl_autoload_register(function($class) {
    if(class_exists($class))
        return;

    # This will turn a namespace/class into a path so should turn:
    # $db = new \DBUtility\DBHelper();
    # into:
    # /var/www/domain/httpdocs/classes/DBUtility/DBHelper.php
    $path = str_replace(DS.DS,DS,CLASSES.DS.str_replace('\\',DS,$class).'.php');
    # If the class file is located in the class folder, it will include it
    if(is_file($path))
        include_once($path);
});

3)我将创建一个静态连接,这样您就不会每次都创建一个新的连接(同样,我将使用

3) I am going to create a static connection so you don't create a new connection every time (also I will use PDO):

/classes/DBUtility/DBHelper.php

<?php
namespace DBUtility;

class DBHelper
{
    protected $query;
    private static $con;

    public function connection()
    {
        # This will send back the connection without making a new one
        if(self::$con instanceof \PDO)
            return self::$con;
        # I like to catch any pdo exceptions on connection, just incase.
        try {
            # Assign the connection
            self::$con = new \PDO('mysql:host='.DB_HOST.';dbname='.DB_NAME,DB_USER,DB_PASS);
        }
        catch(\PDOException $e) {
            # Here you can just die with a more user-friendly error.
            # It would be helpful to save the actual error to a log file
            $msg = $e->getMessage();
            # I would put your log outside the root or in a protected folder
            $txt = realpath(ROOT_DIR.DS.'..').DS.'errors'.DS.'sql.txt';
            # Make a directory if none set
            if(!is_dir(pathinfo($txt,PATHINFO_DIRNAME))) {
                # Make the directory
                if(mkdir(pathinfo($txt,PATHINFO_DIRNAME),0744,true)) {
                    # Save to log file
                    file_put_contents($txt,$msg.PHP_EOL);
                }
            }
            else {
                # Save to log file
                file_put_contents($txt,$msg.PHP_EOL);
            }

            die("Site is under maintenance.");
        }
    }
    # It would be helpful to create a query that will bind and not bind
    public function query($sql,$bind = false)
        {
            if(is_array($bind)) {
                foreach($bind as $key => $value) {
                    $sKey = ":{$key}";
                    $bindArr[$sKey] = $value;
                }

                $this->query = $this->connection()->prepare($sql);
                $this->query->execute($bindArr);
            }
            else {
                # The second "query" on this is the method from PDO, not the
                # "query" method from this class
                $this->query = $this->connection()->query($sql);
            }

            return $this;
        }

    public function getResults()
        {
            if(empty($this->query))
                return false;

            while($result = $this->query->fetch(\PDO::FETCH_ASSOC)) {
                $row[] = $result;
            }

            return (isset($row))? $row : false;
        }
}
# If your page ends with a php tag, you should just remove it. It will
# protect against empty spaces that may cause "header already sent" errors

3a)我使用与此类似的东西来自动加载功能:

3a) I use something similar to this to autoload functions:

/classes/Helper.php

class Helper
    {
        public static function autoload($function)
            {
                if(function_exists($function))
                    return;

                $path = ROOT_DIR.DS.'functions'.DS.$function.'.php';
                if(is_file($path))
                    include_once($path);
            }
    }

4)创建有用/可重用的函数或类/方法

4) Create useful/reusable functions or class/methods

/functions/getUserRole.php

function getUserRole($username,$password,\DBUtility\DBHelper $DBHelper)
    {
        return $DBHelper->query('CALL getUserRoleByLogin(:0, :1)',array($username,$password))->getResults();
    }

/index.php

# Include the config file
require_once(__DIR__.DIRECTORY_SEPARATOR.'config.php');

if (isset($_POST['submit'])) {
    # No need for this line ->> include "/DBUtility/DBHelper.php";
    # Use trim to remove empty spaces on the left and right
    $username = trim($_POST['username']);
    $password = trim($_POST['password']);
}

if (empty($username) || empty($password) ) {
    echo "Fill out the fields!";
} else {
    # User our function autoloader to include this function
    Helper::autoload('getUserRole');
    # Use the function and inject the DB class
    $userRoles = getUserRole($username,$password,new \DBUtility\DBHelper());
    $count     = count($userRoles);

    echo "Count: {$count}";
    echo '<pre>';
    print_r($userRoles);
    echo '</pre>';
}

这篇关于致命错误:无法重新声明已经尝试过的class CLASSNAME错误require_once()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆