參考 - 這個錯誤在PHP中意味著什麼?



Answers

致命錯誤:調用一個非對象的成員函數...

發生類似於xyz->method()代碼,其中xyz不是對象,因此該method不能被調用。

這是一個致命的錯誤,它將停止腳本(向前兼容性注意:它將成為從PHP 7開始的可捕獲錯誤)。

大多數情況下,這表示代碼缺少錯誤條件檢查。 在調用其方法之前驗證對象實際上是一個對象。

一個typical例子是

// ... some code using PDO
$statement = $pdo->prepare('invalid query', ...);
$statement->execute(...);

在上面的例子中,查詢無法準備, prepare()會將false賦給$statement 。 試圖調用execute()方法將導致致命錯誤,因為false是一個“非對象”,因為該值是一個布爾值。

找出為什麼你的函數返回一個布爾值而不是一個對象。 例如,檢查$pdo對像是否發生了最後一個錯誤。 有關如何調試的詳細信息取決於如何針對特定功能/對象/類處理錯誤。

如果即使->prepare失敗,那麼你的$pdo數據庫句柄對像也不會被傳入當前範圍 。 找到它的定義。 然後將其作為參數傳遞,將其存儲為屬性,或通過全局範圍共享它。

另一個問題可能是有條件地創建對象,然後嘗試調用該條件塊外部的方法。 例如

if ($someCondition) {
    $myObj = new MyObj();
}
// ...
$myObj->someMethod();

通過試圖在條件塊外執行該方法,可能不會定義您的對象。

相關問題:

  • 調用非對像上的成員函數
  • 列出所有PHP“致命錯誤:調用成員函數...在非對像上”Stackoverflow問題
Question

這是什麼?

這是關於在編程PHP時可能遇到的警告,錯誤和通知的一些答案,並且不知道如何解決。 這也是一個社區Wiki,所以每個人都被邀請參與添加和維護這個列表。

為什麼是這樣?

諸如“已發送頭文件”“調用非對象成員”等問題經常在堆棧溢出時彈出。 這些問題的根本原因總是相同的。 所以這些問題的答案通常會重複它們,然後顯示OP在他/她的特定情況下要改變哪條線。 這些答案不會給網站增加任何價值,因為它們只適用於OP的特定代碼。 具有相同錯誤的其他用戶不能輕易地從中讀取解決方案,因為它們太本地化。 這很令人傷心,因為一旦你明白了根本原因,糾正錯誤就很簡單。 因此,這份清單試圖以通用的方式解釋解決方案。

我應該在這裡做什麼?

如果您的問題已被標記為與此相同,請在下面找到您的錯誤消息並將修復應用到您的代碼。 答案通常包含進一步的調查鏈接,以防單獨從一般答案中不清楚。

如果您想貢獻,請添加您的“最喜歡的”錯誤消息,警告或通知,每個答案一個,簡短說明它的含義(即使它只是突出顯示手冊頁的術語),一個可能的解決方案或調試方法和一份有價值的現有問答清單。 此外,請隨時改進任何現有答案。

列表

另見




解析錯誤:語法錯誤,意外的T_XXX

當你在意想不到的地方有T_XXX令牌 ,不平衡的(多餘的)圓括號,使用短標籤而不在php.ini中激活它,等等。

相關問題:

進一步的幫助請看:




警告: [函數]期望參數1是資源,布爾給定

警告:mysql_fetch_array()的更一般的變體預計參數1是資源,布爾給定

資源是PHP中的一種type (如字符串,整數或對象)。 資源是一個不透明的blob,它本身沒有固有的有意義的價值。 資源是特定於某些PHP函數或擴展集定義的。 例如,Mysql擴展定義了兩種資源類型

有兩種資源類型在MySQL模塊中使用。 The first one is the link identifier for a database connection, the second a resource which holds the result of a query.

The cURL extension defines another two resource types :

... a cURL handle and a cURL multi handle.

When var_dump ed, the values look like this:

$resource = curl_init();
var_dump($resource);

resource(1) of type (curl)

That's all most resources are, a numeric identifier ( (1) ) of a certain type ( (curl) ).

