2016-12-04 96 views
2

我来自Java编程,我试图将我的知识应用于PHP中的OOP风格编程。致命错误:无法重新声明class CLASSNAME错误已经尝试require_once()

所以,我试图创建一个实用程序类连接到数据库,就像我通常在Java中创建一个静态方法来获取数据库连接一样。

但花费数小时后,我仍然无法修复错误。

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

的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"); ,但仍然无法摆脱错误。

我试着让obtainConnection()静态,并通过DBHelper::obtainConnection();调用它,但没有运气。相同的错误消息。

我得到打开的class DBHelper{

撑我希望你能帮助我这个错误。

谢谢。

+0

嗯,你是正确的做'require_once'或'include_once'。它是否说你不能声明“DBHelper”或什么是类名? – Rasclatt

+0

@Rasclatt首先,谢谢。是的,我得到了错误致命错误:无法重新声明类DBHelper – p3ace

+0

其他原因可能是1)您正在使用相同的名称作为已在其他地方创建的类(可能由别人),在这种情况下,您应该使用命名空间2)也许你重复这个文件,以重命名和扩展它,并忘记更改重复文件上的类名称。 – Rasclatt

回答

2

一对夫妇的提示PHP中实现面向对象编程的时候,你应该做的:

1)我想可能重新考虑不直接烘烤数据库凭据到类,就更难/更麻烦,如果要修改它们通过UI你想实现一个UI控制机制。相反,请尝试制作一个define或者一个json pref文件或一个包含数组的类似动态创建的php文件。我会做一个定义,因为它是最简单的证明:

/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文件,然后让你不必手动包括创建一个类autoloader /需要页面中的类。它会自动它们包括:

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)我要建立一个静态连接,所以你不创建一个新的连接每一次(也是我会用PDO):

/班/ 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)的我使用类似于此自动装载功能的东西:

/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)创建有用/可重复使用的功能或类/方法

/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>'; 
} 
+0

感谢您的所有提示。所有这些将在未来有用,因为我继续学习使用PHP进行编程的OOP方式。你实际上是正确的,我必须与require_once一起使用名称空间来修复错误。我要研究你给出的例子。大多数的OOP模式和风格与我在Java中的做法相似。我只需要学习一些关键字和命令。再次感谢。我的问题是通过使用名称空间解决的。 – p3ace

+0

希望这些东西是有用的,我添加了一些额外的部分,我注意到我没有很好地解决一些事情,或者在某些情况下,根本没有解决。干杯 – Rasclatt

相关问题