An important note for everyone who's upgrading from PHP 5.4 and PHP 5.5, to PHP 5.6: the PHP default_charset in php.ini changed from "empty" to UTF-8, making UTF-8 the default charset in PHP. This may break HTML output if you try to set a different charset in your HTML head. It may also break functions like htmlentities() and htmlspecialchars. For example:

UTF-8 encoding breaks when upgrading PHP 5.6 to PHP 7.0, fix PHP with ini_set( 'default_charset', "" ); or in your php.ini with default_charset = "".

Breaking HTML output with PHP 5.6 default_charset changed to UTF-8

Suppose you have the following lines in PHP code (don't ask me why you would want to do this...):

<html> 
<head> 
<meta http-equiv="content-type"
  content="text/html; charset=ISO-8859-1"> 
</head>
<body> 
<?php echo "éééééeeeeééé"; ?>
</body> 
</html>

The PHP default charset setting in PHP 5.4 and PHP 5.5 prints the expected string on the screen: éééééeeeeééé.

In PHP 5.6 however, the default_charset is set to UTF-8, changing PHP's default charset, and PHP 5.6 will always print a Content-Type response header set to UTF-8:

Content-Type: text/html; charset=UTF-8

The PHP default charset set to UTF-8 breaks HTML output and functions like htmlentities() / htmlspecialchars() (PHP bug #61354), because the HTML charset ISO-8859-1 is printed too (creating a double Content-Type response header):

GET -uUsSed http://www.example.com/echo.php
GET http://www.example.com/echo.php
User-Agent: lwp-request/2.07

GET http://www.example.com/echo.php --> 200 OK
Cache-Control: private
Date: Tue, 31 Mar 2015 12:03:50 GMT
Server: Microsoft-IIS/8.0
Content-Length: 141
Content-Type: text/html; charset=UTF-8
Content-Type: text/html; charset=ISO-8859-1
Client-Date: Tue, 31 Mar 2015 12:03:50 GMT
Client-Peer: 77.94.251.244:80
Client-Response-Num: 1

PHP.net writes:

If omitted, the default value of the encoding varies depending on the PHP version in use. In PHP 5.6 and later, the default_charset configuration option is used as the default value. PHP 5.4 and 5.5 will use UTF-8 as the default. Earlier versions of PHP use ISO-8859-1.

Although this argument is technically optional, you are highly encouraged to specify the correct value for your code if you are using PHP 5.5 or earlier, or if your default_charset configuration option may be set incorrectly for the given input.

PHP.net htmlspecialchars()

How to fix the HTML output in PHP 5.6 - and up (7.0, 7.1)

The most obvious solution to this problem is: don't set a character set encoding in your HTML meta tag, e.g:

<meta http-equiv="content-type"
  content="text/html; charset=ISO-8859-1">

Other options to set a correct default character set (default_charset) are:

Create an user-defined php.ini to overrule default_charset directive

PHP supports user-defined php.ini files, in which you can overrule some php.ini settings. Neat! Upload your user-defined php.ini to your webroot containing the following line:

default_charset = ""

This will tell PHP to not send a Content-Type response header set to UTF-8.

Overrule PHP's default_charset with ini_set()

And last but not least, you can overrule this setting with PHP's ini_set() function:

ini_set( 'default_charset', "" );
Donate a cup of coffee
Donate a cup of coffee

Thank you very much! <3 ❤️

12 Comments

  1. Mihail

    thank so much!

  2. Boris

    Great post thank so much!

  3. Flaviu

    Great! Thanks for the tip.

  4. Terratroz

    Thank you

  5. Palle

    Thanks but it should be:

    ini_set(‘default_charset’, ”);
    or
    ini_set(‘default_charset’, ‘none’);

    or you get an PHP Notice: Use of undefined constant default_charset – assumed ‘default_charset’

    • Well spotted Palle, thank you! The single quotes somehow got lost in that last piece of code, I’ve added them again.

  6. Anonymous

    Thank you!!

  7. Anonymous

    In PHP 7.0.19, the empty value of the default_charset directive (default_charset = “”) causes an error HTTP 500 “Internal Server Error”.
    You can solve this problem by setting the value to “none”. For example:
    php_value default_charset = none
    or
    php_value default_charset = “none”
    or
    php_value default_charset = ‘none’

    • Thanks! I’m about to set up PHP 7.0.20 (had to skip 7.0.19, now running .18) so I’ll keep this in mind and reply with my findings if necessary.

    • Abdulla Saeed

      Thanks you ……
      I was searching about 2 days
      I used default_charset = “none”
      It Solved my php v7.4.4 application
      because i used iconv(‘windows-1256′,’utf-8’, $windowsArabicFileName )

      $windowsArabicFileName = “اسم ملف بالعربي.ppt”

  8. RemBem

    Thank you, this saved my day, fixing an old site suddenly full of questionmarks after upgrading php. All your other website performance articles are also very helpful!

Comments are closed