Этот урок набрал набрал достаточно большое количество комментариев и дальнейшее его комментирование отключено. Если вы хотели убедиться в правильности выполнения ДЗ или у вас возник вопрос по уроку, посмотрите ранее добавленные комментарии, кликнув по кнопке ниже. Скорее всего вы найдете там то, что искали. Если это не помогло - задайте вопрос в чате в телеграме - https://t.me/php_zone
rusgil 25.07.2018 в 21:39

Каждый раз при обращении к БД устанавливается кодировка:

$this->pdo->exec('SET NAMES UTF8');

Зачем это нужно? Если таблицы в БД уже в UTF-8. Или это проверка на случай, если таблицы в другой кодировке? Поясните, пожалуйста, подробнее про кодировки и зачем это делается.
Спасибо.

ivashkevich 26.07.2018 в 06:16

Это задаётся кодировка не для самой базы данных, а для соединения, в рамках которого мы будем с базой данных работать. В зависимости от ОС, на которой запущен сервер и дополнительной конфигурации, эта кодировка может отличаться. Нам важно чтобы наш клиент работал с базой в той же кодировке, что и сама база. Иначе мы в результате запросов будем получать кракозябры.

artemjeka 25.10.2018 в 07:21

Спасибо.

artemjeka 25.10.2018 в 07:22

У меня такой вопрос:
Почему мы используем fetchAll который выводит и индексы и ключи?
Не лучше ли доставать либо только ключи либо только индексы?

ivashkevich 26.10.2018 в 08:48

Лучше) Можете сюда написать, как Вы улучшили.

virtual2018 26.12.2018 в 12:46

С fetchAll проблема может возникнуть только на больших объемах данных возвращаемых из запроса в БД. Зато, при передаче в шаблон, эта функция становится просто незаменимой, позволяя не писать циклы вручную, и тем самым сократить количество кода.

Todd 08.11.2018 в 23:47

http://prntscr.com/lg1k1z тут наверно символ ? лишний

ivashkevich 08.11.2018 в 23:48

Нет, это значит либо массив может вернуться, либо null.

Todd 09.11.2018 в 01:06

странно, почему то у меня ругается, говорит синтаксическая ошибка (Parse error: syntax error, unexpected '?' in C:\OpenServer\domains\test\app\Services\Db.php on line 24)

ivashkevich 09.11.2018 в 09:03

PHP какая версия?

Todd 10.11.2018 в 02:30

виноват, версия была 7, надо было повыше поставить , спасибо)

ivashkevich 12.11.2018 в 01:49

Не за что)

Its-me 30.01.2019 в 20:40

Добрый день. Можно, на ваш взгляд, как то это оптимизировать или это имеет право на жизнь.

public function query(string $sql/*, $params = []*/): ?array
{
    $sth = ibase_query($this->pdo, $sql/*, $params*/);
    $result = ibase_query($this->pdo, $sql/*, $params*/);
    //$result = $sth->execute($params);

    if (false === $result) {
        return null;
    }

    while ($row = ibase_fetch_object($sth)){
    $resar[] = $row;
    $countar = count($resar);
    $ar = $resar[$countar - 1] -> TEXT;
    $blinfo = ibase_blob_info($ar);
    $blob = ibase_blob_open($ar);
    $bltext = ibase_blob_get($blob, $blinfo[0]);
    $resar[$countar - 1] -> TEXT = $bltext;
    $resar[$countar - 1] = (array)$resar[$countar - 1];

    }
ivashkevich 01.02.2019 в 23:48

Выглядит сложновато, рекомендую ознакомиться с другими решениями в комментах.

Its-me 02.02.2019 в 21:22

по firebird нет вроде вариантов....

ivashkevich 03.02.2019 в 23:46

К сожалению, не смогу Вас проконсультировать по поводу этого решения, не работал с этой базой.

excent63 09.03.2019 в 17:30

Можно узнать, для чего существуют такие комментарии?

/** @var Db */

Я где то возможно что то упустил, но погуглив не совсем понимаю для чего они.

ivashkevich 09.03.2019 в 19:40

Это используется затем IDEшкой - она знает что это за тип лежит в этом свойстве и даёт подсказки по тому, какие у него есть методы и свойства. Называется это phpdoc.

excent63 09.03.2019 в 19:44

Вот теперь понял) спасибо!

Metey 20.07.2019 в 17:34

