Этот урок набрал набрал достаточно большое количество
комментариев и дальнейшее его комментирование отключено.
Если вы хотели убедиться в правильности выполнения ДЗ или у вас возник вопрос по уроку,
посмотрите ранее добавленные комментарии, кликнув по кнопке ниже. Скорее всего вы найдете там то, что искали.
Если это не помогло - задайте вопрос в чате в телеграме - https://t.me/php_zone
Каждый раз при обращении к БД устанавливается кодировка:
$this->pdo->exec('SET NAMES UTF8');
Зачем это нужно? Если таблицы в БД уже в UTF-8. Или это проверка на случай, если таблицы в другой кодировке? Поясните, пожалуйста, подробнее про кодировки и зачем это делается.
Спасибо.
Это задаётся кодировка не для самой базы данных, а для соединения, в рамках которого мы будем с базой данных работать. В зависимости от ОС, на которой запущен сервер и дополнительной конфигурации, эта кодировка может отличаться. Нам важно чтобы наш клиент работал с базой в той же кодировке, что и сама база. Иначе мы в результате запросов будем получать кракозябры.
С fetchAll проблема может возникнуть только на больших объемах данных возвращаемых из запроса в БД. Зато, при передаче в шаблон, эта функция становится просто незаменимой, позволяя не писать циклы вручную, и тем самым сократить количество кода.
странно, почему то у меня ругается, говорит синтаксическая ошибка (Parse error: syntax error, unexpected '?' in C:\OpenServer\domains\test\app\Services\Db.php on line 24)
Это используется затем IDEшкой - она знает что это за тип лежит в этом свойстве и даёт подсказки по тому, какие у него есть методы и свойства. Называется это phpdoc.
Тема а из-за чего может быть такое непринятие? вот этой штуки : ?array PHP 7.0 стоит текст ссылки наверное нужно синтаксический анализ PHP в редакторе проставить на 7.2 ?
Как сделать чтоб после VAR_DUMP у меня выводилось так же ровно списком как у тебя ?
у меня почему-то выводится все в куче вот так :
array(2) { [0]=> array(10) { ["id"]=> string(1) "1" [0]=> string(1) "1" ["author_id"]=> string(1) "1" [1]=> string(1) "1" ["name"]=> string(48) "Статья о том, как я погулял" [2]=> string(48) "Статья о том, как я погулял" ["text"]=> string(66) "Шёл я значит по тротуару, как вдруг..." [3]=> string(66) "Шёл я значит по тротуару, как вдруг..." ["created_at"]=> string(19) "2019-07-20 17:26:27" [4]=> string(19) "2019-07-20 17:26:27" } [1]=> array(10) { ["id"]=> string(1) "2" [0]=> string(1) "2" ["author_id"]=> string(1) "1" [1]=> string(1) "1" ["name"]=> string(22) "Пост о жизни" [2]=> string(22) "Пост о жизни" ["text"]=> string(109) "Сидел я тут на кухне с друганом и тут он задал такой вопрос..." [3]=> string(109) "Сидел я тут на кухне с друганом и тут он задал такой вопрос..." ["created_at"]=> string(19) "2019-07-20 17:26:27" [4]=> string(19) "2019-07-20 17:26:27" } }
Чтобы XDebug выводил данные через var_dump() корректно, я сделал такие изменения в php.ini:
Раскомментировал строки
html_errors = on
xdebug.overload_var_dump = 2
А также изменил строку
xdebug.default_enable = on (По умолчанию off)
"Fatal error: Uncaught PDOException: SQLSTATE[HY000] [2002] No such file or directory in ..." - ошибка для unix систем. Кто на убунту/маке и сервер запущен непосредственно самой системой без XAMPP и других помощников, делаем следующее:
в командной строке: mysql -uroot -p
далее: show variables like '%sock%';
копируем строку "/tmp/mysql.sock" (путь может быть другим. в конце обязательно mysql.sock)
получаем путь до php.ini в командной строке: php --ini
Идем к файлу, открываем и в строке pdo_mysql.default_socket="вставляем путь"
Почему тут имя класса со слешем? На php.net и везде в других источниках не нашел(возможно плохо искал если не затруднит, ткните где именно почитать) такого, хотя в этом примере без слеша не работает. Если слеш удалить - пишет класс не определен.
2.
В предыдущем уроке тоже такое было, в этом тоже вижу:
public function __construct()
{
$dbOptions = require __DIR__ . '/../../settings.php';
$this->pdo = new \PDO(
'mysql:host='.$dbOptions['host'].'; dbname='.$dbOptions['dbname'].'; charset='.$dbOptions['charset'],
$dbOptions['user'],
$dbOptions['password']
);
}
3.
Ну и сразу сюда же к примеру выше вопрос про кодировку - можно так использовать? так вроде проще/понятнее чем в уроке
4.
Вопрос аналогичный тому, что был в предыдущем уроке - Чем обусловлено месторасположение файла settings - это чисто субъективное решение, или это принципиально?
У меня такой вопрос, почему мы прописываем директорию в (), и для чего в конце находится ключ ['db']?
$dbOptions = (require DIR . '/../../settings.php')['db'];
А вы пробовали сделать без скобок? А посмотреть что будет в значении без ['db']? На данном этапе у вас уже не должно быть подобных вопросов. Максимально самостоятельно пытайтесь выполнить ДЗ и разобраться без моей помощи. Используйте дебаггер и гугл - это лучшие друзья в работе программиста.
То есть, таким образом мы ложем в переменную $dbOptions именно массив 'db', так как иначе мы не сможем использовать ключи этого массива.
Выходит, если нам нужно одновременно подключить файл и передать в переменную значение из этого файла, в нашем случае массив, используется такая конструкция () [], которую надо запомнить.
Не нужно ничего запоминать, нужно просто понимать, что происходит. Если будет понимание, что require DIR . '/../../settings.php' вернёт в нашем случае массив, то мы само собой можем обращаться к его значениям по ключам. И чтобы взять значение по ключу db, используется конструкция
$array['db']
И получается, что не надо ничего запоминать, всё уже известно.
К вопросу выше +1 про вложенные массивы с данными для подключения ДБ(в файле settings), выглядит громоздко, избыточно, прямо нависает над головой)) Работает и без вложения массива в массив. Непонятно зачем так сделано.
-Читал сначала про взаимодействие PHP с MySQL. Не очень понятно, почему там использовалось bindValue, а тут, в курсе по ООП - bindParam, хотя вроде и там и там можно взаимозаменить их и это ни на что не повлияет в данных условиях. Почему там связывали по значениям, а тут по параметрам, потому что очевидной разнизы я не вижу в
уроке по мускулу и тут.
Еще про связывание параметров: Тут параметры связываются прямо во время вызова на исполнение запроса. А в каких случаях НУЖНО использовать типизацию параметров? Просто ранее в уроках было упоминание, что нужно/очень желательно везде использовать указание типов, а тут типизация не использована, сразу передаются параметры в execute()?. Почему так?
Это конечно круто, когда заранее знаешь и представляешь всю архитектуру, но так наверное бывает крайне редко. Поэтому и непонятно - для чего. Я пока не вижу, какие в дальнейшем нужны дополнительные данные и в каких хранилищах, и скорее всего так всегда и поисходит, поэтому было бы конечно понятнее продвигаться в развитии блога как в реальных условиях, когда все сразу не предусмотришь и было бы полезно видеть как в реальных условиях решаются подобные вопросы.
2,3.
В том то и дело, что читал, но там еще не все понятно, в частности про выходные параметры/хранимые процедуры.
Выбор способа связывания параметров по переменной или значению - обусловлен же только тем, статический или динамический параметр используется для запроса(ссылка или переменная)?
Про передачу параметров через bindParam или bindValue в доке написано что или через них(или тот или тот) или через execute. Указание,что связанные переменные могут как передавать данные, так и принимать данные - ключевое в данном контексте? Или есть другая причина, по которой используется bindParam или bindValu, а не execute? Через execute передаются в запрос только строковое данные, или я что-то не так понял?
Parse error: syntax error, unexpected '?' in C:\openserver\OSPanel\domains\myproject.loc\src\MyProject\Services\Db.php on line 22
public function query(string $sql, $params = []): ?array
Не раз замечал "?" знак возле возврата типа данных функции, всегда удалял их считая за ошибку, но в этот раз решил спросить. Что делает это выражение "?array" и почему PHP выкидывает ошибку?
Сорян, включил мозги и использовал гугл). Ответ кому надо:
Начиная с PHP 7.1.0 возвращаемые значения могут быть помечены как обнуляемые, путём добавления префикса в виде вопросительного знака (?) к названию типу. Это означает, что функция возвращает либо значение указанного типа, либо значение NULL.
Если у вас выдает ошибку, то у вас версия PHP меньше PHP 7.1.
Это будет не очень хорошо. В первом варианте мы явно берем возвращаемое значение и помещаем его в переменную с определенным именем. Если же делать как во втором варианте, у нас в том месте где файл подключается появляются переменные $db и потом что-нибудь ещё непонятно откуда.
А что именно не понял? Я о том, что вот мы написали, к примеру:
$settings = require ...
$db = new Db($settings['db']);
и сразу понятно откуда $settings взялось. Это лучше чем:
require ...
$db = new Db($dbSettings);
И непонятно, откуда появилась $dbSettings. Сиди и думай потом в каком из 10 require нужная переменная взялась, а может она потом в другом require потом еще и поменялась.
Вопрос о том, почему в виде массивов, а не через define всех нужных констант? Ведь настройки для подключения к БД - это тоже константы. Т.е.сложить переменные в файле в виде констант.
Глобальные - как пишут в документации: Как и superglobals, константы доступны из любой области видимости.
Хотя я на самом деле имел в виду не совсем это. В случае с define по такой же схеме как в уроке - все равно нужно при использовании констант подключать файл с константами, там где нужно.
У меня мысль - этот файл с константами подключить один раз через require в index.php, тогда из любого места в проекте можно вызывать нужные константы. Т.о. эти константы наверное можно с чистой совестью называть глобальными?
Интересный хук, первый раз вижу такое: $dbOptions = (require DIR . '/../../settings.php')['db'];
И самое интересное, что гугл ничего не выдаёт мне по этому вопросу, дебаггер показывает, что db массив аннигилирует, когда значения передаются в переменную $dbOptions без этого массива, зачем тогда его вообще писать?
Кто там кого аннигилирует? :D
В результате require вернется массив из файла settings.php, из этого массива берем значение по ключу db и кладем это значение в dbOptions
Каждый раз при обращении к БД устанавливается кодировка:
Зачем это нужно? Если таблицы в БД уже в UTF-8. Или это проверка на случай, если таблицы в другой кодировке? Поясните, пожалуйста, подробнее про кодировки и зачем это делается.
Спасибо.
Это задаётся кодировка не для самой базы данных, а для соединения, в рамках которого мы будем с базой данных работать. В зависимости от ОС, на которой запущен сервер и дополнительной конфигурации, эта кодировка может отличаться. Нам важно чтобы наш клиент работал с базой в той же кодировке, что и сама база. Иначе мы в результате запросов будем получать кракозябры.
Спасибо.
У меня такой вопрос:
Почему мы используем fetchAll который выводит и индексы и ключи?
Не лучше ли доставать либо только ключи либо только индексы?
Лучше) Можете сюда написать, как Вы улучшили.
С fetchAll проблема может возникнуть только на больших объемах данных возвращаемых из запроса в БД. Зато, при передаче в шаблон, эта функция становится просто незаменимой, позволяя не писать циклы вручную, и тем самым сократить количество кода.
http://prntscr.com/lg1k1z тут наверно символ ? лишний
Нет, это значит либо массив может вернуться, либо null.
странно, почему то у меня ругается, говорит синтаксическая ошибка (Parse error: syntax error, unexpected '?' in C:\OpenServer\domains\test\app\Services\Db.php on line 24)
PHP какая версия?
виноват, версия была 7, надо было повыше поставить , спасибо)
Не за что)
Добрый день. Можно, на ваш взгляд, как то это оптимизировать или это имеет право на жизнь.
Выглядит сложновато, рекомендую ознакомиться с другими решениями в комментах.
по firebird нет вроде вариантов....
К сожалению, не смогу Вас проконсультировать по поводу этого решения, не работал с этой базой.
Можно узнать, для чего существуют такие комментарии?
Я где то возможно что то упустил, но погуглив не совсем понимаю для чего они.
Это используется затем IDEшкой - она знает что это за тип лежит в этом свойстве и даёт подсказки по тому, какие у него есть методы и свойства. Называется это phpdoc.
Вот теперь понял) спасибо!
Тема а из-за чего может быть такое непринятие? вот этой штуки : ?array PHP 7.0 стоит
текст ссылки наверное нужно синтаксический анализ PHP в редакторе проставить на 7.2 ?
Да, и в редакторе, и на сервере
Как сделать чтоб после VAR_DUMP у меня выводилось так же ровно списком как у тебя ?
у меня почему-то выводится все в куче вот так :
array(2) { [0]=> array(10) { ["id"]=> string(1) "1" [0]=> string(1) "1" ["author_id"]=> string(1) "1" [1]=> string(1) "1" ["name"]=> string(48) "Статья о том, как я погулял" [2]=> string(48) "Статья о том, как я погулял" ["text"]=> string(66) "Шёл я значит по тротуару, как вдруг..." [3]=> string(66) "Шёл я значит по тротуару, как вдруг..." ["created_at"]=> string(19) "2019-07-20 17:26:27" [4]=> string(19) "2019-07-20 17:26:27" } [1]=> array(10) { ["id"]=> string(1) "2" [0]=> string(1) "2" ["author_id"]=> string(1) "1" [1]=> string(1) "1" ["name"]=> string(22) "Пост о жизни" [2]=> string(22) "Пост о жизни" ["text"]=> string(109) "Сидел я тут на кухне с друганом и тут он задал такой вопрос..." [3]=> string(109) "Сидел я тут на кухне с друганом и тут он задал такой вопрос..." ["created_at"]=> string(19) "2019-07-20 17:26:27" [4]=> string(19) "2019-07-20 17:26:27" } }
Включить xdebug
У меня XDebug включен, но var_dump все равно выводит все одной строкой
в php.ini разкомментируй строку
xdebug.overload_var_dump
Можно написать функцию, чтобы не включать xdebug
код функции:
Только теперь используй команду vardump, а не var_dump
о__О
Чтобы XDebug выводил данные через var_dump() корректно, я сделал такие изменения в php.ini:
Раскомментировал строки
html_errors = on
xdebug.overload_var_dump = 2
А также изменил строку
xdebug.default_enable = on (По умолчанию off)
P.S. Важно изменять не временный файл php.ini
Мне помогло, спасибо.
Для php 7.2 в добавок к вышеперечисленному надо раскоментить:
Вопросы:
1) Файл Db.php
Почему перед array знак вопроса?
2) Файл MainController.php
Эти комментарии создаются автоматом или нет? /* @var Db /
Как их делать?
3) Почему тут в запросе пишутся `` и ;
Вроде бы раньше просто писали:
Cпасибо, HardBass
"Fatal error: Uncaught PDOException: SQLSTATE[HY000] [2002] No such file or directory in ..." - ошибка для unix систем. Кто на убунту/маке и сервер запущен непосредственно самой системой без XAMPP и других помощников, делаем следующее:
в командной строке: mysql -uroot -p
далее: show variables like '%sock%';
копируем строку "/tmp/mysql.sock" (путь может быть другим. в конце обязательно mysql.sock)
получаем путь до php.ini в командной строке: php --ini
Идем к файлу, открываем и в строке pdo_mysql.default_socket="вставляем путь"
перезапускаем apache. (sudo apachectl restart)
в Db.php
в settings.php
Отличный совет!
Спасибо большое за урок!
Пойду на php.net ознакомлюсь с PDO (:
Пожалуйста)
1.
Почему тут имя класса со слешем? На php.net и везде в других источниках не нашел(возможно плохо искал если не затруднит, ткните где именно почитать) такого, хотя в этом примере без слеша не работает. Если слеш удалить - пишет класс не определен.
2.
В предыдущем уроке тоже такое было, в этом тоже вижу:
Зачем оборачивать массив в еще один массив? Без этого вроде все и так работает:
settings.php
конструктор класса Db
3.
Ну и сразу сюда же к примеру выше вопрос про кодировку - можно так использовать? так вроде проще/понятнее чем в уроке
4.
Вопрос аналогичный тому, что был в предыдущем уроке - Чем обусловлено месторасположение файла settings - это чисто субъективное решение, или это принципиально?
Подскажите пожалуйста по третьему вопросу выше.
Да, можно =)
У меня такой вопрос, почему мы прописываем директорию в (), и для чего в конце находится ключ ['db']?
$dbOptions = (require DIR . '/../../settings.php')['db'];
А вы пробовали сделать без скобок? А посмотреть что будет в значении без ['db']? На данном этапе у вас уже не должно быть подобных вопросов. Максимально самостоятельно пытайтесь выполнить ДЗ и разобраться без моей помощи. Используйте дебаггер и гугл - это лучшие друзья в работе программиста.
Хорошо
То есть, таким образом мы ложем в переменную $dbOptions именно массив 'db', так как иначе мы не сможем использовать ключи этого массива.
Выходит, если нам нужно одновременно подключить файл и передать в переменную значение из этого файла, в нашем случае массив, используется такая конструкция () [], которую надо запомнить.
Не нужно ничего запоминать, нужно просто понимать, что происходит. Если будет понимание, что require DIR . '/../../settings.php' вернёт в нашем случае массив, то мы само собой можем обращаться к его значениям по ключам. И чтобы взять значение по ключу db, используется конструкция
И получается, что не надо ничего запоминать, всё уже известно.
К вопросу выше +1 про вложенные массивы с данными для подключения ДБ(в файле settings), выглядит громоздко, избыточно, прямо нависает над головой)) Работает и без вложения массива в массив. Непонятно зачем так сделано.
-Читал сначала про взаимодействие PHP с MySQL. Не очень понятно, почему там использовалось bindValue, а тут, в курсе по ООП - bindParam, хотя вроде и там и там можно взаимозаменить их и это ни на что не повлияет в данных условиях. Почему там связывали по значениям, а тут по параметрам, потому что очевидной разнизы я не вижу в
уроке по мускулу и тут.
Еще про связывание параметров: Тут параметры связываются прямо во время вызова на исполнение запроса. А в каких случаях НУЖНО использовать типизацию параметров? Просто ранее в уроках было упоминание, что нужно/очень желательно везде использовать указание типов, а тут типизация не использована, сразу передаются параметры в execute()?. Почему так?
1.
Это конечно круто, когда заранее знаешь и представляешь всю архитектуру, но так наверное бывает крайне редко. Поэтому и непонятно - для чего. Я пока не вижу, какие в дальнейшем нужны дополнительные данные и в каких хранилищах, и скорее всего так всегда и поисходит, поэтому было бы конечно понятнее продвигаться в развитии блога как в реальных условиях, когда все сразу не предусмотришь и было бы полезно видеть как в реальных условиях решаются подобные вопросы.
2,3.
В том то и дело, что читал, но там еще не все понятно, в частности про выходные параметры/хранимые процедуры.
Выбор способа связывания параметров по переменной или значению - обусловлен же только тем, статический или динамический параметр используется для запроса(ссылка или переменная)?
Про передачу параметров через bindParam или bindValue в доке написано что или через них(или тот или тот) или через execute. Указание,что связанные переменные могут как передавать данные, так и принимать данные - ключевое в данном контексте? Или есть другая причина, по которой используется bindParam или bindValu, а не execute? Через execute передаются в запрос только строковое данные, или я что-то не так понял?
Parse error: syntax error, unexpected '?' in C:\openserver\OSPanel\domains\myproject.loc\src\MyProject\Services\Db.php on line 22
Не раз замечал "?" знак возле возврата типа данных функции, всегда удалял их считая за ошибку, но в этот раз решил спросить. Что делает это выражение "?array" и почему PHP выкидывает ошибку?
Сорян, включил мозги и использовал гугл). Ответ кому надо:
Начиная с PHP 7.1.0 возвращаемые значения могут быть помечены как обнуляемые, путём добавления префикса в виде вопросительного знака (?) к названию типу. Это означает, что функция возвращает либо значение указанного типа, либо значение NULL.
Если у вас выдает ошибку, то у вас версия PHP меньше PHP 7.1.
И еще опечатка в строке:
Точек с запятой многовато.
Одна из них в конце SQL-запроса
Я чего-то не так понял или тут с файлом index.php нужно самому разбираться?
Разобрался. Мой косяк был, запутался в путях и в итоге не работало.
Ок, молодец что разобрался
Добрый вечер.
Для понимания - а можно просто создавать переменные и потом обращаться к ним из других файлов?
Так.
settings.php
Это будет не очень хорошо. В первом варианте мы явно берем возвращаемое значение и помещаем его в переменную с определенным именем. Если же делать как во втором варианте, у нас в том месте где файл подключается появляются переменные $db и потом что-нибудь ещё непонятно откуда.
Не понял, но беру за правило.)
Спасибо!
А что именно не понял? Я о том, что вот мы написали, к примеру:
и сразу понятно откуда $settings взялось. Это лучше чем:
И непонятно, откуда появилась $dbSettings. Сиди и думай потом в каком из 10 require нужная переменная взялась, а может она потом в другом require потом еще и поменялась.
Меньше прозрачности, в общем
Понятный код! Теперь понял, Артем, благодарю.
На здоровье)
Почему хранение данных выбрано именно в виде массива, а не как глобальные константы?
Что ещё за глобальные константы и откуда вы про них узнали?
Вопрос о том, почему в виде массивов, а не через define всех нужных констант? Ведь настройки для подключения к БД - это тоже константы. Т.е.сложить переменные в файле в виде констант.
Глобальные - как пишут в документации: Как и superglobals, константы доступны из любой области видимости.
Хотя я на самом деле имел в виду не совсем это. В случае с define по такой же схеме как в уроке - все равно нужно при использовании констант подключать файл с константами, там где нужно.
У меня мысль - этот файл с константами подключить один раз через require в index.php, тогда из любого места в проекте можно вызывать нужные константы. Т.о. эти константы наверное можно с чистой совестью называть глобальными?
Можно и так конечно, но лучше тогда уж через getenv() получать переменные окружения. Почитайте про dotenv
Спасибо за урок! ))
Пожалуйста)
Интересный хук, первый раз вижу такое: $dbOptions = (require DIR . '/../../settings.php')['db'];
И самое интересное, что гугл ничего не выдаёт мне по этому вопросу, дебаггер показывает, что db массив аннигилирует, когда значения передаются в переменную $dbOptions без этого массива, зачем тогда его вообще писать?
Кто там кого аннигилирует? :D
В результате require вернется массив из файла settings.php, из этого массива берем значение по ключу db и кладем это значение в dbOptions
Надо было, наверное, все таки в две строчки написать, для наглядности:
Можно без скобок)
Возможно