致命错误:无法重新声明已经尝试过的class CLASSNAME错误require_once() [英] Fatal error: Cannot redeclare class CLASSNAME error already tried 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屋!