I am doing a tutorial and am getting this error:
Fatal error: Class ‘MySQLi’ not found (LONG URL) on line 8
The code on line 8 is:
$mysqli = new MySQLi($db_server, $db_user, $db_pass, $db_name);
I saw online someone said to see if it was turned on in my phpinfo(), but there wasn’t anything listed in there under for «mysqli».
Also, I am running PHP version 5.2.5
Dharman♦
31.1k25 gold badges86 silver badges137 bronze badges
asked Mar 20, 2009 at 16:04
4
Sounds like you just need to install MySQLi.
If you think you’ve done that and still have a problem, please post your operating system and anything else that might help diagnose it further.
kalehmann
4,8316 gold badges26 silver badges36 bronze badges
answered Mar 20, 2009 at 16:07
GregGreg
317k54 gold badges369 silver badges333 bronze badges
5
You can check if the mysqli libraries are present by executing this code:
if (!function_exists('mysqli_init') && !extension_loaded('mysqli')) {
echo 'We don\'t have mysqli!!!';
} else {
echo 'Phew we have it!';
}
answered Mar 21, 2009 at 21:12
karim79karim79
340k67 gold badges414 silver badges406 bronze badges
3
If you are on Ubuntu, run:
sudo apt-get install php-mysqlnd
And don’t forget to restart the php service after this (Apache or php-fpm depends on the setup).
answered Mar 20, 2014 at 6:35
anshumananshuman
3,4961 gold badge19 silver badges13 bronze badges
6
If you’re calling «new mysqli(..)» from within a class that is namespaced, you might see a similar error Fatal error: Class 'foo\bar\mysqli' not found in. The way to fix this is to explicitly set it to the root namespace with a preceding backslash like so:
<?php
$mysqli = new \MySQLi($db_server, $db_user, $db_pass, $db_name);
Dharman♦
31.1k25 gold badges86 silver badges137 bronze badges
answered Mar 9, 2015 at 2:06
alexkbalexkb
3,2162 gold badges30 silver badges30 bronze badges
1
In addition to uncommenting the php_mysqli.dll extension in php.ini, also uncomment the extension_dir directive in php.ini and specify your location:
extension_dir = "C:\software\php\dist\ext"
This made it work for me.
Sᴀᴍ Onᴇᴌᴀ
8,2188 gold badges36 silver badges58 bronze badges
answered Oct 22, 2010 at 19:16
catawampuscatawampus
1791 silver badge3 bronze badges
3
If you are on Docker…
Inside php-container RUN:
#docker-php-ext-install mysqli
#apachectl restart
answered Apr 24, 2020 at 13:22
reyquesonreyqueson
4791 gold badge8 silver badges10 bronze badges
0
My OS is Ubuntu. I solved this problem by using:
sudo apt-get install php5-mysql
answered Jul 15, 2014 at 2:23
1
How to Enable mysqli in php.ini
- Edit/uncomment by removing ‘;'(colon) the following config in php.ini:
1st (uncomment and add config):include_path = "C:\php\includes"2nd (uncomment):
extension_dir = "ext"3rd (uncomment and edit config):
extension=C:/PHP/ext/php_mysql.dll extension=C:/PHP/ext/php_mysqli.dll - Restart the IIS server
- Make sure that mysql is running on the system.
How to load php.ini file
- Rename any one of the file php.ini-production/php.ini-development to php.ini from C:\PHP(note now the extention will be ini i.e «php.ini»).
- After renaming to php.ini file restart server
- See the changes in http://localhost/phpinfo.php
Dharman♦
31.1k25 gold badges86 silver badges137 bronze badges
answered Jun 11, 2018 at 10:59
GaniGani
4221 gold badge8 silver badges16 bronze badges
- Open your PHP folder.
- Find php.ini-development and open it.
- Find
;extension=mysqli - delete the
;symbol - save file and change the file extension from php.ini-development to php.ini
- Restart the server and test the code:
if (!function_exists('mysqli_init') && !extension_loaded('mysqli')) {
echo 'We don\'t have mysqli!!!';
} else {
echo 'mysqli is installed';
}
- if it not working, change both extension_dir in php.ini from «ext» to «c:\php\ext»
and extension=mysqli to extension=php_mysqli.dll then test again
Remember to reset the server every time you test
Suraj Rao
29.4k11 gold badges94 silver badges103 bronze badges
answered Nov 11, 2020 at 12:12
AnjiAnji
5172 silver badges10 bronze badges
For anyone using docker, I ran into this issue, and resolved it by using my own Dockerfile instead of the php:fpm image:
FROM php:fpm
RUN docker-php-ext-install mysqli
answered Apr 17, 2020 at 19:09
bozdozbozdoz
12.6k7 gold badges67 silver badges96 bronze badges
Seems like problem with your installation.
- Have you installed MySQLi?
- Have you activated it in php.ini?
- Restarted Apache and/or PHP-FPM?
http://www.php.net/manual/en/mysqli.installation.php
mario
144k20 gold badges237 silver badges291 bronze badges
answered Mar 20, 2009 at 16:08
vartecvartec
131k36 gold badges219 silver badges244 bronze badges
The PHP zip includes most of the commonly used extensions (*.dll on windows such as php_mysqli.dll) under the \ext directory, however they are not enabled by default. You might be getting this Fatal Error when trying to use MySQLi:
( ! ) Fatal error: Uncaught Error: Class 'mysqli' not found in C:\myProject\ class.Database.php on line 24
To enable extensions, open php.ini (you might need to first copy php.ini-development as php.ini), and un-comment (or add) these two lines:
extension_dir = "ext"
And any particular extensions you are getting Fatal Errors for, i.e. for mysqli:
extension=mysqli
answered Mar 12, 2018 at 2:26
GriknokGriknok
3842 silver badges13 bronze badges
On a fresh install of PHP, remove ; before extension_dir in php.ini.
answered Mar 23, 2019 at 0:52
AndreiAndrei
1602 silver badges14 bronze badges
I thought I might help anybody with the same problem using Namesco servers.
I have been trying to fix this problem after moving a database from my local server on home pc to namesco. They would not assist they said it was a coding issue.
- However, it was simple to fix from their CPANEl LINUX hosting
interface. - Click on php.
- then click on php modules and from their list of preinstalled modules just click the box for mysqli.
- Then click save. (No need to change code if it worked(s) on another server.)
Unfortunately, their support articles were a waste of time. After reading this I went to admin interface with a new determination.
Dharman♦
31.1k25 gold badges86 silver badges137 bronze badges
answered Oct 25, 2017 at 15:51
All you have to do is go to the php.ini file and on line 926 (depending on version) delete #. It should look like this:
;extension=ldap
;extension=mbstring
;extension=exif
extension=mysqli
;extension=oci8_12c
;extension=odbc
Save the file and open console (cmd) as administrator. Go to the path Apache24 / bin and enter httpd -k restart. This command will restart your server. After that, refresh the page and everything should work.
answered Apr 14, 2021 at 8:58
oliosolios
697 bronze badges
Some distributions (such as Gentoo) support multiple installations of PHP, and you have to make sure you’re using one with mysqli installed and enabled.
On Gentoo, I had installed a new PHP (with the mysqli USE flag enabled), but I needed to activate the new version of PHP (since the old one must have been missing mysqli):
# eselect php list apache2
[1] php5.3 *
[2] php5.5
# eselect php set apache2 2
You have to run `/etc/init.d/apache2 restart' for the changes to take effect
# /etc/init.d/apache2 restart
answered Nov 16, 2013 at 1:55
Jared ThirskJared Thirsk
1,24717 silver badges17 bronze badges
I checked all above and it didn’t work for me,
There are some steps I found.
I used PHP Version 5.5.9-1ubuntu4.17 on Ubuntu 14.04
First check the folder
#ls /etc/php5/mods-available/
json.ini mcrypt.ini mysqli.ini mysql.ini mysqlnd.ini opcache.ini pdo.ini pdo_mysql.ini readline.ini xcache.ini
If it did not contain mysqli.ini, read other answer for installing it,
Open php.ini find extension_dir
In my case , I must set extension_dir = /usr/lib/php5/20121212
And restart apache2 : /ect/init.d/apache2 restart
answered Jul 18, 2016 at 8:03
vanduc1102vanduc1102
5,8071 gold badge47 silver badges43 bronze badges
on ubuntu:
sudo apt-get install php-mysql
sudo service apache2 restart
answered Jul 25, 2018 at 17:40
on Debian 10
apt install php-mysql
/etc/init.d/apache2 restart
answered Jan 2, 2020 at 20:44
Salvador RuedaSalvador Rueda
8552 gold badges7 silver badges15 bronze badges
I found a solution for this problem after a long analysing procedure.
After properly testing my php installation with the command line features I found out that the php is working well and could work with the mysql database. Btw. you can run code-files with php code with the command php -f filename.php
So I realized, it must something be wrong with the Apache.
I made a file with just the phpinfo() function inside.
Here I saw, that in the line
Loaded Configuration File
my config file was not loaded, instead there was mentioned (none).
Finally I found within the Apache configuration the entry
<IfModule php5_module>
PHPINIDir "C:/xampp/php"
</IfModule>
But I’ve installed the PHP 7 and so the Apache could not load the php.ini file because there was no entry for that.
I added
<IfModule php7_module>
PHPINIDir "C:/xampp/php"
</IfModule>
and after restart Apache all works well.
These code blocks above I found in my httpd-xampp.conf file. May it is somewhere else at your configuration.
In the same file I had changed before the settings for the php 7 as replacement for the php 5 version.
#
# PHP-Module setup
#
#LoadFile "C:/xampp/php/php5ts.dll"
#LoadModule php5_module "C:/xampp/php/php5apache2_4.dll"
LoadFile "C:/xampp/php/php7ts.dll"
LoadModule php7_module "C:/xampp/php/php7apache2_4.dll"
As you can see I have the xampp package installed but this problem was just on the Apache side.
Dharman♦
31.1k25 gold badges86 silver badges137 bronze badges
answered Nov 1, 2018 at 19:58
install
phpXX-extension by PHP.
In my FreeBSD’s case:
pkg install php74-extensions
Dharman♦
31.1k25 gold badges86 silver badges137 bronze badges
answered Jul 20, 2020 at 19:23
I’m using xampp and my problem was fixed once i rename:
extension_dir = "ext"
to
extension_dir = "C:\xampp\php\ext"
PS: Don’t forget to restart apache after making this change!
answered Sep 12, 2020 at 2:27
AndreiAndrei
1602 silver badges14 bronze badges
In php.ini :
extension_dir ="c:/wamp64/bin/php/php7.4.9/ext/"
Make sure the PHP version is correct.
Obsidian
3,7398 gold badges18 silver badges30 bronze badges
answered Sep 22, 2020 at 15:19
When I tried my PHP web app it was giving me the same error.
By googling I found out the MySQL plugin for the PHP server was missing with my installation. I am using Ubuntu, so when I tried MySQL plugin for PHP I found out 2 are there,
php-mysql and php<version>-mysql
I issued command — php --version in my terminal, I was having php7.4,
again I issued apt install php7.4-mysql
It worked.
answered Jul 9, 2021 at 3:35
Willey HuteWilley Hute
94913 silver badges18 bronze badges
If you tried all answers above and are still out of luck, then do check if the version numbers of the packages installed on your system really match:
apache2-mod_php7-7.4.33-150200.3.46.2.x86_64
php7-mysql-7.4.33-150200.3.46.2.x86_64
Once I had to do a manual installation from a different repo, which lead to certain libs not getting loaded (though their config was OK and their .ini files were getting parsed).
You can also try using
php -S <server_ip>:8080
to launch a test server and see if your missing module (mysqli) loads there. If it shows up in phpinfo there (and doesn’t in your regular configuration), then you at least know where to have a look at…
answered Apr 15 at 10:28
This issue can be also caused by the .htaccess file misconfiguration.
answered Sep 2, 2021 at 10:01
1685155616851556
2533 silver badges11 bronze badges
mysqli_error
(PHP 5, PHP 7, PHP 
mysqli::$error — mysqli_error — Возвращает строку с описанием последней ошибки
Описание
Объектно-ориентированный стиль
Процедурный стиль
mysqli_error(mysqli $mysql): string
Возвращаемые значения
Строка с описанием ошибки. Пустая строка, если ошибки нет.
Примеры
Пример #1 Пример с $mysqli->error
Объектно-ориентированный стиль
<?php
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");/* Проверить соединение */
if ($mysqli->connect_errno) {
printf("Соединение не удалось: %s\n", $mysqli->connect_error);
exit();
}
if (!
$mysqli->query("SET a=1")) {
printf("Сообщение ошибки: %s\n", $mysqli->error);
}/* Закрыть соединение */
$mysqli->close();
?>
Процедурный стиль
<?php
$link = mysqli_connect("localhost", "my_user", "my_password", "world");/* Проверить соединение */
if (mysqli_connect_errno()) {
printf("Соединение не удалось: %s\n", mysqli_connect_error());
exit();
}
if (!
mysqli_query($link, "SET a=1")) {
printf("Сообщение ошибки: %s\n", mysqli_error($link));
}/* Закрыть соединение */
mysqli_close($link);
?>
Результат выполнения данных примеров:
Сообщение ошибки: Unknown system variable 'a'
Смотрите также
- mysqli_connect_errno() — Возвращает код ошибки последней попытки соединения
- mysqli_connect_error() — Возвращает описание последней ошибки подключения
- mysqli_errno() — Возвращает код ошибки последнего вызова функции
- mysqli_sqlstate() — Возвращает код состояния SQLSTATE последней MySQL операции
information at saunderswebsolutions dot com ¶
17 years ago
The mysqli_sql_exception class is not available to PHP 5.05
I used this code to catch errors
<?php
$query = "SELECT XXname FROM customer_table ";
$res = $mysqli->query($query);
if (!
$res) {
printf("Errormessage: %s\n", $mysqli->error);
}?>
The problem with this is that valid values for $res are: a mysqli_result object , true or false
This doesn't tell us that there has been an error with the sql used.
If you pass an update statement, false is a valid result if the update fails.
So, a better way is:
<?php
$query = "SELECT XXname FROM customer_table ";
$res = $mysqli->query($query);
if (!
$mysqli->error) {
printf("Errormessage: %s\n", $mysqli->error);
}?>
This would output something like:
Unexpected PHP error [mysqli::query() [<a href='function.query'>function.query</a>]: (42S22/1054): Unknown column 'XXname' in 'field list'] severity [E_WARNING] in [G:\database.php] line [249]
Very frustrating as I wanted to also catch the sql error and print out the stack trace.
A better way is:
<?php
mysqli_report(MYSQLI_REPORT_OFF); //Turn off irritating default messages$mysqli = new mysqli("localhost", "my_user", "my_password", "world");$query = "SELECT XXname FROM customer_table ";
$res = $mysqli->query($query);
if (
$mysqli->error) {
try {
throw new Exception("MySQL error $mysqli->error <br> Query:<br> $query", $msqli->errno);
} catch(Exception $e ) {
echo "Error No: ".$e->getCode(). " - ". $e->getMessage() . "<br >";
echo nl2br($e->getTraceAsString());
}
}//Do stuff with the result
?>
Prints out something like:
Error No: 1054
Unknown column 'XXname' in 'field list'
Query:
SELECT XXname FROM customer_table
#0 G:\\database.php(251): database->dbError('Unknown column ...', 1054, 'getQuery()', 'SELECT XXname F...')
#1 G:\data\WorkSites\1framework5\tests\dbtest.php(29): database->getString('SELECT XXname F...')
#2 c:\PHP\includes\simpletest\runner.php(58): testOfDB->testGetVal()
#3 c:\PHP\includes\simpletest\runner.php(96): SimpleInvoker->invoke('testGetVal')
#4 c:\PHP\includes\simpletest\runner.php(125): SimpleInvokerDecorator->invoke('testGetVal')
#5 c:\PHP\includes\simpletest\runner.php(183): SimpleErrorTrappingInvoker->invoke('testGetVal')
#6 c:\PHP\includes\simpletest\simple_test.php(90): SimpleRunner->run()
#7 c:\PHP\includes\simpletest\simple_test.php(498): SimpleTestCase->run(Object(HtmlReporter))
#8 c:\PHP\includes\simpletest\simple_test.php(500): GroupTest->run(Object(HtmlReporter))
#9 G:\all_tests.php(16): GroupTest->run(Object(HtmlReporter))
This will actually print out the error, a stack trace and the offending sql statement. Much more helpful when the sql statement is generated somewhere else in the code.
se (at) brainbits (dot) net ¶
17 years ago
The decription "mysqli_error -- Returns a string description of the LAST error" is not exactly that what you get from mysqli_error. You get the error description from the last mysqli-function, not from the last mysql-error.
If you have the following situation
if (!$mysqli->query("SET a=1")) {
$mysqli->query("ROLLBACK;")
printf("Errormessage: %s\n", $mysqli->error);
}
you don't get an error-message, if the ROLLBACK-Query didn't failed, too. In order to get the right error-message you have to write:
if (!$mysqli->query("SET a=1")) {
printf("Errormessage: %s\n", $mysqli->error);
$mysqli->query("ROLLBACK;")
}
callforeach at gmail dot com ¶
8 years ago
I had to set mysqli_report(MYSQLI_REPORT_ALL) at the begin of my script to be able to catch mysqli errors within the catch block of my php code.
Initially, I used the below code to throw and subsequent catch mysqli exceptions
<?php
try {
$mysqli = new mysqli('localhost','root','pwd','db');
if ($mysqli->connect_errno)
throw new Exception($mysqli->connect_error);
} catch (
Exception $e) {
echo $e->getMessage();
}I realized the exception was being thrown before the actual throw statement and hence the catch block was not being called.My current code looks like
mysqli_report(MYSQLI_REPORT_ALL) ;
try {
$mysqli = new mysqli('localhost','root','pwd','db');
/* I don't need to throw the exception, it's being thrown automatically */} catch (Exception $e) {
echo $e->getMessage();
}This works fine and I'm able to trap all mysqli errors
asmith16 at littlesvr dot ca ¶
9 years ago
Please note that the string returned may contain data initially provided by the user, possibly making your code vulnerable to XSS.
So even if you escape everything in your SQL query using mysqli_real_escape_string(), make sure that if you plan to display the string returned by mysqli_error() you run that string through htmlspecialchars().
As far as I can tell the two escape functions don't escape the same characters, which is why you need both (the first for SQL and the second for HTML/JS).
abderrahmanekaddour dot aissat at gmail dot com ¶
1 year ago
<?php// The idea is the add formated errors information for developers to easier bugs detection.$myfile = fopen("database_log.log", "r");
$db = new mysqli("localhost", "root","root","data");
if(!$db->query("SELECT")){
$timestamp = new DateTime();
$data_err = " {
\"title\": \" Select statement error \",
\"date_time\": ".$timestamp->getTimestamp().",
\"error\":\" ".$db->error." \"
} "; // Do more information
fwrite($myfile, $data_err); // writing data
}
// In separate file do file read and format it for good visual.$db->close();
fclose($myfile);
?>
information at saunderswebsolutions dot com ¶
17 years ago
Hi, you can also use the new mysqli_sql_exception to catch sql errors.
Example:
<?php
//set up $mysqli_instance here..
$Select = "SELECT xyz FROM mytable ";
try {
$res = $mysqli_instance->query($Select);
}catch (mysqli_sql_exception $e) {
print "Error Code <br>".$e->getCode();
print "Error Message <br>".$e->getMessage();
print "Strack Trace <br>".nl2br($e->getTraceAsString());
}?>
Will print out something like
Error Code: 0
Error Message
No index used in query/prepared statement select sess_value from frame_sessions where sess_name = '5b85upjqkitjsostvs6g9rkul1'
Strack Trace:
#0 G:\classfiles\lib5\database.php(214): mysqli->query('select sess_val...')
#1 G:\classfiles\lib5\Session.php(52): database->getString('select sess_val...')
#2 [internal function]: sess_read('5b85upjqkitjsos...')
#3 G:\classfiles\includes.php(50): session_start()
#4 G:\tests\all_tests.php(4): include('G:\data\WorkSit...')
#5 {main}
Anonymous ¶
3 years ago
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
try {
$this->connection = mysqli_connect($hostname,$username,$password, $dbname);
} catch (Exception $e) {
echo "Errno: " . mysqli_connect_errno() . PHP_EOL;
echo "Text error: " . mysqli_connect_error() . PHP_EOL;
exit;
}
Время на прочтение
11 мин
Количество просмотров 209K
Для кого это статья? Первоочередной целью написания статьи было именно «разложить все по полочкам» для тех, кто уже работал с mysqli, но не вникал глубоко, а быстренько написал свои обертки и забыл про оригинальный синтаксис. Я постарался разъяснить нюансы, с которым столкнулся сам, при переносе данных из большой и очень старой БД, спроектированной человеком, не знающим про нормализации, в новую, с сильно изменившейся структурой.
Можно ли читать эту статью людям, которые все еще используют старое расширение mysql и только думающие об перехода на PDO или MySqli? Думаю даже нужно.
MySqli или PDO
Последние годы я писал сайты исключительно на фреймворках, что избавляло меня от работы с БД напрямую. Некоторое время назад начал работу над сайтом на чистом php и задался вопросом, что использовать вместо устаревшего и нерекомендованного к использованию старого расширения PHP MySQL.
Выбирать нужно было между MySqli и PDO. После не очень длительного изучения решил остановиться на MySqli, так как, как мне тогда казалось, он полностью идентичен PDO, за исключением того, что нет возможности отказаться от MySQL в пользу чего-то другого. Как я напишу ниже это не совсем так, минимум одно заметное отличие есть.
MySqli рекомендован к использованию самими разработчиками PHP.[1]
ООП и процедурный интерфейс
MySqli позволяет писать код как в ООП стиле так и в процедурном. Мне ближе ООП как и большинству из хабр сообщества, поэтому в этом статье будет использован именно он.
Три основные класса
MySqli имеет 3 основные класса, которые будут подробно рассмотрены в этой статье
- mysqli — необходим для установки соединения с БД и будет полезен, если мы хотим выполнить запросы так, как мы это делали в старом расширении MySQL;
- mysqli_stmt — необходим для использования новой возможности MySqli: выполнять запросы по подготовленным выражениям;
- mysqli_result — объединяет функции для получения результатов запросов, сделанных с помощью mysqli или mysqli_stmt.
Рассмотрим каждый из них подробнее ниже.
Соединение с БД
Есть два способа.
Способ первый. Если вам нужно просто создать соединение.
$mysqli = new mysqli(‘localhost’, ‘my_user’, ‘my_password’, ‘my_db’);
if ($mysqli->connect_error) {
die(‘Connect Error (‘ . $mysqli->connect_errno . ‘) ‘ . $mysqli->connect_error);
}
Способ второй. Если вам нужно использовать опции соединения.
$mysqli = mysqli_init();
if (!$mysqli) {
die(‘mysqli_init failed’);
}if (!$mysqli->options(MYSQLI_INIT_COMMAND, ‘SET AUTOCOMMIT = 0’)) {
die(‘Setting MYSQLI_INIT_COMMAND failed’);
}if (!$mysqli->real_connect(‘localhost’, ‘my_user’, ‘my_password’, ‘my_db’)) {
die(‘Connect Error (‘ . $mysqli->connect_errno . ‘) ‘ . $mysqli->connect_error);
}
С помощью $mysqli->connect_errno и $mysqli->connect_error мы получаем описание и код ошибки, возникших при соединении. И new mysqli() и $mysqli->real_connect() при ошибках соединений вызывают ошибку PHP Warning. Поэтому вывод ошибок с помощью выше упомянутых функций имеет смысл, если у вас отключено отображение ошибок PHP, например, на рабочем сервере, либо если вам нужно как-то обработать эти данные. Я упомнил здесь об этом, потому что не все функции MySQLi вызывают PHP Warning в случае ошибки, и для того что бы узнать, что произошла ошибка необходимо обязательно обращаться к специальным функциям, об этом ниже.
Полученный при соединении объект мы присвоили переменной $mysqli, для того чтобы использовать его в дальнейшем. Это очевидно для ООП стиля, но и для процедурного стиля этот объект также необходим, в этом отличие от устаревшего расширения MySQL, где ссылку на соединение необязательно было передавать при каждом использовании mysql функций.
Буферизированные и не буферизированные результаты
Прежде чем рассказывать дальше, хотелось бы объяснить разницу между этими двумя типами результатов.
Рассмотрим небуферизированный результат. В этом случае вы можете начинать читать результаты, не дожидаясь пока mysql сервер получит результат полностью.
Преимущества:
- Результат можно начинать читать раньше, сокращается время ожидания;
- Результат не занимает место в оперативной памяти.
Недостатки:
- Невозможно узнать, сколько строк получено;
- Невозможно передвигаться к определенному результату, то есть можно читать данные только с начала и по порядку;
- Нельзя выполнять других запросов, пока не закрыт этот результат.
Буферизированный результат лишен этих недостатков и соответственно лишен перечисленных преимуществ.
«Классические» запросы
В MySqli оставили возможность «классических» запросов: когда пользователю предлагается самостоятельно заниматься безопасностью передаваемых запросов так, как это было в устаревшем расширении MySQL. Для этого предлагается использовать функцию $mysqli->real_escape_string(), с помощью которой необходимо обрабатывать все данные перед помещением их в запрос.
Так же как и с соединением есть два способа сделать такой запрос короткий и длинный.
Короткий.
$result = $mysqli->query(‘текст запроса’, MYSQLI_USE_RESULT);
Возможные константы:
MYSQLI_STORE_RESULT – вернет буферизированный результат, значение по умолчанию
MYSQLI_USE_RESULT – небуферизированный
Длинный.
$mysqli->real_query(‘текст запроса’);
echo($mysqli->field_count); // вернет количество столбцов, в результате,
// можно получить до начала получения результата, что дает дополнительную гибкость
// по сравнению c коротким способом, разумеется, вызывать не обязательно
$result = $mysqli->use_result(); // вернет небуферизированный результат
// или
$result = $mysqli->store_result(); // вернет буферизированный результат
Функции $mysqli->use_result() или $mysqli->store_result() так же используются при мульти запросах (запросах состоящих из нескольких запросов). Мульти запросы в этой статье рассмотрены не будут.
И тот и другой синтаксисы вернут результат в виде объекта mysqli_result, который представляет собой удобный интерфейс для работы с результатом, как с буферизированным так и не с небуферизированным.
Как я писал выше, не все функции MySQLi выбрасывают ошибки PHP, описанные выше функции из их числа. В случае если запрос неверный и сервер вернул ошибку, PHP не даст об этом знать. Для проверки используйте функции:
- $mysqli->error – описание ошибки
- $mysqli->errno – код ошибки
$city = $mysqli->real_escape_string($city);
$mysqli->query(«SELECT * FROM `city` WHERE `id` = ‘$city‘»);
if ($mysqli->errno) {
die(‘Select Error (‘ . $mysqli->errno . ‘) ‘ . $mysqli->error);
}
Преимущества «классического» синтаксиса запросов:
- Он значительно более компактен, чем подготовленные выражения (класс mysqli_stmt);
- Он позволяет получить небуферизированный результат в виде mysqli_result. Подготовленные выражения позволяют получить только буферизированный результат mysqli_result, а с небуферизированным придется работать средствами mysqli_stmt, который значительно менее гибкий, чем mysqli_result.
Практическое применение «классического» синтаксиса запросов я вижу:
- В не буферизированных запросах, если вам хочется использовать преимущества работы с mysqli_result;
- В запросах INSERT, UPDATE, REPLACE или DELETE, если для вас предпочтителен их более короткий синтаксис.
Для таких запросов будут полезны свойства:
- $mysqli->affected_rows – количество затронутых строк предыдущим запросом не на выборку
- $mysqli->insert_id – автоматически сгенерированный ID для последнего запроса вставки.
Подготовленные запросы
Преимущества подготовленных запросов над «классическими»:
- При серии запросов, в которых меняются лишь данные, запрос передается на сервер только один раз, в дальнейшем посылаются только изменяющиеся данные;
- Защита от SQL-инъекций.
За работу с подготовленными запросами в MySQLi отвечает класс mysqli_stmt.
Два способа создания подготовленного запроса.
// первый способ — используя объект mysqli
$mysqli->prepare(«SELECT * FROM `sk2_articles` WHERE `id` = ?»);
if ($mysqli->errno) {
die(‘Select Error (‘ . $mysqli->errno . ‘) ‘ . $mysqli->error);
}// второй способ — используя объект mysqli_stmt
$stmt = $mysqli->stmt_init();
$stmt->prepare(«SELECT * FROM `sk2_articles` WHERE `id` = ?»);
if ($stmt->errno) {
die(‘Select Error (‘ . $stmt->errno . ‘) ‘ . $stmt->error);
}
Различия в том, для какого объекта вызываются функции получения информации об ошибке. Мне второй способ кажется удобнее, потому что проверки на ошибки можно объединить в один блок if c другими функциями mysqli_stmt. Как это сделать будет видно в примерах ниже.
$id_min = 81;
$id_max = 88;
$stmt = $mysqli->stmt_init();
if(
// подготовливаем запрос, там куда будут вствлятся данные отмечаем символом ? (плейсхолдоры)
($stmt->prepare(«SELECT title FROM sk2_articles WHERE id > ? and id < ?») ===FALSE)
// привязываем переменные к плейсхолдорам
or ($stmt->bind_param(‘ii’, $id_min, $id_max) === FALSE)
// отрправляем даные, которые на данный момент находятся в привязанных переменных
or ($stmt->execute() === FALSE)
// привязывем переменую для получения в нее результата
or ($stmt->bind_result($title) === FALSE)
// делаем запрос буферизированным,
// если бы этой строки не было, запрос был бы небуферезированым
or ($stmt->store_result() === FALSE)
// получение результата в привязанную переменную
or ($stmt->fetch() === FALSE)
// закрываем подготовленный запрос
or ($stmt->close() === FALSE)
) {
die(‘Select Error (‘ . $stmt->errno . ‘) ‘ . $stmt->error);
}
echo $title;
Несколько пояснений к выше написанному коду.
- В $stmt->bind_param() первым параметром указываем тип привязываемых данных (i – integer, d — double, s – строка). Вторым и последующим указываются переменные, которые будет привязаны к соответствующим плейсхолдорам, объявленным в $stmt->prepare() символами «?» в том порядке, в каком они указаны в $stmt->prepare(). Это заметное отличие от PDO, где плесхолдоры могут быть именованными, а значит не зависят от порядка объявления.
- $stmt->bind_result по-моему самое слабое место класса mysqli_stmt, так как оно обязывает знать, какие именно данные будут получены из запроса и каком порядке они объявлены в запросе. Для случая “SELECT * FROM …” он вряд ли применим. Гораздо более гибкий подход в работе с результатом предлагает класс mysqli_result. Чтобы быть окончательно объективным, стоит упомянуть, что можно воспользоваться функцией $stmt->result_metadata() получить mysqli_result содержащий только о метаданные без самих данных, и посмотреть что за столбцы получены, но этот подход мне кажется излишне сложным, и о нем я упомянул только, чтобы избежать обвинений в неточной информации.
- $stmt->store_result(), как я написал в комментарии к строке, необязательный и нужен для того, чтобы можно было использовать такие функции как:
- $mysqli_stmt->num_rows – количество полученных строк к результате,
- $stmt->data_seek – перемещение внутреннего указателя на заданную строку результата,
- $stmt->free_result() – и не забудьте вызвать освобождение памяти если вы использовали $stmt->store_result().
- $stmt->fetch() возвращает TRUE/FALSE если данные были получены удачно/неудачно, и NULL если данных больше нет.
- Не все функции, объединенные в блок if, в случае ошибки помещают ее в $stmt->error, некоторые вызывают PHP Warning, но все из них в случае неудачи возвращают FALSE, поэтому мне кажется эта конструкция удачной. Если вам нужно выполнить несколько раз $stmt->execute() или $stmt->fetch(), то так сделать не получится.
- Не зависимо от того, был ли запрос буферизированный или нет, доступны следующие свойства:
- $stmt->field_count — количество столбцов в результате,
- $stmt->affected_rows – количество затронутых строк предыдущим запросом не на выборку,
- $stmt->insert_id – автоматически сгенерированный id предыдущей вставки.
Изменим код так, чтобы получить результат в виде экземпляра объекта mysqli_result.
$id_min = 81;
$id_max = 88;
$stmt = $mysqli->stmt_init();
if(
($stmt->prepare(«SELECT title FROM sx2_links WHERE id > ? and id < ?») === FALSE)
or ($stmt->bind_param(‘ii’, $id_min, $id_max) === FALSE)
or ($stmt->execute() === FALSE)
// получение буферизированного результата в виде mysqli_result,
// небуферизированный результат получить нельзя, о чем я писал в недостатках
or (($result = $stmt->get_result()) === FALSE)
or ($stmt->close() === FALSE)
) {
die(‘Select Error (‘ . $stmt->errno . ‘) ‘ . $stmt->error);
}
$row = $result->fetch_row();
echo $row[0];
Класс mysqli_result и работа с результатом с помощью него
Как было показано выше, объект mysqli_result вы могли получить как с помощью «классического» запроса с помощью класса mysqli, тогда он может быть как буферизированный так и небуферизированный, так и с помощью класса mysqli_stmt, тогда он буферизированный. От того какой результат вы получили, зависит работа функций этого класса, поэтому нужно хорошо понимать, что если ваш запрос небуферизированный вы не располагаете всем результатом и соответственно не можете знать сколько строк в результате, и читать его можно только по-порядку строка за строкой.
Набор функций в этом классе покажется знакомым по-старому расширения:
- $result->fetch_row() – получает текущий ряд результата в виде нумерованного массива,
- $result->fetch_assoc() – в виде ассоциативного массива,
- $result->fetch_array() – тип массива задается константой,
- MYSQLI_ASSOC – ассоциативный,
- MYSQLI_NUM – нумерованный,
- MYSQLI_BOTH – оба,
- $result->fetch_object() – строка результата в виде объекта.
Про $result->fetch_object() хотелось бы поговорить отдельно. У этой функции есть два параметра, оба необязательные:
- class_name – имя класса, на основе которого будет создан объект,
- params – массив параметров, которые будут переданы конструктору при создании объекта.
Как видите, передать конструктору класса предположим ассоциативный массив одной строки результата с помощью этой функции не получится. Она сама за вас присвоит свойствам класса, совпадающие с названиями полей результаты. Если свойства класса не будет найдено, оно создается динамически, с областью видимости public.
class Book
{
private $some1;
public $some2;
protected $id;function __construct($param1, $param2) {
$this->some1 = $param1;
$this->some2 = $param2;
}
}
$book = $result->fetch_object(‘Book’, array(1, 2));
var_dump( $book);
Выведет, если в результате было только одно поле id
object(Book)[4]
private ‘some1’ => int 1
public ‘some2’ => int 2
protected ‘id’ => int 382
Другие полезные функции и свойства рассматриваемого класса:
- $result->fetch_all() — получение всех рядов в виде массива нумерованного / ассоциативного / обоих типов ,
- $result->data_seek() — установка внутреннего указателя на заданный ряд результата,
- $result->num_rows – количество строк в результате.
Ссылки:
Страница MySQLi в официальной документации на php.net
Больше примеров по MySQLi
Список функций MySQLi на русском языке
I am doing a tutorial and am getting this error:
Fatal error: Class ‘MySQLi’ not found (LONG URL) on line 8
The code on line 8 is:
$mysqli = new MySQLi($db_server, $db_user, $db_pass, $db_name);
I saw online someone said to see if it was turned on in my phpinfo(), but there wasn’t anything listed in there under for «mysqli».
Also, I am running PHP version 5.2.5
Dharman♦
31.1k25 gold badges86 silver badges137 bronze badges
asked Mar 20, 2009 at 16:04
4
Sounds like you just need to install MySQLi.
If you think you’ve done that and still have a problem, please post your operating system and anything else that might help diagnose it further.
kalehmann
4,8316 gold badges26 silver badges36 bronze badges
answered Mar 20, 2009 at 16:07
GregGreg
317k54 gold badges369 silver badges333 bronze badges
5
You can check if the mysqli libraries are present by executing this code:
if (!function_exists('mysqli_init') && !extension_loaded('mysqli')) {
echo 'We don\'t have mysqli!!!';
} else {
echo 'Phew we have it!';
}
answered Mar 21, 2009 at 21:12
karim79karim79
340k67 gold badges414 silver badges406 bronze badges
3
If you are on Ubuntu, run:
sudo apt-get install php-mysqlnd
And don’t forget to restart the php service after this (Apache or php-fpm depends on the setup).
answered Mar 20, 2014 at 6:35
anshumananshuman
3,4961 gold badge19 silver badges13 bronze badges
6
If you’re calling «new mysqli(..)» from within a class that is namespaced, you might see a similar error Fatal error: Class 'foo\bar\mysqli' not found in. The way to fix this is to explicitly set it to the root namespace with a preceding backslash like so:
<?php
$mysqli = new \MySQLi($db_server, $db_user, $db_pass, $db_name);
Dharman♦
31.1k25 gold badges86 silver badges137 bronze badges
answered Mar 9, 2015 at 2:06
alexkbalexkb
3,2162 gold badges30 silver badges30 bronze badges
1
In addition to uncommenting the php_mysqli.dll extension in php.ini, also uncomment the extension_dir directive in php.ini and specify your location:
extension_dir = "C:\software\php\dist\ext"
This made it work for me.
Sᴀᴍ Onᴇᴌᴀ
8,2188 gold badges36 silver badges58 bronze badges
answered Oct 22, 2010 at 19:16
catawampuscatawampus
1791 silver badge3 bronze badges
3
If you are on Docker…
Inside php-container RUN:
#docker-php-ext-install mysqli
#apachectl restart
answered Apr 24, 2020 at 13:22
reyquesonreyqueson
4791 gold badge8 silver badges10 bronze badges
0
My OS is Ubuntu. I solved this problem by using:
sudo apt-get install php5-mysql
answered Jul 15, 2014 at 2:23
1
How to Enable mysqli in php.ini
- Edit/uncomment by removing ‘;'(colon) the following config in php.ini:
1st (uncomment and add config):include_path = "C:\php\includes"2nd (uncomment):
extension_dir = "ext"3rd (uncomment and edit config):
extension=C:/PHP/ext/php_mysql.dll extension=C:/PHP/ext/php_mysqli.dll - Restart the IIS server
- Make sure that mysql is running on the system.
How to load php.ini file
- Rename any one of the file php.ini-production/php.ini-development to php.ini from C:\PHP(note now the extention will be ini i.e «php.ini»).
- After renaming to php.ini file restart server
- See the changes in http://localhost/phpinfo.php
Dharman♦
31.1k25 gold badges86 silver badges137 bronze badges
answered Jun 11, 2018 at 10:59
GaniGani
4221 gold badge8 silver badges16 bronze badges
- Open your PHP folder.
- Find php.ini-development and open it.
- Find
;extension=mysqli - delete the
;symbol - save file and change the file extension from php.ini-development to php.ini
- Restart the server and test the code:
if (!function_exists('mysqli_init') && !extension_loaded('mysqli')) {
echo 'We don\'t have mysqli!!!';
} else {
echo 'mysqli is installed';
}
- if it not working, change both extension_dir in php.ini from «ext» to «c:\php\ext»
and extension=mysqli to extension=php_mysqli.dll then test again
Remember to reset the server every time you test
Suraj Rao
29.4k11 gold badges94 silver badges103 bronze badges
answered Nov 11, 2020 at 12:12
AnjiAnji
5172 silver badges10 bronze badges
For anyone using docker, I ran into this issue, and resolved it by using my own Dockerfile instead of the php:fpm image:
FROM php:fpm
RUN docker-php-ext-install mysqli
answered Apr 17, 2020 at 19:09
bozdozbozdoz
12.6k7 gold badges67 silver badges96 bronze badges
Seems like problem with your installation.
- Have you installed MySQLi?
- Have you activated it in php.ini?
- Restarted Apache and/or PHP-FPM?
http://www.php.net/manual/en/mysqli.installation.php
mario
144k20 gold badges237 silver badges291 bronze badges
answered Mar 20, 2009 at 16:08
vartecvartec
131k36 gold badges219 silver badges244 bronze badges
The PHP zip includes most of the commonly used extensions (*.dll on windows such as php_mysqli.dll) under the \ext directory, however they are not enabled by default. You might be getting this Fatal Error when trying to use MySQLi:
( ! ) Fatal error: Uncaught Error: Class 'mysqli' not found in C:\myProject\ class.Database.php on line 24
To enable extensions, open php.ini (you might need to first copy php.ini-development as php.ini), and un-comment (or add) these two lines:
extension_dir = "ext"
And any particular extensions you are getting Fatal Errors for, i.e. for mysqli:
extension=mysqli
answered Mar 12, 2018 at 2:26
GriknokGriknok
3842 silver badges13 bronze badges
On a fresh install of PHP, remove ; before extension_dir in php.ini.
answered Mar 23, 2019 at 0:52
AndreiAndrei
1602 silver badges14 bronze badges
I thought I might help anybody with the same problem using Namesco servers.
I have been trying to fix this problem after moving a database from my local server on home pc to namesco. They would not assist they said it was a coding issue.
- However, it was simple to fix from their CPANEl LINUX hosting
interface. - Click on php.
- then click on php modules and from their list of preinstalled modules just click the box for mysqli.
- Then click save. (No need to change code if it worked(s) on another server.)
Unfortunately, their support articles were a waste of time. After reading this I went to admin interface with a new determination.
Dharman♦
31.1k25 gold badges86 silver badges137 bronze badges
answered Oct 25, 2017 at 15:51
All you have to do is go to the php.ini file and on line 926 (depending on version) delete #. It should look like this:
;extension=ldap
;extension=mbstring
;extension=exif
extension=mysqli
;extension=oci8_12c
;extension=odbc
Save the file and open console (cmd) as administrator. Go to the path Apache24 / bin and enter httpd -k restart. This command will restart your server. After that, refresh the page and everything should work.
answered Apr 14, 2021 at 8:58
oliosolios
697 bronze badges
Some distributions (such as Gentoo) support multiple installations of PHP, and you have to make sure you’re using one with mysqli installed and enabled.
On Gentoo, I had installed a new PHP (with the mysqli USE flag enabled), but I needed to activate the new version of PHP (since the old one must have been missing mysqli):
# eselect php list apache2
[1] php5.3 *
[2] php5.5
# eselect php set apache2 2
You have to run `/etc/init.d/apache2 restart' for the changes to take effect
# /etc/init.d/apache2 restart
answered Nov 16, 2013 at 1:55
Jared ThirskJared Thirsk
1,24717 silver badges17 bronze badges
I checked all above and it didn’t work for me,
There are some steps I found.
I used PHP Version 5.5.9-1ubuntu4.17 on Ubuntu 14.04
First check the folder
#ls /etc/php5/mods-available/
json.ini mcrypt.ini mysqli.ini mysql.ini mysqlnd.ini opcache.ini pdo.ini pdo_mysql.ini readline.ini xcache.ini
If it did not contain mysqli.ini, read other answer for installing it,
Open php.ini find extension_dir
In my case , I must set extension_dir = /usr/lib/php5/20121212
And restart apache2 : /ect/init.d/apache2 restart
answered Jul 18, 2016 at 8:03
vanduc1102vanduc1102
5,8071 gold badge47 silver badges43 bronze badges
on ubuntu:
sudo apt-get install php-mysql
sudo service apache2 restart
answered Jul 25, 2018 at 17:40
on Debian 10
apt install php-mysql
/etc/init.d/apache2 restart
answered Jan 2, 2020 at 20:44
Salvador RuedaSalvador Rueda
8552 gold badges7 silver badges15 bronze badges
I found a solution for this problem after a long analysing procedure.
After properly testing my php installation with the command line features I found out that the php is working well and could work with the mysql database. Btw. you can run code-files with php code with the command php -f filename.php
So I realized, it must something be wrong with the Apache.
I made a file with just the phpinfo() function inside.
Here I saw, that in the line
Loaded Configuration File
my config file was not loaded, instead there was mentioned (none).
Finally I found within the Apache configuration the entry
<IfModule php5_module>
PHPINIDir "C:/xampp/php"
</IfModule>
But I’ve installed the PHP 7 and so the Apache could not load the php.ini file because there was no entry for that.
I added
<IfModule php7_module>
PHPINIDir "C:/xampp/php"
</IfModule>
and after restart Apache all works well.
These code blocks above I found in my httpd-xampp.conf file. May it is somewhere else at your configuration.
In the same file I had changed before the settings for the php 7 as replacement for the php 5 version.
#
# PHP-Module setup
#
#LoadFile "C:/xampp/php/php5ts.dll"
#LoadModule php5_module "C:/xampp/php/php5apache2_4.dll"
LoadFile "C:/xampp/php/php7ts.dll"
LoadModule php7_module "C:/xampp/php/php7apache2_4.dll"
As you can see I have the xampp package installed but this problem was just on the Apache side.
Dharman♦
31.1k25 gold badges86 silver badges137 bronze badges
answered Nov 1, 2018 at 19:58
install
phpXX-extension by PHP.
In my FreeBSD’s case:
pkg install php74-extensions
Dharman♦
31.1k25 gold badges86 silver badges137 bronze badges
answered Jul 20, 2020 at 19:23
I’m using xampp and my problem was fixed once i rename:
extension_dir = "ext"
to
extension_dir = "C:\xampp\php\ext"
PS: Don’t forget to restart apache after making this change!
answered Sep 12, 2020 at 2:27
AndreiAndrei
1602 silver badges14 bronze badges
In php.ini :
extension_dir ="c:/wamp64/bin/php/php7.4.9/ext/"
Make sure the PHP version is correct.
Obsidian
3,7398 gold badges18 silver badges30 bronze badges
answered Sep 22, 2020 at 15:19
When I tried my PHP web app it was giving me the same error.
By googling I found out the MySQL plugin for the PHP server was missing with my installation. I am using Ubuntu, so when I tried MySQL plugin for PHP I found out 2 are there,
php-mysql and php<version>-mysql
I issued command — php --version in my terminal, I was having php7.4,
again I issued apt install php7.4-mysql
It worked.
answered Jul 9, 2021 at 3:35
Willey HuteWilley Hute
94913 silver badges18 bronze badges
If you tried all answers above and are still out of luck, then do check if the version numbers of the packages installed on your system really match:
apache2-mod_php7-7.4.33-150200.3.46.2.x86_64
php7-mysql-7.4.33-150200.3.46.2.x86_64
Once I had to do a manual installation from a different repo, which lead to certain libs not getting loaded (though their config was OK and their .ini files were getting parsed).
You can also try using
php -S <server_ip>:8080
to launch a test server and see if your missing module (mysqli) loads there. If it shows up in phpinfo there (and doesn’t in your regular configuration), then you at least know where to have a look at…
answered Apr 15 at 10:28
This issue can be also caused by the .htaccess file misconfiguration.
answered Sep 2, 2021 at 10:01
1685155616851556
2533 silver badges11 bronze badges
I’d like to save mysqli object into a variable. What does constructor return, if an error occurs? I mean if for example, I pass wrong login/pass/ip/dbname, I get a warning message (if warnings are enabled), but what value is in the variable?
<?php
error_reporting(E_ALL ^ E_WARNING);
$conn = new mysqli("bad", "bad", "so bad", "too bad, what then?");
//what is in $conn?
I could not find this information in PHP manual.
Dharman♦
31.1k25 gold badges86 silver badges137 bronze badges
asked Dec 14, 2018 at 15:12
9
From the PHP docs as pointed out by @Funk Forty Niner.
https://secure.php.net/manual/en/mysqli.construct.php
Note:
OO syntax only: If a connection fails an object is still returned. To check if the connection failed then use either the mysqli_connect_error() function or the mysqli->connect_error property as in the preceding examples.
However, if you enable error reporting properly like you always should then if mysqli can’t connect to the server it will throw an exception and return nothing. To do it properly enable error reporting before opening the connection:
<?php
error_reporting(E_ALL ^ E_WARNING);
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$conn = new mysqli("bad", "bad", "so bad", "too bad, what then?");
// If an error occurred then the lines below will never be executed
//VVV - $conn will always be a valid mysqli object
$conn->set_charset('utf8mb4');
Contrary to what the PHP manual says, you should never check for mysqli connection errors manually!
answered Dec 14, 2018 at 15:20
Dharman♦Dharman
31.1k25 gold badges86 silver badges137 bronze badges
0
It will still return a mysqli object, so that you can get the connect_error out of it:
$conn = new mysqli("bad", "bad", "so bad", "too bad, what then?");
print_r($conn);
Results (the first two lines are printed many times):
Warning: print_r(): Couldn't fetch mysqli in /path/to/test.php on line 4 PHP
Warning: print_r(): Couldn't fetch mysqli in /path/to/test.php on line 4
Warning: print_r(): Couldn't fetch mysqli in /path/to/test.php on line 4 (
[affected_rows] =>
[client_info] =>
[client_version] => 50011
[connect_errno] => 2002
[connect_error] => php_network_getaddresses: getaddrinfo failed: Temporary failure in name resolution
[errno] =>
[error] =>
[error_list] =>
[field_count] =>
[host_info] =>
[info] =>
[insert_id] =>
[server_info] =>
[server_version] =>
[stat] =>
[sqlstate] =>
[protocol_version] =>
[thread_id] =>
[warning_count] => )
answered Dec 14, 2018 at 15:19
aynberaynber
22.4k8 gold badges50 silver badges63 bronze badges

