Долго провозился с использованием переменной в запросе
public function view(int $articleId)
{
$result = $this->db->query(
'SELECT * FROM `articles` WHERE id = :id;',
[':id' => $articleId]
);
$author = $this->db->query('SELECT nickname FROM users WHERE id = "'.$result[0][1].'"');
if ($result === []) {
$this->view->renderHtml('errors/404.php');
return;
}
$this->view->renderHtml('articles/view.php', ['article' => $result[0], 'author' =>$author[0][0]]);
}
В экшне ArticlesController::view() после получения статьи, добавьте ещё один запрос на получение автора этой статьи из таблицы users. Выведите nickname автора в шаблоне.
С помощью Join соединил две таблички и без лишних обращений к базе забрал себе пользователей, дополнительно в списке статей тоже вывел авторов. Курс по БД прошел не зря=)
//MainController.php
public function main()
{
$articles = $this->db->query('SELECT * FROM `articles` a JOIN `users` u ON a.author_id = u.id');
$this->view->renderHtml('main/main.php', ['articles' => $articles]);
}
//ArticlesController.php
public function view(int $articleId)
{
$result = $this->db->query('SELECT * FROM `articles` a JOIN `users` u ON a.author_id = u.id WHERE a.id = :id;',[':id' => $articleId]);
if ($result === []) {
$this->view->renderHtml('errors/404.php',[],404);
return;
}
$this->view->renderHtml('articles/view.php', ['article' => $result[0]]);
}
public function view(int $articleId)
{
$result = $this->db->query(
'SELECT * FROM `articles` WHERE id = :id;',
[':id' => $articleId]
);
if ($result === []) {
$this->view->renderHtml('errors/404.php', 404);
return;
}
$author = $this->db->query(
'SELECT nickname FROM users WHERE id = :id',
[':id' => $result[0][1]]
);
$this->view->renderHtml('articles/view.php', ['article' => $result[0], 'author' => $author[0][0]]);
}
И есть один вопрос, View на вход принимает $articleId, так вот мне не совсем понятно каким образом эта переменная задается ив какой именно момент она получает свои значения "1" "2"
$articles = $this->db->query('SELECT A.id,A.name,A.text,B.nickname FROM `articles` A INNER JOIN `users` B ON A.`author_id` = B.`id`;');/*Изменил запрос в MainController*/
public function view(int $articleId)
{
$result = $this->db->query(
'SELECT A.id,A.name,A.text,B.nickname FROM `articles` A INNER JOIN `users` B ON A.`author_id` = B.`id` WHERE A.id = :id;',
[':id' => $articleId]
);/*так же в ActiveController*/
<p>Автор: <?= $article['nickname'] ?></p><!-- добавил автора в main.php и view.php -->
Для коллекции решений, автора получим в основном запросе выборкой из двух баз и дополнительно электронную почту автора , отдельным запросом с выводом в отдельную переменную:
public function view(int $articleId)
{
$result = $this->db->query(
'SELECT a.author_id,a.name,a.text,u.nickname FROM `articles` a, `users` u WHERE a.author_id = u.id and a.id = :id;',
[':id' => $articleId]
);
if ($result === []) {
$this->view->renderHtml('errors/404.php', [], 404);
return;
}
$result_users = $this->db->query(
'SELECT email FROM `users` WHERE id = :id;',
[':id' => $result[0]['author_id']]
);
$this->view->renderHtml('articles/view.php', ['article' => $result[0], 'mail_to' => $result_users[0]['email']]);
}
Мы столько учили классы и наследования, можем ли мы тут их применить, как это к примеру сделал я?
<?php
namespace MyProject\Controllers;
class ArticlesController extends MainController
{
public function view(int $articleId)
{
$result = $this->db->query(
'SELECT * FROM `articles` WHERE id = :id;',
[':id' => $articleId]
);
if ($result === []) {
$this->view->renderHtml('errors/404.php');
return;
}
$author = $this->db->query(
'SELECT * FROM `users` WHERE id = :author_id;',
[':author_id' => $result[0]['author_id']]);
$this->view->renderHtml('articles/view.php', ['article' => $result[0], 'author' => $author[0]]);
}
}
этим мы вроде как слегка оптимизировали код, убрали
use MyProject\Services\Db;
use MyProject\View\View;
/** @var View */
private $view;
/** @var Db */
private $db;
public function __construct()
{
$this->view = new View(__DIR__ . '/../../../templates');
$this->db = new Db();
}
если будет много контроллеров, сделать абстрактный класс, со всеми этими VIew и подклечениями к бд, и от него уже наследоваться. Хотя я может просто бегу впереди паровоза))
Не надо так. Можно просто завести переменную $nickname в самом начале метода со значением 'Автор не найден'. Если после запроса он есть, то переопределять эту переменную. И в renderHtml передавать её.
С помощью комментариев получилось добиться рабочего кода, но где то я что недопонял видимо и теперь немного не понимаю как происходит вывод статей, попробую проходить дальше, если так же не будет доходить, придётся назад возвращаться и перечитывать по новой)
//ArticlesController.php
public function view(int $articleId)
{
$result = $this->db->query(
'SELECT * FROM `articles` WHERE id = :id',
[':id' => $articleId]
);
if ($result === []) {
$this->view->renderHtml('errors/404.php', [], 404);
return;
}
$user = $this->db->query(
'SELECT `nickname` FROM `users` WHERE id = :id',
[':id' => $result[0]['author_id']]
);
if ($user === []) {
$user[0]['nickname'] = 'не известно';
}
$this->view->renderHtml('articles/view.php', ['article'=> $result[0], 'nickname' => $user[0]['nickname']],200);
}
//view.php
<?php include __DIR__ . '/../header.php'; ?>
<h1><?= $article['name'] ?></h1>
<p><?= $article['text'] ?></p>
<p>Имя автора: <?= $nickname ?></p>
<?php include __DIR__ . '/../footer.php'; ?>
public function view()
{
echo 'Здесь будет получение статьи и рендеринг шаблона';
}
Все нормально по адресу http://localhost/articles/1 я вижу "Здесь будет получение статьи и рендеринг шаблона".
Стоит изменить эту функцию на
public function view(int $articleId)
{
$result = $this->db->query(
'SELECT * FROM `articles` WHERE id = :id;',
[':id' => $articleId]
);
var_dump($result);
}
И я снова получаю ту ошибку, о которой писал ранее:
( ! ) Fatal error: Uncaught ArgumentCountError: Too few arguments to function MyProject\Controllers\ArticlesController::view(), 0 passed in C:\OSPanel\domains\localhost\index.php on line 32 and exactly 1 expected in C:\OSPanel\domains\localhost\src\MyProject\Controllers\ArticlesController.php on line 22
( ! ) ArgumentCountError: Too few arguments to function MyProject\Controllers\ArticlesController::view(), 0 passed in C:\OSPanel\domains\localhost\index.php on line 32 and exactly 1 expected in C:\OSPanel\domains\localhost\src\MyProject\Controllers\ArticlesController.php on line 22
Вы говорили использовать дебаг, но в каком файле - теперь то их куча. Попробовал поставить красную точку в начале каждого файла и перезапускать страницу - ничего не дало.
P.S. и еще у меня проблема с обратными слешами. Приходиться извращаться например так чтобы все работало
public function __construct()
{
$this->view = new View('C:\OSPanel\domains\localhost\src\templates');
$this->db = new Db();
}
и так
public function renderHtml(string $templateName, array $vars = [])
{
extract($vars);
ob_start();
include $this->templatesPath . '\\' . $templateName;
$buffer = ob_get_contents();
ob_end_clean();
echo $buffer;
}
Проблема в парсинге регулярки ноута, скорее всего. Не приходит второй аргумент. Напишите в личные сообщения в ВК или телеграме. Что-то много у вас проблем для решения в комментариях.
Оба решения вполне годные. Я бы предпочел второй вариант.
Но только назовите не article2, а nickname. Имя переменной должно отражать суть значения, которое в ней лежит.
Проверять есть ли автор, если есть статья я думаю не стоит, если не прав поправьте
и подумал что стоит получить все данные автора. Вдруг мы захотим еще что либо выводить на странице поста.
Е еще я где то пропустил почему нужно писать $user[0] а не $user?
Это чтоб выбирать по первому ключу?
public function view(int $articleId)
{
$result = $this->db->query(
'SELECT * FROM `articles` WHERE id = :id;',
[':id' => $articleId]
);
if ($result=== []){
$this->view->renderHtml('errors/404.php', [], 404);
return ;
}
$user = $this->db->query(
'SELECT * FROM `users` WHERE id = :id;',
[':id' => $result[0]['author_id']]
);
$this->view->renderHtml('articles/view.php', [
'article' => $result[0],
'users' => $user[0]
]
);
}
для вьюхи
<?php include __DIR__ . '/../header.php'; ?>
<h1><?= $article['name'] ?></h1>
<p><?= $article['text'] ?></p>
<p><?= $users['nickname'] ?></p>
<?php include __DIR__ . '/../footer.php'; ?>
$query = $this->db->query('SELECT nickname FROM `users`
WHERE `id` IN ( SELECT author_id FROM `articles` WHERE id = :id );',
[':id' => $articleId]
);
Зачем второй раз делаете запрос статьи? У вас уже есть id пользователя в $result.
// $this->view->renderHtml('articles/view.php',
Не присылайте бесполезные комментарии в ДЗ. В рабочем коде их быть не должно.
if ($query === []) {
$this->view->renderHtml('errors/404.php', [], 404);
return;
}
То, что автор не найден, не означает, что на сайте нет статьи, и что нужно показывать 404 ошибку. Придумайте корректное поведение, которое позволит пользователям читать статьи на сайте, даже если автора найти не удалось.
Так я знаю что в articles есть id, и думал зачем ещё один запрос, но в ДЗ было написано чтобы сделать ещё один запрос для вывода автора. Проста из-за этого не так понял
Не понял вопроса. Говоришь, что с запросом всё понятно. Что с передачей в шаблон всё понятно. Непонятно только что происходит после запроса. Но после запроса идёт передача в шаблон и между ними ничего нет. И вообще код отличный. В чем проблема?)
Не полностью осилил задание,сам запрос я написал нормально,только вот смотрю,как люди делают,и немного не понимаю вот эту часть [':id' => $result[0]['author_id']] мы этой частью как-бы передаём в массиве номер автора,по которому отправляем запрос, например автор 1- admin,автор 2-user?
Долго провозился с использованием переменной в запросе
Автора стоит получать только после того, как проверили что массив не пустой.
В экшне ArticlesController::view() после получения статьи, добавьте ещё один запрос на получение автора этой статьи из таблицы users. Выведите nickname автора в шаблоне.
С помощью Join соединил две таблички и без лишних обращений к базе забрал себе пользователей, дополнительно в списке статей тоже вывел авторов. Курс по БД прошел не зря=)
Хорошо, так тоже можно)
А почему использовали LEFT JOIN?
Да как-то так придумалось) Неверно?
Нужно понимать разницу между разными типами JOIN-ов - прочитайте о них. Конкретно здесь должен быть INNER JOIN.
Хорошо!
ArticlesController
view
Отлично!
на участке:
renderHtml должен принимать на вход два аргумента, и при таком коде у меня ошибка, исправил на:
Вопрос почему у вас работает иначе)?
А можно увидеть функцию renderHtml ? второй аргумент должен иметь дефолтное значение, ощущение что у Вас он не задан, но могу ошибаться)
Привет! Вот код:
Второй аргумент по умолчанию равен пустому массиву.
Да действительно упустил
Спасибо
Сделал так
И есть один вопрос, View на вход принимает $articleId, так вот мне не совсем понятно каким образом эта переменная задается ив какой именно момент она получает свои значения "1" "2"
Норм сделал. То что и нужно было.
Там снизу еще вопрос есть)
Не понял вопроса. Напиши по нему лучше в личку в телеге.
ArticlesController.php
view.php
Лучше не засовывать автора внутрь статьи. Пусть пробрасывается отдельной переменной.
Ок)
В предыдущих уроках header и footer лежали тут:
а в этом переехали в
Для коллекции решений, автора получим в основном запросе выборкой из двух баз и дополнительно электронную почту автора , отдельным запросом с выводом в отдельную переменную:
Отлично!
ArticlesController.php
view.php
Так можно решить?
Это не очень правильно, потому что у $article не должно быть nickname и других полей пользователя.
Мы столько учили классы и наследования, можем ли мы тут их применить, как это к примеру сделал я?
этим мы вроде как слегка оптимизировали код, убрали
если будет много контроллеров, сделать абстрактный класс, со всеми этими VIew и подклечениями к бд, и от него уже наследоваться. Хотя я может просто бегу впереди паровоза))
Да. Отлично! Если уверен, что все контроллеры будут содержать этот код - то твой вариант правильный.
ArticlesController
view
Не надо так. Можно просто завести переменную $nickname в самом начале метода со значением 'Автор не найден'. Если после запроса он есть, то переопределять эту переменную. И в renderHtml передавать её.
С помощью комментариев получилось добиться рабочего кода, но где то я что недопонял видимо и теперь немного не понимаю как происходит вывод статей, попробую проходить дальше, если так же не будет доходить, придётся назад возвращаться и перечитывать по новой)
Прочитайте мой ответ выше. Аналогичные пожелания.
view.php
Отлично
ArticlesController.php
view.php
Отлично!
Отлично
Все нормально по адресу http://localhost/articles/1 я вижу "Здесь будет получение статьи и рендеринг шаблона".
Стоит изменить эту функцию на
И я снова получаю ту ошибку, о которой писал ранее:
Вы говорили использовать дебаг, но в каком файле - теперь то их куча. Попробовал поставить красную точку в начале каждого файла и перезапускать страницу - ничего не дало.
P.S. и еще у меня проблема с обратными слешами. Приходиться извращаться например так чтобы все работало
и так
Проблема в парсинге регулярки ноута, скорее всего. Не приходит второй аргумент. Напишите в личные сообщения в ВК или телеграме. Что-то много у вас проблем для решения в комментариях.
Решение №1, быдлокод :))) просто оно мне первое в голову пришло...
+ в view.php
Говнокод №2 :)) мне кажется опять не правильно... ну как неправильно - данные то выводит, но вероятно не по стандартам написано
+ в view.php
прошу критики...
Оба решения вполне годные. Я бы предпочел второй вариант.
Но только назовите не article2, а nickname. Имя переменной должно отражать суть значения, которое в ней лежит.
Ух ты! Спасибо, не ожидал! Начинает получаться значит :))
Видимо)
Проверять есть ли автор, если есть статья я думаю не стоит, если не прав поправьте
и подумал что стоит получить все данные автора. Вдруг мы захотим еще что либо выводить на странице поста.
Е еще я где то пропустил почему нужно писать $user[0] а не $user?
Это чтоб выбирать по первому ключу?
user[0] - потому что из query тебе вернётся массив записей.
Тут должен быть $user, потому что он там один.
А в остальном - всё супер.
Спасибо, теперь понял!
Controller:
VIEW:
Отлично
Долго мучался, но вроде разобрался)
ArticlesController.php
view.php
Отлично!
Ошибка здесь:
Сможете найти?
не не нашел, а что здесь не так?
Ищете пользователя по id. Вместо id пользователя передаёте id статьи.
Зачем второй раз делаете запрос статьи? У вас уже есть id пользователя в $result.
Не присылайте бесполезные комментарии в ДЗ. В рабочем коде их быть не должно.
То, что автор не найден, не означает, что на сайте нет статьи, и что нужно показывать 404 ошибку. Придумайте корректное поведение, которое позволит пользователям читать статьи на сайте, даже если автора найти не удалось.
Так я знаю что в articles есть id, и думал зачем ещё один запрос, но в ДЗ было написано чтобы сделать ещё один запрос для вывода автора. Проста из-за этого не так понял
Ну так запрос для получения пользователя всё равно нужен. Непонятно, зачем вы внутри него снова за статьей идёте.
ArticlesController.php:
articles/view.php:
Отлично! Образцовая домашка.
Отлично
ArticlesController.php
templates/articles/view.php
Отлично
Отлично!
Рабочий получилось сделать, но немного с логикой запутался. Поправьте , если мыслю не совсем верно.
Создаем переменную $resultAuthor. Аргументы у нас на входе запрос($sql) и массив(params=[]).
Дальше не понимаю , что происходит((( .
Не понял вопроса. Говоришь, что с запросом всё понятно. Что с передачей в шаблон всё понятно. Непонятно только что происходит после запроса. Но после запроса идёт передача в шаблон и между ними ничего нет. И вообще код отличный. В чем проблема?)
Не полностью осилил задание,сам запрос я написал нормально,только вот смотрю,как люди делают,и немного не понимаю вот эту часть [':id' => $result[0]['author_id']] мы этой частью как-бы передаём в массиве номер автора,по которому отправляем запрос, например автор 1- admin,автор 2-user?
Всё,разобрался,что-то я тупанул,как запрос будет знать,какой id из массива мы запрашиваем,если мы этого не указываем) под вечер уже мозги кипят.
Бывает)
view.php
ArticlesController.php
Отлично
А если я сделал запрос такого вида,как мне подставить нужный параметр в users.id ?
Запрос некорректный в принципе.