You carry these resources around and pass them to different functions for which such a resource means something. Typically these functions allocate certain data in the background and a resource is just a reference which they use to keep track of this data internally.

The " ... expects parameter 1 to be resource, boolean given " error is typically the result of an unchecked operation that was supposed to create a resource, but returned false instead. For instance, the fopen function has this description:

Return Values

Returns a file pointer resource on success, or FALSE on error.

So in this code, $fp will either be a resource(x) of type (stream) or false :

$fp = fopen(...);

If you do not check whether the fopen operation succeed or failed and hence whether $fp is a valid resource or false and pass $fp to another function which expects a resource, you may get the above error:

$fp   = fopen(...);
$data = fread($fp, 1024);

Warning: fread() expects parameter 1 to be resource, boolean given

You always need to error check the return value of functions which are trying to allocate a resource and may fail :

$fp = fopen(...);

if (!$fp) {
    trigger_error('Failed to allocate resource');
    exit;
}

$data = fread($fp, 1024);

Related Errors:




解析錯誤:語法錯誤,意外的T_ENCAPSED_AND_WHITESPACE

當整個複雜變量結構不包含在{}時,嘗試引用帶雙引號字符串內引號的數字值時最經常遇到此錯誤。

錯誤情況:

這將導致Unexpected T_ENCAPSED_AND_WHITESPACE

echo "This is a double-quoted string with a quoted array key in $array['key']";
//---------------------------------------------------------------------^^^^^

可能的修正:

在雙引號字符串中,PHP將允許使用未加引號的數組鍵字符串,並且不會發出E_NOTICE 。 所以上面可以寫成:

echo "This is a double-quoted string with an un-quoted array key in $array[key]";
//------------------------------------------------------------------------^^^^^

整個複雜數組變量和密鑰可以用{}括起來,在這種情況下, 應該引用它們以避免E_NOTICEPHP文檔為複雜變量推薦了這種語法。

echo "This is a double-quoted string with a quoted array key in {$array['key']}";
//--------------------------------------------------------------^^^^^^^^^^^^^^^
// Or a complex array property of an object:
echo "This is a a double-quoted string with a complex {$object->property->array['key']}";

當然,上述任何一種方法的替代方法都是將數組變量連接起來,而不是對其進行插值:

echo "This is a double-quoted string with an array variable " . $array['key'] . " concatenated inside.";
//----------------------------------------------------------^^^^^^^^^^^^^^^^^^^^^

有關參考,請參閱PHP字符串手冊頁 變量分析部分




警告:有效的open_basedir限制

此警告可能會與文件和目錄訪問相關的各種功能出現。 它警告有關配置問題。

當它出現時,這意味著某些文件已被禁止訪問。

警告本身不會破壞任何內容,但如果阻止文件訪問,則通常腳本無法正常工作。

解決方法通常是更改PHP配置 ,相關設置稱為open_basedir

有時會使用錯誤的文件或目錄名稱,然後修復程序使用正確的文件或目錄名稱。

相關問題:




致命錯誤:無法重新聲明class [class name]

致命錯誤:無法重新聲明[函數名稱]

這意味著您要么使用相同的函數/類名稱兩次,需要重命名其中一個名稱,或者是因為您已經使用了requireinclude要使用require_onceinclude_once

當在PHP中聲明一個類或函數時,它是不可變的,並且以後不能用新值聲明。

考慮下面的代碼:

class.php

<?php

class MyClass
{
    public function doSomething()
    {
        // do stuff here
    }
}

的index.php

<?php

function do_stuff()
{
   require 'class.php';
   $obj = new MyClass;
   $obj->doSomething();
}

do_stuff();
do_stuff();

第二次調用do_stuff()會產生上面的錯誤。 通過將require改為require_once ,我們可以確定包含MyClass定義的文件只會被加載一次,並且會避免錯誤。




Warning: mysql_connect(): Access denied for user 'name'@'host'