Тема а из-за чего может быть такое непринятие? вот этой штуки : ?array PHP 7.0 стоит
текст ссылки наверное нужно синтаксический анализ PHP в редакторе проставить на 7.2 ?

ivashkevich 21.07.2019 в 05:19

Да, и в редакторе, и на сервере

Metey 20.07.2019 в 17:53

Как сделать чтоб после 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" } }

ivashkevich 21.07.2019 в 05:20

Включить xdebug

Dimitry 03.04.2020 в 15:29

У меня XDebug включен, но var_dump все равно выводит все одной строкой

Galay 02.05.2020 в 18:38

в php.ini разкомментируй строку
xdebug.overload_var_dump

Egleman 16.08.2019 в 14:00

Можно написать функцию, чтобы не включать xdebug
код функции:

function vardump($var) {
  echo '<pre>';
  var_dump($var);
  echo '</pre>';
}

Только теперь используй команду vardump, а не var_dump

ivashkevich 03.04.2020 в 18:38

о__О

HardBass 25.06.2020 в 20:47

Чтобы XDebug выводил данные через var_dump() корректно, я сделал такие изменения в php.ini:
Раскомментировал строки
html_errors = on
xdebug.overload_var_dump = 2
А также изменил строку
xdebug.default_enable = on (По умолчанию off)

P.S. Важно изменять не временный файл php.ini

demos Patron 04.09.2020 в 17:13

Мне помогло, спасибо.

demos Patron 21.09.2020 в 15:55

Для php 7.2 в добавок к вышеперечисленному надо раскоментить:

zend_extension = xdebug
prognoz 21.08.2019 в 00:37

Вопросы:
1) Файл Db.php
Почему перед array знак вопроса?

public function query(string $sql, $params = []) : ?array

