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.
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.
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.
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:
$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:
$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:
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!"
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.
In a few cases, PHP will sometimes suggest the wrong thing. For example, take this line of code:
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.
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:
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).
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:
$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.
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.
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.
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".
HEADER / HTTP ERRORS
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.
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.
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 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.
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.
Again, you can use ob_start() to enable output buffering as a quick fix:
<?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:
<?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).
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:
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 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.
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:
myclass.php
class MyClass
{
...
}
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:
$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:
$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:
$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!
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:
$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:
$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 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).
A common beginner's question is, "My computer has many gigabytes of RAM - why doesn't PHP just use it?"
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.
A temporary solution for this problem can be to either:
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:
$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).
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
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...
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.
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.
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:
$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:
$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.
Copyright © 2018 - Jonathan Hilgeman. All Rights Reserved.
Have a question about something in this article? You can receive help directly from the article author. Sign up for a free trial to get started.
Comments (1)
Commented: