php常见的难点和解决方案
There's a good chance you came across this article because you Googled for a PHP error message, but learning how to READ the errors yourself will make you a faster, more efficient developer, so here's a breakdown of the most common errors you'll come across in PHP development, and how to immediately find and fix the problem yourself.
您碰到这篇文章的机会很大,因为您在Google上搜索了一条PHP错误消息,但是学习如何自己读取错误将使您成为更快,更高效的开发人员,所以这里列出了您遇到的最常见错误在PHP开发中,以及如何立即发现并解决问题。
GENERAL SYNTAX ERRORS
一般语法错误
This error happens all the time, and the "unexpected" character will change depending on your situation. To understand this error, imagine you're reading a book.
此错误始终发生,并且“意外”字符将根据您的情况而变化。 要了解此错误,请想象您正在读一本书。
Without realizing it, your brain is connecting all these different words in the book together to form sentences and ideas. You read a description like "red apple" and your brain says, "These words are in the correct order and 'red' is referring to the color of the 'apple'." This process of reading something and then analyzing the words into purposes ("red" describing "apple", which is an object) is called parsing.
如果没有意识到这一点,您的大脑会将书中所有这些不同的单词连接在一起以形成句子和构想。 您读到类似“红苹果”的描述,大脑说:“这些词的顺序正确,'红色'指的是'苹果'的颜色。” 读取某些内容然后将这些单词分析为目的的过程(“红色”表示对象“ apple”)称为解析 。
Now let's say you were reading this sentence:
现在,假设您正在阅读以下句子:
"George stepped out of the shadows and then he purple."
“乔治走出阴影,然后他紫了。”
Your brain stops and says, "What the... purple? The way the sentence was going, I expected the next word to be some kind of action or verb... but 'purple' doesn't belong there!"
你的大脑停了下来,说道:“什么……紫色?句子的前进方式,我希望下一个单词是某种动作或动词……但'紫色'不属于那里!”
This is exactly what PHP is saying when you get this error. Basically, it's reading and parsing your code, and it's expecting to see something in your code, but instead, it finds some character that it didn't expect - something that doesn't quite make sense, given the code that comes BEFORE the unexpected character.
当您收到此错误时,这正是PHP所说的。 基本上,它正在读取和解析您的代码,并且期望看到您的代码中的某些内容,但是,相反,它找到了一些意料之外的字符-考虑到之前出现的代码,这并没有多大意义字符。
Let's say we get this error:
假设我们收到此错误:
Parse error: syntax error, unexpected ';' in your_script_file.php on line 2
Opening up your_script_file.php, we look at line 2 and see this:
打开your_script_file.php,我们看一下第2行,并看到以下内容:
$my_variable = ("123";
We then locate the "unexpected" character, which is the semicolon ; and then work BACKWARDS from right to left from there. So PHP is expecting something, and it wasn't a semicolon, so we need to find out what it WAS expecting. We know the semicolon ends a line of code, so PHP obviously doesn't think the line of code is completely finished just yet. This means we look for things that started but did not end. In this case, we can see that there's an unmatched, opening parentheses before our string. So PHP is expecting that parentheses to close before it can finish the line of code. So the fix would be to add a ")" right before the semi-colon:
然后,我们找到“意外”字符,即分号; 然后从右到左从左向后工作。 因此,PHP期望的东西不是分号,因此我们需要找出它期望的东西。 我们知道分号结束了一行代码,因此PHP显然不认为代码行还没有完全完成。 这意味着我们寻找开始但没有结束的事情。 在这种情况下,我们可以看到在字符串之前有一个不匹配的开括号。 因此,PHP期望在完成代码行之前括号会关闭。 因此解决方法是在分号之前添加“)”:
$my_variable = ("123");
Or, if the parentheses isn't needed, then another solution would be to remove the opening parentheses:
或者,如果不需要括号,则另一种解决方案是删除开头的括号:
$my_variable = "123";
Either way, we're ensuring that there is no unfinished code before the line ends.
无论哪种方式,我们都确保在行结束之前没有未完成的代码。
In some cases, PHP might be able to tell you specifically what it is expecting. Let's say we get this common variation of the same error:
在某些情况下,PHP也许可以告诉您具体的期望。 假设我们得到了相同错误的常见变化:
Parse error: syntax error, unexpected '=', expecting ']' in your_script_file.php on line 2
We go to line 2 in that file and see:
我们转到该文件的第二行,然后看到:
$my_array[123 = "Hello World";
So we find the unexpected "=" character and again we work backwards, looking at the code that is leading up to it, and we see that we're in the middle of specifying the index / key of an array using the square brackets. We've got the opening bracket [ and a value of 123 for our index / key. PHP would reasonably expect that you're ready to give it the closing square bracket ], but instead it finds the = sign, so it says, "Hey, you forgot your ']' character before you moved onto the next part of the code!"
因此,我们找到了意外的“ =”字符,然后再次向后工作,查看导致该字符的代码,然后我们发现我们正在使用方括号指定数组的索引/键。 我们已经有了左括号[和索引/键的值123。 PHP会合理地期望您已经准备好将其放在方括号[]中,但是却找到了=号,因此它说:“嘿,在移至代码的下一部分之前,您忘记了']'字符。 !!”
The vast majority of these "unexpected" errors can be quickly and easily resolved by locating the unexpected character and then working backwards to see what PHP is expecting instead of the character that it found.
绝大多数的这些“意外”的错误可以通过定位意想不到的字符,然后向后工作,看看有什么PHP 期待 ,而不是它发现的字符快速,轻松地解决。
In a few cases, PHP will sometimes suggest the wrong thing. For example, take this line of code:
在某些情况下,PHP有时会提示错误的内容。 例如,采用以下代码行:
foreach($my_array as $key => val)
It results in:
结果是:
Parse error: syntax error, unexpected ')', expecting '[' in...
If we follow the basic instructions, we can start at the ")" at the end of the line and then work backwards and see that we forgot a $ sign in front of our "val" variable name. However, PHP gave a slightly-misleading error message because it thought that maybe you were trying to write some more advanced PHP code. It's rare that you get a misleading suggestion for the expected character, but it happens.
如果遵循基本说明,则可以从行末的“)”开始,然后向后工作,然后看到我们忘记了在“ val”变量名前面的$符号。 但是,PHP给出了一个稍微令人误解的错误消息,因为它认为您可能正在尝试编写一些更高级PHP代码。 很少有人会误以为是预期字符,但确实如此。
Let's look at one more common variation of the error:
让我们看一下错误的另一种常见变化:
Parse error: syntax error, unexpected end of file in your_script_file.php on line 4
If we go look at line 4, it's just the final line in the script - there's no code! But in almost every case, when you get this error, it's because you have an opening "{" curly brace that doesn't end, like this:
如果我们看一下第4行,那只是脚本中的最后一行-没有代码! 但是几乎在每种情况下,当您遇到此错误时,这是因为您有一个没有结束的“ {”花括号,例如:
foreach($my_array as $key => $val)
{
Alternatively, if we see this error:
或者,如果我们看到此错误:
Parse error: syntax error, unexpected '}', expecting end of file in...
...it almost always means we have too many closing } curly braces, like this:
...几乎总是意味着我们有太多的}花括号,例如:
foreach($my_array as $key => $val)
{
}}
Just remember, start by finding the unexpected value, and then work backwards and you'll find the problem every time.
请记住,从找到意外的值开始,然后向后工作,每次都会发现问题。
This is one of the most bizarre error messages because it's the Hebrew word for "double colon" (according to what I read once upon a time). Essentially, there's a variety of ways that this error can pop up, but it's usually due to a missing character of some kind. Think of it as another "unexpected character" type of error, because it is usually due to PHP seeing some code that could potentially be valid if the next part of the code was "::" (followed by something else).
这是最奇怪的错误消息之一,因为它是希伯来语中的“双冒号”(根据我曾经读过的内容)。 本质上,可以通过多种方式弹出此错误,但这通常是由于某种字符丢失所致。 可以将其视为另一种“意外字符”错误,因为它通常是由于PHP看到某些代码,如果代码的下一部分为“ ::”,则可能是有效的(后面接其他内容)。
More often than not, the scope resolution (the "::" you might use for something like referencing a static class property, like MyClass:$some_property) is actually not really what you were going for, and chances are that you just forgot a $ sign or you didn't close a curly brace around a variable embedded in a string. For example:
实际上,范围解析(可能会用于引用静态类属性(例如MyClass:$ some_property之类的东西)的“ ::”)实际上并不是您想要的,并且很可能您只是忘记了$符号,或者您没有关闭嵌入在字符串中的变量周围的花括号。 例如:
$x = "hello";
echo "{$x world!";
You can see that the valid, expected code should have been echo "{$x} world!", but that the } character was missing. Again, fix this how you would fix the other errors about unexpected characters - find the line number and start working backwards from the end of that line.
您可以看到有效的预期代码应该是echo“ {$ x } world!”,但是缺少}字符。 再次,解决此问题,如何解决与意外字符有关的其他错误-找到行号并从该行的末尾开始向后工作。
Let's move onto some other common errors...
让我们继续探讨其他一些常见错误...
THE UNDEFINED ERRORS
未定义的错误
These are all pretty straightforward errors, so this will be a quick section.
这些都是非常简单的错误,因此这是一个快速的部分。
This is an easy one. It simply means you tried to use a variable that doesn't exist. For example:
这是个简单的。 这只是意味着您尝试使用不存在的变量。 例如:
$My_variable_name = "Hello world!";
echo $my_variable_name;
Notice that the variable names do not match - the first line has an upper-case "M" in the variable name "My" instead of "my". So the first line is creating one variable and the second line is echo-ing a completely different variable which just happens to have a SIMILAR name. Usually, when you have this error, it's because you have a typo in one of your variable names, or maybe you're incorrectly assuming that a bit of code has been run that defines a variable.
请注意,变量名称不匹配-第一行在变量名称“ My”中使用大写字母“ M”,而不是“ my”。 因此,第一行正在创建一个变量,第二行正在回显一个完全不同的变量,该变量恰好具有相似的名称。 通常,当您遇到此错误时,这是因为您的一个变量名中有一个错字,或者您可能错误地假设已经运行了一些定义变量的代码。
This is a similar issue to the undefined variable error, with similar causes. Let's take a look at a code example:
这是与未定义的变量错误类似的问题,原因类似。 让我们看一个代码示例:
$example_array = array(
"hello" => "world",
"How" => "are you?"
);
echo $example_array["how"];
Again, we see a case-sensitive problem - the echo is trying access an array index called "how", but our array uses "How" with an uppercase "H", so the line with echo will fail and display that notice. If you ever get this error and you are CONVINCED that the index exists, then you can use print_r() to dump the contents of the array, which can often lead to understanding the reason.
再次,我们看到一个区分大小写的问题-echo正在尝试访问名为“ how”的数组索引,但是我们的数组使用“ How”和大写的“ H”,因此带有echo的行将失败并显示该通知。 如果您遇到此错误,并且确信该索引存在,则可以使用print_r()转储数组的内容,这通常会导致理解原因。
Usually, this happens because you've stored a function in some file and it hasn't been included, or you were removing some code but didn't clean it all up completely, or maybe you have a typo in your function name. No matter what, it's because you're calling a function that doesn't exist. Example:
通常,发生这种情况是因为您已将函数存储在某个文件中,但尚未包含该函数,或者您正在删除一些代码但没有完全清除所有代码,或者您的函数名中有错字。 无论如何,这是因为您正在调用一个不存在的函数。 例:
function do_my_bidding()
{
}
domybidding(); // Throws the error because we're missing the _ characters in the name.
This is almost always the result of a missing $ in front of a variable. For example:
这几乎总是导致变量前面缺少$的结果。 例如:
$hello = "world";
echo hello; // Notice: Use of undefined constant hello - assumed 'hello' in...
If PHP just sees something in the middle of code that looks like it should be treated like a value, then it will try to figure out whether you wanted a string, a constant, or a variable. Without a $ sign, it throws out the possibility of it being a variable, so it then checks to see if there's a constant with that name. If there's no constant, then it throws the warning and then assumes that you wanted the string, so in the above example, it would echo out the word "hello".
如果PHP只是在代码中间看到一些看起来像应该被视为值的东西,那么它将尝试找出您是想要字符串,常量还是变量。 如果没有$符号,它将排除它成为变量的可能性,因此它随后检查该名称是否存在常量。 如果没有常量,则它将引发警告,然后假定您想要该字符串,因此在上面的示例中,它将回显单词“ hello”。
HEADER / HTTP ERRORS
标头/ HTTP错误
To understand this, you need to understand some basics about how HTTP works. When a browser sends a request to the web server, it gets back a response that is made up of 2 parts. The first part is the HTTP header and the second part is the body / content. The header contains some basic information about the response, such as how long the response content is, the date the content was last modified, the server type, the date/time on the server, and it can also contain instructions to the browser, such as telling the browser to store some cookies or maybe redirect to another page.
要了解这一点,您需要了解有关HTTP工作原理的一些基础知识。 当浏览器向Web服务器发送请求时,它会返回由两部分组成的响应。 第一部分是HTTP 标头 ,第二部分是正文/内容 。 标头包含有关响应的一些基本信息,例如响应内容有多长时间,上次修改内容的日期,服务器类型,服务器上的日期/时间,还可以包含针对浏览器的指令,例如告诉浏览器存储一些cookie或重定向到另一个页面。
The content, on the other hand, is the normal stuff you see when you view the source of the page. For a web page, the content section of the response would contain HTML. For an image, the content section would contain the raw image bytes, and so on.
另一方面,内容是您在查看页面源代码时看到的普通内容。 对于网页,响应的内容部分将包含HTML。 对于图像,内容部分将包含原始图像字节,依此类推。
The rules for HTTP say that the HTTP headers all have to be together, and that a blank line will indicate the end of the headers and the start of the content. So a response basically looks like:
HTTP规则规定HTTP标头必须全部在一起,并且空行将指示标头的末尾和内容的开头。 因此,响应基本上如下所示:
HTTP Header
HTTP Header
HTTP Header
<blank line>
HTTP Content...
Now, when you use the header() line in PHP, or if you're using session_start(), then you're trying to tell PHP to modify/add the appropriate HTTP headers. However, the moment that any NON-header content is rendered (even a single white space or a blank line), then PHP assumes that you are finished modifying the headers, and so it will send the headers back to the browser, and then wait for you to finish the content. So once those headers are sent, you can't change them anymore, and THAT is what this error is about. Basically, to solve this, you have to find the non-header content and remove it, or re-order your code, or use a more drastic solution like output buffering (ob_start()) so that nothing is sent to the browser until everything is finished.
现在,当您在PHP中使用header()行时,或者在使用session_start()时,则试图让PHP修改/添加适当的HTTP标头。 但是,在呈现任何NON-header内容(甚至是单个空格或空白行)的那一刻,PHP便假定您已完成标题的修改,因此它将标题发送回浏览器,然后等待让您完成内容。 因此,一旦发送了这些标头,就无法再对其进行更改,这就是此错误的所在。 基本上,要解决此问题,您必须找到非标题内容并将其删除,或者对代码进行重新排序,或者使用更激烈的解决方案(例如输出缓冲(ob_start())),以便在所有内容发送给浏览器之前,不会发送任何内容完成。
Reproducing this issue is easy:
重现此问题很容易:
<?php
header("X-My-Header-1: hello"); // This will work okay.
?>
<?php
header("X-My-Header-2: world"); // This will cause the error.
?>
When we ended the first PHP block, we had some white space between that point and the start of the next PHP block, and that counts as CONTENT, so PHP will send (flush) the headers after the first one and when you try to modify the headers the second time, it will give you the warning since the headers have already been finished and sent.
当我们结束第一个PHP块时,在该点和下一个PHP块的开始之间有一定的空格,这算作CONTENT,因此PHP将在第一个PHP头之后以及您尝试修改时发送(刷新)标头第二次发送标头,因为标头已经完成并发送,它将向您发出警告。
Again, you can use ob_start() to enable output buffering as a quick fix:
同样,您可以使用ob_start()启用输出缓冲作为快速解决方案:
<?php
ob_start();
header("X-My-Header-1: hello"); // This will work okay.
?>
<?php
header("X-My-Header-2: world"); // This will now work.
?>
...but you should really review the pros and cons of output buffering before doing this. At a glance, output buffering will use up more memory and the browser won't be able to do any sort of incremental loading because it won't get anything at all from the server until ALL the headers and HTML content of the page has been generated. Usually the more appropriate fix is to simply eliminate the whitespace:
...但是在执行此操作之前,您应该真正查看输出缓冲的优缺点。 乍一看,输出缓冲将占用更多的内存,并且浏览器将无法执行任何类型的增量加载,因为在页面的所有标题和HTML内容都被获取之前,它将无法从服务器获得任何内容产生。 通常,更合适的解决方法是消除空白:
<?php
header("X-My-Header-1: hello"); // This will work okay.
header("X-My-Header-2: world"); // This will work okay, too.
?>
OBJECT-ORIENTED PROGRAMMING ERRORS
面向对象的编程错误
These two are almost the same error. They both occur when you try to use a regular variable as if it were an object:
这两个几乎是相同的错误。 当您尝试像使用对象一样使用常规变量时,它们都会发生:
$my_var = "Hello world";
echo $my_var->foo; // Notice: Trying to get property of non-object error
echo $my_var->bar(); // Fatal error: Call to a member function bar() on a non-object
So if you get that error and you THINK that $my_var should be an object, use something like var_dump() on it to inspect the value prior using it. Chances are that the variable may have been overwritten (e.g. it WAS an object but then some code changed it to a string or something). The "Call to a member function" error can also be due to a bad mysqli query when you're using the object-oriented style of mysqli (see further below).
因此,如果收到该错误,并且认为$ my_var应该是一个对象,请在使用它之前使用类似var_dump()之类的值来检查该值。 可能是该变量可能已被覆盖(例如,它曾经是一个对象,但是随后一些代码将其更改为字符串或其他内容)。 当您使用mysqli的面向对象样式时,“调用成员函数”错误也可能是由于mysqli查询错误所致(请参见下文)。
The most common root cause for this is either copying a function from a class or using $this in a static function/method, since $this is a special variable that can ONLY be used within the methods of a class instance:
最常见的根本原因是从类复制函数或在静态函数/方法中使用$ this,因为$ this是一个特殊变量,只能在类实例的方法中使用:
class Foo
{
public $message = "I'm foo!";
public function Hello()
{
echo $this->message;
}
public static function World()
{
echo $this->message;
}
}
$x = new Foo();
$x->Hello(); // I'm foo!
Foo::World(); // Fatal error: Using $this when not in object context
Bottom line, you should never use the variable $this unless you're inside a class method.
最重要的是,除非您在类方法中,否则永远不要使用变量$ this 。
This is a mostly simple one. You can only have one class with a given name, so this will produce the error:
这是一个最简单的方法。 您只能使用一个具有给定名称的类,这样会产生错误:
class Foo
{
}
class Foo // Fatal error: Cannot declare class Foo, because the name is already in use in...
{
}
Now, there is a slight exception to the rule. PHP supports namespaces, so you can have two different namespaces that have the same class name. If your application makes use of namespaces and you get this error, then you have two classes with the same name within the same namespace.
现在,该规则略有例外。 PHP支持名称空间,因此您可以拥有两个具有相同类名的不同名称空间。 如果您的应用程序使用了命名空间,并且出现此错误,则您在同一个命名空间中有两个具有相同名称的类。
One common cause of this error is using include() or require() instead of include_once() or require_once(). If you include() or require() a file containing a class definition more than once, then it's going to cause this problem. For example:
导致此错误的一个常见原因是使用include()或require()而不是include_once()或require_once()。 如果您的include()或require()包含一个类定义的文件不止一次,则将导致此问题。 例如:
myclass.php
myclass.php
class MyClass
{
...
}
index.php
index.php
include("myclass.php"); // <-- This defines MyClass
include("myclass.php"); // <-- This will trigger the problem since MyClass is already defined
This isn't necessarily an object-oriented error, but it's the same root cause as the above error. The only difference is that instead of having the same class name defined twice, you have the same function name defined twice. That's it.
这不一定是面向对象的错误,但与上述错误是相同的根本原因。 唯一的区别是您不必两次定义相同的类名,而是两次定义了相同的函数名。 而已。
DATABASE ERRORS
数据库错误
Database errors can be a little tricky, since many of them are alike and have some SMALL differences in their messages that make a BIG difference in their meaning.
数据库错误可能有点棘手,因为它们中的许多相似并且在消息中存在一些小差异,从而使含义大为不同。
The vast majority of the time, this is because your query failed. If query executed by mysql_query() or mysqli_query() ends up failing (e.g. an invalid table, or invalid syntax, etc...). Example:
在大多数情况下,这是因为查询失败。 如果由mysql_query()或mysqli_query()执行的查询最终失败(例如,无效的表或无效的语法等)。 例:
$conn = mysqli_connect("localhost","user","pass","db");
$results = mysqli_query($conn,"SELECT * FROM non_existent_table"); // The query fails, so $results is now false instead of a valid result
$row = mysqli_fetch_assoc($results); // This produces the warning.
Note that if you use the object-oriented style of the mysqli extension, then an invalid query will still return a false result, so when you try to call the fetch_assoc() method on the result (which is the boolean "false") , you will get the error about calling a member function on a non-object, since false is not an object:
请注意,如果您使用mysqli扩展的面向对象样式,则无效查询仍将返回错误结果,因此,当您尝试在结果上调用fetch_assoc()方法(即布尔值“ false”)时,您将得到关于在非对象上调用成员函数的错误,因为false不是对象:
$conn = new mysqli("localhost","user","pass","db");
$results = $conn->query("SELECT * FROM non_existent_table"); // The query fails, so $results is now false instead of a valid result
$row = $results->fetch_assoc(); // This produces the "Call to a member function fetch_assoc() on boolean" error.
This is an extremely common error these days, and it's almost always because people are updating their code to use the new mysqli extension instead of the old mysql extension. PHP can support multiple different database connections at the same time, and the old mysql extension syntax didn't force users to pick a specific database connection. If you didn't specify which database you wanted to query, the mysql extension would simply pick the last one you connected to:
这些天来这是一个非常普遍的错误,并且几乎总是因为人们正在更新他们的代码以使用新的mysqli扩展而不是旧的mysql扩展。 PHP可以同时支持多个不同的数据库连接,并且旧的mysql扩展语法没有强制用户选择特定的数据库连接。 如果您未指定要查询的数据库,则mysql扩展名将仅选择您连接到的最后一个数据库:
$connA = mysql_connect("serverA","user","pass");
$connB = mysql_connect("serverB","user","pass");
mysql_query("UPDATE some_table SET field=value");
In that example, server B would receive the UPDATE query, since it was the last one connected. This could be a serious problem if you wanted that UPDATE query to go to server A!
在该示例中,服务器B将收到UPDATE查询,因为它是最后一个连接的服务器。 如果您希望将UPDATE查询发送到服务器A,这可能是一个严重的问题!
The new mysqli extension requires you to specify the connection as the FIRST parameter of your mysqli_query(), so if you just do a search-and-replace on your code to change all instances of "mysql_" to "mysqli_", you will end up with this kind of code that produces the error:
新的mysqli扩展要求您将连接指定为mysqli_query()的FIRST参数,因此,如果仅对代码进行搜索和替换以将“ mysql_”的所有实例更改为“ mysqli_”,则将结束这种产生错误的代码:
$connA = mysqli_connect("serverA","user","pass");
$connB = mysqli_connect("serverB","user","pass");
mysqli_query("UPDATE some_table SET field=value"); // Warning: mysqli_query() expects at least 2 parameters, 1 given
The fix is simple - just specify the database connection as your first parameter:
修复很简单-只需指定数据库连接作为第一个参数即可:
$connA = mysqli_connect("serverA","user","pass");
$connB = mysqli_connect("serverB","user","pass");
mysqli_query($connA, "UPDATE some_table SET field=value");
Now PHP knows exactly which server to send the query to! You can also avoid this by using the object-oriented style of coding that the mysqli extension offers:
现在,PHP确切知道了将查询发送到哪个服务器! 您还可以通过使用mysqli扩展提供的面向对象的编码样式来避免这种情况:
$connA = new mysqli("serverA","user","pass","db");
$connB = new mysqli("serverB","user","pass","db");
$connA->query("UPDATE some_table SET field=value");
MEMORY ERRORS
内存错误
There's really only one common memory error, which is:
实际上只有一个常见的内存错误,即:
You can probably imagine why this occurs - PHP has run out of memory. To be clear, this is NOT saying that your computer has run out of memory.
您可能可以想象为什么会发生这种情况-PHP内存不足。 需要明确的是,这并不是说您的计算机内存不足。
PHP has its own internal memory limit, which is defined in the php.ini file and can be overridden in many cases with ini_set(). This limit used to be 8MB a long time ago, then it was upped to 16MB in PHP 5.2.0. Nowadays, the default memory_limit setting in PHP 7 and higher is 128MB. However, many popular software packages, like Wordpress, will have their own default limits that they will try to set, which might override that limit (WP has a 40MB default limit for regular sites, and 64MB default limit for multi-sites).
PHP有其自己的内部内存限制,该限制在php.ini文件中定义,在许多情况下可以使用ini_set()覆盖。 这个限制很久以前是8MB,然后在PHP 5.2.0中增加到16MB。 如今,PHP 7及更高版本中的默认memory_limit设置为128MB。 但是,许多流行的软件包(如Wordpress)将尝试设置其自己的默认限制,而这些默认限制可能会覆盖该限制(WP对常规站点的默认限制为40MB,对多站点的默认限制为64MB)。
A common beginner's question is, "My computer has many gigabytes of RAM - why doesn't PHP just use it?"
初学者经常遇到的一个问题是:“ 我的计算机上有许多GB的RAM-PHP为什么不仅仅使用它? ”
- First, you have to remember that PHP is most frequently used in a web server setup where many copies of PHP can be running at the same time. So if you had a situation where PHP needed several gigabytes of RAM, and you had multiple copies of the script running at the same time, you'd run into some other bigger problems, from reliability to performance.
首先,您必须记住,PHP是Web服务器设置中最常用的工具,在该服务器中,PHP的多个副本可以同时运行。 因此,如果您遇到PHP需要数GB的RAM,并且同时运行多个脚本副本的情况,那么您将遇到其他一些更大的问题,从可靠性到性能。
- Second, PHP scripts usually do not need gigabytes of memory to run. A few megabytes go a long way, and if your PHP scripts are using gigabytes of data, you're probably doing something wrong.
其次,PHP脚本通常不需要千兆字节的内存即可运行。 几兆字节会走很长一段路,如果您PHP脚本使用的是千兆字节的数据,则可能是您做错了什么。
- Third, PHP is still making the popular transition from 32-bit to 64-bit. For a long time, the most popular PHP configuration was 32-bit, which means it could only access a few gigabytes of memory, even if you had 8 or more gigabytes available. Nowadays, more people are going with 64-bit builds of PHP 7, which means you can access a lot more of the system memory, but just because you CAN doesn't mean you SHOULD. 第三,PHP仍在流行地从32位过渡到64位。 长期以来,最受欢迎PHP配置是32位,这意味着即使您有8 GB或更多的可用内存,它也只能访问几GB的内存。 如今,越来越多的人正在使用PHP 7的64位版本,这意味着您可以访问更多的系统内存,但是仅仅因为您可以这样做并不意味着您应该这样做。
Now, the common root causes of these errors stem from developers who aren't thinking in advance about how much memory their code might use up. For example, take this simple line of code:
现在,这些错误的常见根源来自开发人员,他们没有事先考虑他们的代码可能会消耗多少内存。 例如,使用以下简单的代码行:
$contents = file_get_contents("logfile.csv");
It reads the contents of the "logfile.csv" into memory, into a string variable called $contents. This works fine if logfile.csv is relatively small, like 100 megabytes or less. But what if logfile.csv is something that grows every day without anything that limits its size? Let's say that over time, it eventually grows to be 1 gigabyte in size, and suddenly, your PHP script starts throwing these memory errors, even though nobody has changed any code! It's because the file has finally reached a size where it is simply too big to be read into PHP's memory without exceeding PHP's memory limit.
它将“ logfile.csv”的内容读入内存,读入名为$ contents的字符串变量。 如果logfile.csv相对较小(例如100兆字节或更小),则此方法可以正常工作。 但是,如果logfile.csv每天都在增长,而没有任何限制其大小的东西怎么办? 假设随着时间的推移,它最终会增长到1 GB,突然,即使没有人更改任何代码,您PHP脚本也会开始引发这些内存错误! 这是因为文件最终达到的大小太大了,无法在不超出PHP内存限制的情况下将其读入PHP内存。
A temporary solution for this problem can be to either:
此问题的临时解决方案可以是:
- Increase the memory limit in either php.ini
or 增加任一php.ini中的内存限制
要么 - Use the PHP code: ini_set("memory_limit","1234M"), where "1234" is the number of megabytes you want as your new limit. 使用PHP代码: ini_set(“ memory_limit”,“ 1234M”) ,其中“ 1234”是要用作新限制的兆字节数。
However, never just apply this quick fix and walk away. If you're suddenly getting this error, increasing the memory limit means that it will probably happen again later. Eventually you will reach a point where you can't increase it any further, and by that time, you'll likely have a HUGE data problem on your hands.
但是, 永远不要仅应用此快速修复程序就走开。 如果突然出现此错误,则增加内存限制意味着以后可能会再次发生。 最终,您将无法再进一步增加它,到那时,您可能会遇到巨大的数据问题。
So if you're going to increase the memory limit in PHP, make sure you immediately start looking into a more permanent solution to the problem. For example, usually there's no point in reading an entire file into memory (unless you are a professional who knows exactly why you would do so). It's often more efficient to read a file in chunks. For example, if the previous example's logfile.csv was 2 gigabytes in size, you could read through the entire file like this:
因此,如果您要增加PHP中的内存限制,请确保立即开始寻找针对该问题的更永久的解决方案。 例如,通常没有必要将整个文件读到内存中(除非您是一个专业人士,他确切地知道为什么要这么做)。 批量读取文件通常更有效。 例如,如果上一个示例的logfile.csv大小为2 GB,则可以像这样读取整个文件:
$fp = fopen("logfile.csv","r");
while(!feof($fp))
{
$line = fgetcsv($fp);
}
fclose($fp);
...and chances are that you would never exceed 100k of memory usage, because the $line variable gets overwritten in each loop, so you would never have more than just one line of data in memory at any given time (and using fseek and ftell to jump around a file instantly can address most performance concerns with reading large files).
...并且很有可能您不会超过100k的内存使用量,因为$ line变量在每个循环中都会被覆盖,因此在任何给定时间(并且使用fseek和使用ftell立即跳转到文件可以通过读取大文件解决大多数性能问题。
Another root cause is trying to keep too much data in memory and/or not taking measures to properly cast it. For example, let's say that the logfile.csv file just contains a million numbers, like this:
另一个根本原因是试图在内存中保留太多数据和/或不采取措施正确地投射数据。 例如,假设logfile.csv文件仅包含一百万个数字,如下所示:
logfile.csv
logfile.csv
123
124
125
126
...etc...
If you used a file loop to simply read each line into an array, like this:
如果使用文件循环将每一行简单地读入数组,如下所示:
$numbers = array();
$fp = fopen("logfile.csv","r");
while(!feof($fp))
{
$numbers[] = fgets($fp);
}
fclose($fp);
...then you would end up with a million strings inside your array, like "123", "124", etc...
...那么您最终将在数组中放入一百万个字符串 ,例如“ 123”,“ 124”等。
For all PHP knows, it is simply a coincidence that all of the strings happen to contain numbers. A number in a string takes up more memory than the number itself. Unfortunately, PHP's simplicity comes at the cost of overall memory efficiency, so if you've worked in other languages where an integer takes up just a few bytes... well that's not the case here. Pretty much any and every variable has quite a bit of overhead that eats up close to 50 bytes, not counting the value itself. However, there's still a lot of efficiencies to be gained by casting a numeric string to an integer, for example. You can easily cut your memory usage in HALF or more by doing this in many cases.
就所有PHP所知,所有字符串恰巧都包含数字只是一个巧合。 字符串中的数字比数字本身占用更多的内存。 不幸的是,PHP的简单性是以牺牲整体内存效率为代价的,因此,如果您使用其他语言,其中整数仅占用几个字节,那么情况就不是这样了。 几乎所有变量都具有相当大的开销,这些开销占用了近50个字节,这还不算值本身。 但是,例如,通过将数字字符串转换为整数仍然可以获得很多效率。 在许多情况下,通过执行此操作,您可以轻松地减少一半或更多的内存使用量。
This can be pretty important if you're working with LOTS of data that has to be held in memory, but that's another article for another time.
如果要处理必须保存在内存中的大量数据,这可能非常重要,但这是另一篇文章。
IMPORTANT NOTE: The 64-bit version of PHP increases the amount of overhead for each variable, compared to the 32-bit version. So if you're moving from 32-bit to 64-bit (e.g. you're doing an upgrade from PHP 5 to PHP 7), don't just copy your old php.ini over, with its old memory limit. If you copy it over, make sure you increase the memory limit (if it's set) by about 30% to be safe.
重要说明:与32位版本相比,PHP的64位版本增加了每个变量的开销。 因此,如果您正在从32位升级到64位(例如,您正在从PHP 5升级到PHP 7),则不要仅仅复制旧的php.ini,并限制其旧的内存。 如果将其复制过来,请确保将内存限制(如果已设置)增加约30%,以确保安全。
OTHER ERRORS
其他错误
PHP takes care of a lot of data type conversions for you. For example, if you had the number 123 or the boolean value of true, you could echo them out like this:
PHP为您处理了许多数据类型转换。 例如,如果您具有数字123或布尔值true,则可以像这样回显它们:
$var = 123;
echo $var; // Works fine and outputs "123"
$var = true;
echo $var; // Works fine and outputs "1"
Whenever it CAN convert a simple value to a string, it will do it automatically when you try to treat that value as if it were a string. However, not every data type can be represented as a simple string. So when it comes to any of the more complex data types like objects, resources, or arrays, PHP will do its best, but will usually throw an error or display something unhelpful:
每当它可以将简单值转换为字符串时,当您尝试将该值视为字符串时,它将自动执行该操作。 但是,并非每种数据类型都可以表示为简单的字符串。 因此,当涉及到任何更复杂的数据类型(如对象,资源或数组)时,PHP会尽力而为,但通常会引发错误或显示无用的内容:
$var = array();
echo $var; // Notice: Array to string conversion in...
$var = fopen("some_existing_file","r");
echo $var; // Resource id ##
$var = new stdClass();
echo $var; // Catchable fatal error: Object of class stdClass could not be converted to string in...
And there you have it. There will be other variations and errors that you might come across, but these are by far the most common ones that I see every day.
那里有。 您可能还会遇到其他变化和错误,但这是我每天看到的最常见的变化和错误。
翻译自: https://www.experts-exchange.com/articles/32160/How-to-Fix-Just-About-Every-Common-PHP-Error.html
php常见的难点和解决方案