2) Файл MainController.php
Эти комментарии создаются автоматом или нет? /* @var Db /
Как их делать?

3) Почему тут в запросе пишутся `` и ;

$articles = $this->db->query('SELECT * FROM `articles`;');

Вроде бы раньше просто писали:

'SELECT * FROM articles';
ivashkevich 22.08.2019 в 06:51
  1. Потому что функция помимо массива может вернуть null.
  2. Нет, они пишутся от руки. Почитайте про PHPDoc
  3. Можно и так и так, но правильнее все же окружать имя таблицы кавычками.
[email protected] 08.07.2020 в 22:26

Cпасибо, HardBass

vtolstov 23.09.2019 в 12:25

"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

$this->pdo = new \PDO(
                'mysql:host=' . $dbOptions['host'] . ';dbname=' . $dbOptions['dbname'] . ';unix_socket=' . $dbOptions['unix_socket'],
                $dbOptions['user'],
                $dbOptions['password']
                );

в settings.php

return [
    'db' => [
        'host' => 'localhost',
        'dbname' => 'my_project',
        'user' => 'root',
        'password' => '',
        'unix_socket' => '/tmp/mysql.sock', //здесь прописать свой путь
    ]
];
ivashkevich 23.09.2019 в 13:35

Отличный совет!

andreskrip 26.01.2020 в 18:22

Спасибо большое за урок!
Пойду на php.net ознакомлюсь с PDO (:

ivashkevich 28.01.2020 в 18:44

Пожалуйста)

X-Nick 23.02.2020 в 18:21

1.

$this->pdo = new \PDO

Почему тут имя класса со слешем? На php.net и везде в других источниках не нашел(возможно плохо искал если не затруднит, ткните где именно почитать) такого, хотя в этом примере без слеша не работает. Если слеш удалить - пишет класс не определен.

2.
В предыдущем уроке тоже такое было, в этом тоже вижу:

return [
    'db' => [
        'host' => 'localhost',
        'dbname' => 'my_project',
        'user' => 'root',
        'password' => '',
    ]
];

Зачем оборачивать массив в еще один массив? Без этого вроде все и так работает:

settings.php

<?php
return [

        'host' => 'localhost',
        'dbname' => 'my_project',
        'user' => 'root',
        'password' => '',
        'charset' => 'UTF8'
];

конструктор класса Db

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 - это чисто субъективное решение, или это принципиально?

ivashkevich 23.02.2020 в 19:42
  1. Это указание нэймспэйса. В данном случае корневого. Когда начинается использование неймспейсов нужно явно указывать полный путь до классов.
OneMoreTime 26.02.2020 в 21:30

Подскажите пожалуйста по третьему вопросу выше.

ivashkevich 28.02.2020 в 05:01

Да, можно =)

studentDev 02.05.2020 в 10:27

У меня такой вопрос, почему мы прописываем директорию в (), и для чего в конце находится ключ ['db']?
$dbOptions = (require DIR . '/../../settings.php')['db'];

ivashkevich 02.05.2020 в 16:22

А вы пробовали сделать без скобок? А посмотреть что будет в значении без ['db']? На данном этапе у вас уже не должно быть подобных вопросов. Максимально самостоятельно пытайтесь выполнить ДЗ и разобраться без моей помощи. Используйте дебаггер и гугл - это лучшие друзья в работе программиста.

studentDev 02.05.2020 в 16:33

Хорошо

[email protected] 08.07.2020 в 22:46
      $dbOptions = (require __DIR__ . '/../../settings.php') ['db'];

То есть, таким образом мы ложем в переменную $dbOptions именно массив 'db', так как иначе мы не сможем использовать ключи этого массива.

Выходит, если нам нужно одновременно подключить файл и передать в переменную значение из этого файла, в нашем случае массив, используется такая конструкция () [], которую надо запомнить.

ivashkevich 09.07.2020 в 05:26

Не нужно ничего запоминать, нужно просто понимать, что происходит. Если будет понимание, что require DIR . '/../../settings.php' вернёт в нашем случае массив, то мы само собой можем обращаться к его значениям по ключам. И чтобы взять значение по ключу db, используется конструкция

$array['db']

И получается, что не надо ничего запоминать, всё уже известно.

OneMoreTime 05.05.2020 в 20:51

К вопросу выше +1 про вложенные массивы с данными для подключения ДБ(в файле settings), выглядит громоздко, избыточно, прямо нависает над головой)) Работает и без вложения массива в массив. Непонятно зачем так сделано.


-Читал сначала про взаимодействие PHP с MySQL. Не очень понятно, почему там использовалось bindValue, а тут, в курсе по ООП - bindParam, хотя вроде и там и там можно взаимозаменить их и это ни на что не повлияет в данных условиях. Почему там связывали по значениям, а тут по параметрам, потому что очевидной разнизы я не вижу в
уроке по мускулу и тут.


Еще про связывание параметров: Тут параметры связываются прямо во время вызова на исполнение запроса. А в каких случаях НУЖНО использовать типизацию параметров? Просто ранее в уроках было упоминание, что нужно/очень желательно везде использовать указание типов, а тут типизация не использована, сразу передаются параметры в execute()?. Почему так?

ivashkevich 06.05.2020 в 13:51
  1. Потому что потом появятся другие настройки, помимо подключения к БД.
  2. Почитайте документацию.
  3. И тут тоже) Прям почитайте про PDO и про параметризованные запросы. В официальной документации есть ответы на ваши вопросы.
OneMoreTime 06.05.2020 в 22:47

1.

потом

Это конечно круто, когда заранее знаешь и представляешь всю архитектуру, но так наверное бывает крайне редко. Поэтому и непонятно - для чего. Я пока не вижу, какие в дальнейшем нужны дополнительные данные и в каких хранилищах, и скорее всего так всегда и поисходит, поэтому было бы конечно понятнее продвигаться в развитии блога как в реальных условиях, когда все сразу не предусмотришь и было бы полезно видеть как в реальных условиях решаются подобные вопросы.

2,3.
В том то и дело, что читал, но там еще не все понятно, в частности про выходные параметры/хранимые процедуры.

Выбор способа связывания параметров по переменной или значению - обусловлен же только тем, статический или динамический параметр используется для запроса(ссылка или переменная)?

Про передачу параметров через bindParam или bindValue в доке написано что или через них(или тот или тот) или через execute. Указание,что связанные переменные могут как передавать данные, так и принимать данные - ключевое в данном контексте? Или есть другая причина, по которой используется bindParam или bindValu, а не execute? Через execute передаются в запрос только строковое данные, или я что-то не так понял?

titelivus 08.05.2020 в 09:06

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 выкидывает ошибку?

titelivus 08.05.2020 в 09:26

Сорян, включил мозги и использовал гугл). Ответ кому надо:

Начиная с PHP 7.1.0 возвращаемые значения могут быть помечены как обнуляемые, путём добавления префикса в виде вопросительного знака (?) к названию типу. Это означает, что функция возвращает либо значение указанного типа, либо значение NULL.

Если у вас выдает ошибку, то у вас версия PHP меньше PHP 7.1.

[email protected] 08.05.2020 в 13:45

И еще опечатка в строке:

$articles = $this->db->query('SELECT * FROM `articles`;');

Точек с запятой многовато.

ivashkevich 08.05.2020 в 20:30

Одна из них в конце SQL-запроса

invisibleee 26.06.2020 в 15:24

Я чего-то не так понял или тут с файлом index.php нужно самому разбираться?

invisibleee 26.06.2020 в 16:03

Разобрался. Мой косяк был, запутался в путях и в итоге не работало.

ivashkevich 27.06.2020 в 16:30

Ок, молодец что разобрался

[email protected] 08.07.2020 в 22:52
return [
    'db' => [
        'host' => 'localhost',
        'dbname' => 'my_project',
        'user' => 'root',
        'password' => '',
    ]
];

Добрый вечер.
Для понимания - а можно просто создавать переменные и потом обращаться к ним из других файлов?
Так.
settings.php

  $db = ['host' => 'localhost',
        'dbname' => 'my_project',
        'user' => 'root',
        'password' => 'root'];
ivashkevich 09.07.2020 в 05:29

Это будет не очень хорошо. В первом варианте мы явно берем возвращаемое значение и помещаем его в переменную с определенным именем. Если же делать как во втором варианте, у нас в том месте где файл подключается появляются переменные $db и потом что-нибудь ещё непонятно откуда.

[email protected] 09.07.2020 в 06:35

Не понял, но беру за правило.)
Спасибо!

ivashkevich 09.07.2020 в 08:11

А что именно не понял? Я о том, что вот мы написали, к примеру:

$settings = require ...
$db = new Db($settings['db']);

и сразу понятно откуда $settings взялось. Это лучше чем:

require ...
$db = new Db($dbSettings);

И непонятно, откуда появилась $dbSettings. Сиди и думай потом в каком из 10 require нужная переменная взялась, а может она потом в другом require потом еще и поменялась.

Меньше прозрачности, в общем

[email protected] 09.07.2020 в 08:44

Понятный код! Теперь понял, Артем, благодарю.

ivashkevich 09.07.2020 в 11:55

На здоровье)

OneMoreTime 17.07.2020 в 14:58

Давайте также создадим файл с настройками для подключения к базе данных. Он будет представлять собой простой массив.

Почему хранение данных выбрано именно в виде массива, а не как глобальные константы?

ivashkevich 20.07.2020 в 02:21

Что ещё за глобальные константы и откуда вы про них узнали?

OneMoreTime 20.07.2020 в 15:48

Вопрос о том, почему в виде массивов, а не через define всех нужных констант? Ведь настройки для подключения к БД - это тоже константы. Т.е.сложить переменные в файле в виде констант.
Глобальные - как пишут в документации: Как и superglobals, константы доступны из любой области видимости.

Хотя я на самом деле имел в виду не совсем это. В случае с define по такой же схеме как в уроке - все равно нужно при использовании констант подключать файл с константами, там где нужно.

У меня мысль - этот файл с константами подключить один раз через require в index.php, тогда из любого места в проекте можно вызывать нужные константы. Т.о. эти константы наверное можно с чистой совестью называть глобальными?

ivashkevich 21.07.2020 в 12:02

Можно и так конечно, но лучше тогда уж через getenv() получать переменные окружения. Почитайте про dotenv

VitaliyB 08.08.2020 в 09:26

Спасибо за урок! ))

ivashkevich 11.08.2020 в 13:18

Пожалуйста)

[email protected] 01.12.2020 в 18:26

Интересный хук, первый раз вижу такое: $dbOptions = (require DIR . '/../../settings.php')['db'];
И самое интересное, что гугл ничего не выдаёт мне по этому вопросу, дебаггер показывает, что db массив аннигилирует, когда значения передаются в переменную $dbOptions без этого массива, зачем тогда его вообще писать?

ivashkevich 01.12.2020 в 19:41

Кто там кого аннигилирует? :D
В результате require вернется массив из файла settings.php, из этого массива берем значение по ключу db и кладем это значение в dbOptions

[email protected] 18.04.2021 в 14:44

Надо было, наверное, все таки в две строчки написать, для наглядности:

$settings = (require DIR . '/../../settings.php');
$dbOptions = $settings['db'];

Можно без скобок)

ivashkevich 18.04.2021 в 18:04

Возможно

Логические задачи с собеседований