This warning shows up when you connect to a MySQL/MariaDB server with invalid or missing credentials (username/password). So this is typically not a code problem, but a server configuration issue.

  • See the manual page on mysql_connect("localhost", "user", "pw") for examples.

  • Check that you actually used a $username and $password .

    • It's uncommon that you gain access using no password - which is what happened when the Warning: said (using password: NO) .
    • Only the local test server usually allows to connect with username root , no password, and the test database name.

    • You can test if they're really correct using the command line client:
      mysql --user="username" --password="password" testdb

    • Username and password are case-sensitive and whitespace is not ignored. If your password contains meta characters like $ , escape them, or put the password in single quotes .

    • Most shared hosting providers predeclare mysql accounts in relation to the unix user account (sometimes just prefixes or extra numeric suffixes). See the docs for a pattern or documentation, and CPanel or whatever interface for setting a password.

    • See the MySQL manual on Adding user accounts using the command line. When connected as admin user you can issue a query like:
      CREATE USER 'username'@'localhost' IDENTIFIED BY 'newpassword';

    • Or use Adminer or WorkBench or any other graphical tool to create, check or correct account details.

    • If you can't fix your credentials, then asking the internet to "please help" will have no effect. Only you and your hosting provider have permissions and sufficient access to diagnose and fix things.

  • Verify that you could reach the database server, using the host name given by your provider:
    ping dbserver.hoster.example.net

    • Check this from a SSH console directly on your webserver. Testing from your local development client to your shared hosting server is rarely meaningful.

    • Often you just want the server name to be "localhost" , which normally utilizes a local named socket when available. Othertimes you can try "127.0.0.1" as fallback.

    • Should your MySQL/MariaDB server listen on a different port, then use "servername:3306" .

    • If that fails, then there's a perhaps a firewall issue. (Off-topic, not a programming question. No remote guess-helping possible.)

  • When using constants like eg DB_USER or DB_PASSWORD , check that they're actually defined .

    • If you get a "Warning: Access defined for 'DB_USER'@'host'" and a "Notice: use of undefined constant 'DB_PASS'" , then that's your problem.

    • Verify that your eg xy/db-config.php was actually included and whatelse.

  • Check for correctly set GRANT permissions .

    • It's not sufficient to have a username + password pair.

    • Each MySQL/MariaDB account can have an attached set of permissions.

    • Those can restrict which databases you are allowed to connect to, from which client/server the connection may originate from, and which queries are permitted.

    • The "Access denied" warning thus may as well show up for mysql_query calls, if you don't have permissions to SELECT from a specific table, or INSERT / UPDATE , and more commonly DELETE anything.

    • You can adapt account permissions when connected per command line client using the admin account with a query like:
      GRANT ALL ON yourdb.* TO 'username'@'localhost';

  • If the warning shows up first with Warning: mysql_query(): Access denied for user ''@'localhost' then you may have a php.ini-preconfigured account/password pair .

    • Check that mysql.default_user= and mysql.default_password= have meaningful values.

    • Oftentimes this is a provider-configuration. So contact their support for mismatches.

  • Find the documentation of your shared hosting provider:

  • Note that you may also have depleted the available connection pool . You'll get access denied warnings for too many concurrent connections. (You have to investigate the setup. That's an off-topic server configuration issue, not a programming question.)

  • Your libmysql client version may not be compatible with the database server. Normally MySQL and MariaDB servers can be reached with PHPs compiled in driver. If you have a custom setup, or an outdated PHP version, and a much newer database server, or significantly outdated one - then the version mismatch may prevent connections. (No, you have to investigate yourself. Nobody can guess your setup).

More references:

Btw, you probably don't want to use mysql_* functions anymore . Newcomers often migrate to mysqli , which however is just as tedious. Instead read up on PDO and prepared statements .
$db = new PDO("mysql:host=localhost;dbname=testdb", "username", "password");




注意:未定義的索引

當您嘗試通過數組中不存在的鍵訪問數組時,會發生。

