2016-12-04 185 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

相關問題