Undefined Index通知的典型示例是( demo

$data = array('foo' => '42', 'bar');
echo $data['spinach'];
echo $data[1];

spinach1都不存在於陣列中,導致E_WARNING被觸發。

解決方案是確保索引或偏移量在訪問該索引之前存在。 這可能意味著您需要修復程序中的錯誤,以確保這些索引在您期望的時候確實存在。 或者這可能意味著您需要使用array_key_existsisset來測試索引是否存在:

$data = array('foo' => '42', 'bar');
if (array_key_exists('spinach', $data)) {
    echo $data['spinach'];
}
else {
    echo 'No key spinach in array';
}

如果你有這樣的代碼:

<?php echo $_POST['message']; ?>
<form method="post" action="">
    <input type="text" name="message">
    ...

那麼當第一次加載這個頁面時, $_POST['message']不會被設置,你將會得到上述錯誤。 只有在提交表單並且第二次運行此代碼時,數組索引才存在。 你通常用以下方法檢查:

if ($_POST)  ..  // if the $_POST array is not empty
// or
if ($_SERVER['REQUEST_METHOD'] == 'POST') ..  // page was requested with POST

相關問題:




警告: [功能] :未能打開流: [原因]

當你通常通過includerequirefopen調用一個文件並且PHP找不到該文件或沒有足夠的權限來加載文件時,就會發生這種情況。

這可能由於各種原因而發生:

  • 文件路徑是錯誤的
  • 文件路徑是相對的
  • 包含路徑是錯誤的
  • 權限限制太多
  • SELinux正在生效
  • 還有很多 ...

一個常見的錯誤是不使用絕對路徑。 這可以通過使用完整路徑或魔術常量(__DIR__dirname(__FILE__)輕鬆解決:

include __DIR__ . '/inc/globals.inc.php';

要么:

require dirname(__FILE__) . '/inc/globals.inc.php';

確保使用正確的路徑是解決這些問題的一個步驟,這也可能與不存在的文件,防止訪問的文件系統權限或PHP本身打開的基於文件限制有關。

快速解決此問題的最佳方法是遵循下面的故障排除檢查表。

相關問題:

相關錯誤:




Fatal error: [TraitA] and [TraitB] define the same property ([$x]) in the composition of [ClassC]

Occurs when a class attempts to use multiple Traits , where two or more of those Traits have defined a property by the same name, and with the property having differing initial values.

例:

<?php
trait TraitA
{
    public $x = 'a';
}
trait TraitB
{
    public $x = 'b';
}
class ClassC
{
    use TraitA, TraitB;
}

Problematic: While it's possible to resolve conflicts between competing methods , there is currently no syntax that would resolve a conflict between two competing properties. The only solution at this time is to refactor ; ie, avoid a conflict between property names that produces a fatal error.

Related Questions:




MySQL:你的SQL語法有錯誤; 檢查與您的MySQL服務器版本相對應的手冊,以便在...附近使用正確的語法...

此錯誤通常是由於您忘記正確地轉義傳遞給MySQL查詢的數據而造成的。

該做什麼的例子(“糟糕的想法”):

$query = "UPDATE `posts` SET my_text='{$_POST['text']}' WHERE id={$_GET['id']}";
mysqli_query($db, $query);

此代碼可以包含在帶有表單的網頁中,並提供一個網址,例如http://example.com/edit.php?id=10 (編輯帖子n°10)

如果提交的文本包含單引號,會發生什麼? $query將結束於:

$query = "UPDATE `posts` SET my_text='I'm a PHP newbie' WHERE id=10';

當這個查詢被發送到MySQL時,它會抱怨語法錯誤,因為中間有一個額外的單引號。

為避免此類錯誤,您必須在查詢中使用之前始終轉義數據。

在SQL查詢中使用之前轉義數據也非常重要,因為如果您不這樣做,您的腳本將開放給SQL注入。 SQL注入可能導致更改,丟失或修改記錄,表或整個數據庫。 這是一個非常嚴重的安全問題!

文檔:




解析錯誤:語法錯誤,意外的T_VARIABLE

可能的情況

我似乎無法找到我的代碼出錯的地方。 這是我的完整錯誤:

解析錯誤:語法錯誤,第x行出現意外的T_VARIABLE

我在嘗試什麼

$sql = 'SELECT * FROM dealer WHERE id="'$id.'"';

回答

解析錯誤:與程序語法有關的問題,如在語句末尾留下分號,或者像上面的情況一樣,錯過了. 運營商。 解釋器遇到解析錯誤時會停止運行程序。

簡而言之,這是一個語法錯誤,這意味著代碼中的某些內容會阻止它正確解析並因此正在運行。

你應該做的是仔細檢查錯誤所在的地方,以便發現任何簡單的錯誤。

該錯誤消息意味著在文件的第x行中,PHP解釋器希望看到一個開放的括號,但是卻遇到了一個名為T_VARIABLE東西。 那T_VARIABLE東西被稱為token 。 這是PHP解釋器表達程序不同基本部分的方式。 當解釋程序讀入程序時,它會將您寫入的內容轉換為令牌列表。 無論你在程序中放置一個變量,解釋器列表中都有一個T_VARIABLE標記。

良好閱讀:解析器令牌列表

所以請確保您至少在您的php.ini啟用了E_PARSE 。 生產腳本中不應該存在解析錯誤。

我始終建議在編碼時添加以下語句:

error_reporting(E_ALL);

PHP錯誤報告

使用IDE可以讓您知道在輸入時解析錯誤,這也是一個好主意。 您可以使用:

  1. NetBeans (美好的和平,自由軟件)(在我看來是最好的)
  2. PhpStorm (舅舅戈登喜歡這樣:P,付費計劃,包含專有和免費軟件)
  3. Eclipse (美女與野獸,免費軟件)

相關問題:

  • 參考: PHP解析/語法錯誤; 以及如何解決它們?



Warning: Illegal string offset 'XXX'

This happens when you try to access an array element with the square bracket syntax, but you're doing this on a string, and not on an array, so the operation clearly doesn't make sense .

例:

$var = "test";
echo $var["a_key"];

If you think the variable should be an array, see where it comes from and fix the problem there.




致命錯誤:當不在對像上下文中時使用$ this

$this是PHP中的一個特殊變量,不能分配。 如果在不存在的上下文中訪問它,則會給出這個致命錯誤。

此錯誤可能會發生:

  1. 如果靜態調用非靜態方法。 例:

    class Foo {
       protected $var;
       public function __construct($var) {
           $this->var = $var;
       }
    
       public static function bar () {
           // ^^^^^^
           echo $this->var;
           //   ^^^^^
       }
    }
    
    Foo::bar();
    

    如何解決:再次檢查您的代碼, $this只能在對像上下文中使用,並且永遠不應該用於靜態方法。 另外,靜態方法不應該訪問非靜態屬性。 使用self::$static_property來訪問靜態屬性。

  2. 如果來自類方法的代碼已被複製到普通函數或全局範圍中保留$this特殊變量。
    如何解決:查看代碼並用另一個替換變量替換$this

相關問題:

  1. 調用非靜態方法為靜態: PHP致命錯誤:當不在對像上下文中時使用$ this
  2. 複製代碼: 致命錯誤:當不在對像上下文中時使用$ this
  3. 所有“當不在對像上下文中使用$ this”的問題



Warning: Division by zero

The warning message 'Division by zero' is one of the most commonly asked questions among new PHP developers. This error will not cause an exception, therefore, some developers will occasionally suppress the warning by adding the error suppression operator @ before the expression. 例如:

$value = @(2 / 0);

But, like with any warning, the best approach would be to track down the cause of the warning and resolve it. The cause of the warning is going to come from any instance where you attempt to divide by 0, a variable equal to 0, or a variable which has not been assigned (because NULL == 0) because the result will be 'undefined'.

To correct this warning, you should rewrite your expression to check that the value is not 0, if it is, do something else. If the value is zero you should not divide, or change the value to 1 and then divide so the division results in the equivalent of having divided only by the additional variable.

if ( $var1 == 0 ) { // check if var1 equals zero
    $var1 = 1; // var1 equaled zero so change var1 to equal one instead
    $var3 = ($var2 / $var1); // divide var1/var2 ie. 1/1
} else {
    $var3 = ($var2 / $var1); // if var1 does not equal zero, divide
}

Related Questions:




Related