Комментарии к публикации
View в MVC

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

<?php

namespace MyProject\Controllers;
use MyProject\View\View;
class MainController
{
    private $view;

    public function __construct()
    {
        $this->view = new View(__DIR__ . '/../../../templates');
    }

    public function main()
    {
        $articles = [
            ['name' => 'Статья 1', 'text' => 'Текст статьи 1'],
            ['name' => 'Статья 2', 'text' => 'Текст статьи 2'],
        ];
        $title = '';
        $this->view->renderHtml('main/main.php', ['articles' => $articles], $title);
    }

    public function sayHello(string $name)
    {
        $title = 'Страница приветствия';
        $this->view->renderHtml('main/hello.php', ['name' => $name], $title);
    }
}

// View.php 

<?php

namespace MyProject\View;
class View
{
    private $templatesPath;

    public function __construct(string $templatesPath)
    {
        $this->templatesPath = $templatesPath;
    }

    public function renderHtml(string $templateName, array $vars = [], string $title)
    {
        extract($vars);

        ob_start();
        include $this->templatesPath . '/' . $templateName;
        $buffer = ob_get_contents();
        ob_end_clean();

        echo $buffer;
    }
}

// header.php

    <?php 
    if (!empty($title)) {
        $title;
    } else {
    $title = 'Мой блог';
} ?>
    <title><?= $title ?></title>
ivashkevich 01.09.2018 в 19:09

А зачем вам еще один параметр? Можно же title положить в vars, просто еще одно значение.
Выводить можно проще:

<title><?= $title ?? 'Мой блог' ?></title>
Sparkqy 05.09.2018 в 13:10

Переменную $title передаю из MainController в renderHtml (в массив $vars). Все работает, но не получается вывести <title> при пустом значении $title. Вывожу так:
<title><?= $title ?? "Мой блог" ?></title>

Если делать проверку if (empty($title)), то выводит что надо. Почему <?= $title ?? "Мой блог" ?> не работает?

ivashkevich 05.09.2018 в 23:47

Оператор ?? работает только с null-ом. Значит там не null, попробуй через var_dump узнать, что в переменной лежит. Скорее всего у тебя там пустая строка =)

Sparkqy 06.09.2018 в 14:35

О, да, так и есть. Не знал про Null :)

computerix 24.09.2018 в 08:49
//routes
<?php
return [
    '~^hello/(.*)$~' => [\MyProject\Controllers\MainController::class, 'sayHello'],
    '~^bye/(.*)$~' => [\MyProject\Controllers\MainController::class, 'sayBye'],
    '~^$~' => [\MyProject\Controllers\MainController::class, 'main'],
    '~(.*)$~' => [\MyProject\Controllers\MainController::class, 'title'],
];

//MainController
<?php
namespace MyProject\Controllers;

use MyProject\View\View;

class MainController
{
    private $view;

    public function __construct()
    {
        $this->view = new View( __DIR__ . '/../../../templates' );
    }

    public function main()
    {
        $articles = [
            ['name' => 'Статья 1', 'text' => 'Текст статьи 1'],
            ['name' => 'Статья 2', 'text' => 'Текст статьи 2'],
        ];
        $this->view->renderHtml('main/main.php', ['articles' => $articles]);
    }
    public function sayHello(string $name)
    {
        $this->view->renderHtml('main/hello.php', ['name' => $name]);
    }
    public function sayBye(string $name)
    {
        $this->view->renderHtml('main/bye.php', ['name' => $name]);
    }
    public function title(string $title)
    {
        $articles = [
            ['name' => 'Статья 1', 'text' => 'Текст статьи 1'],
            ['name' => 'Статья 2', 'text' => 'Текст статьи 2'],
        ];
       $this->view->renderHtml('main/main.php', ['title' => $title, 'articles' => $articles]);
    }
}

//main
<? if (empty($title)) {$title = 'Мой блог';} ?>
<title><?= $title ?></title>
<?php include __DIR__ . '/../header.php'; ?>
<?php foreach ($articles as $article): ?>
    <h2><?= $article['name'] ?></h2>
    <p><?= $article['text'] ?></p>
    <hr>
<?php endforeach; ?>
<?php include __DIR__ . '/../footer.php'; ?>

//hello
<title>Страница приветствия</title>
<?php include __DIR__ . '/../header.php'; ?>
Привет, <?= $name ?>!!!
<?php include __DIR__ . '/../footer.php'; ?>
ivashkevich 24.09.2018 в 23:10

Вся домашка заключалась в следующем:

  • в шаблоне header.php добавить:
    <title><?= $title ?? 'Мой блог' ?></title>
  • в экшене sayHello() сделать следующее:
    public function sayHello(string $name)
    {
    $this->view->renderHtml('main/hello.php', ['name' => $name, 'title' => 'Страница приветствия']);
    }

Возможно, я плохо сформулировал домашнее задание, если это так, напишите мне в ВК, подумаем, как сделать лучше.

Если же вам просто захотелось поэкспериментировать - то всё в порядке =)

computerix 25.09.2018 в 05:14

Все оказалось проще, чем я понял) Я ещё подумал, что сложноватая домашка, но зато разобрался хорошо, пока делал)

artemjeka 17.10.2018 в 09:26

Я написал в /src/MVCExample/Views/View.php

public function renderHtml(string $templateName, array $vars)

Обязательно ли писать:

array $vars = []
ivashkevich 19.10.2018 в 00:17

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

artemjeka 20.10.2018 в 07:02

Понял, спасибо.

artemjeka 17.10.2018 в 10:53

Учитель, почему у меня не подключаются стили если я перехожу на /hello/Name?
code github

PS
У меня структура локального сайта построена как учебник с папками по этому дирректория с фронтальным контроллером такая:

http://php_book/mvc/www/index.php
ivashkevich 19.10.2018 в 00:19

Открой консоль разработчика, посмотри вкладку networks. Там будет видно, откуда браузер пытается грузить стили.

artemjeka 20.10.2018 в 06:57

Я так понял у нас localhost подключен к www?
И тогда подключая стили через / корневой слеш мы не ошибаемся и попадаем сначала в www дирректорию.

ivashkevich 20.10.2018 в 10:06

www - должна быть корневой директорией сайта. И если в браузере пишем /что-то там, то веб сервер будет искать именно в папке www. Как и index.php в этой папке является точкой входа в приложение.

SBTesla 17.10.2018 в 12:29
//header.php
<title><?= $title ?? 'Мой блог-жек'?></title>

//routes.php
return[
      '~^hello/(.*)$~' => [\MyProject\Controllers\MainController::class, 'sayHello'],
      '~^$~' => [MyProject\Controllers\MainController::class, 'main'],
      '~^bye/(.*)$~' => [MyProject\Controllers\MainController::class, 'sayBye'],
     '~(.*)$~'=>[MyProject\Controllers\MainController::class, 'sayHello']
      ];

//MainController.php

namespace MyProject\Controllers;

use MyProject\View\View;

class MainController
     {
          private $view;

          public function __construct()
          {
               $this->view = new View(__DIR__ . '/../../../templates');
          }

     public function main()
          {

               $articles = [
                     ['name' => ' Статья 1 ', 'text' => ' Текст статьи 1'],
                    ['name' => ' Статья 1 ', 'text' => ' Текст статьи 2'],
               ];
               include __DIR__ . '/../../../templates/main/main.php';
          }
          public function sayHello(string $name)
          {
               $this->view->renderHtml('main/hello.php', ['name' => $name, 'title' => 'Страница приветствия']);
          }

          public function sayBye(string $name)
          {
               echo 'Досвидания, ' . $name;
          }

     }
ivashkevich 19.10.2018 в 00:19

Супер! =)

artemjeka 20.10.2018 в 09:30
// MainController.php
public function sayHello(string $name)
    {
        $this->view->renderHtml('main/hello.php', ['name' => $name, 'title' => 'Страница приветствия']);
    }
// header.php
<title><?=$title ?? 'Мой блог'?></title>
ivashkevich 20.10.2018 в 10:07

Отлично!

AxLT 01.11.2018 в 23:10

Почему так работает:

<?= $title ?? 'Мой блог' ?>

а так нет?

<?php $title ?? 'Мой блог' ?>
ivashkevich 02.11.2018 в 01:24

<?=... - это сокращение для <?php echo...

stokato 07.11.2018 в 12:59

Сделайте чтобы title для каждой страницы можно было задавать через переменную для шаблона. В случае, когда title не передан, выводите заголовок по умолчанию - "Мой блог". Для страницы /hello/username сделайте title "Страница приветствия".

//header.php
<!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <title><?= $title ?? 'Мой блог'; ?></title>
    <link rel="stylesheet" href="/styles.css">
</head>
<body>

<table class="layout">
    <tr>
        <td colspan="2" class="header">
            Мой блог
        </td>
    </tr>
    <tr>
        <td>
//MainController.php
public function sayHello(string $name)
    {
        $this->view->renderHtml('main/hello.php', ['name' => $name, 'title' => 'Страница приветствия']);
    }
ivashkevich 08.11.2018 в 10:37

То что нужно!

Todd 08.11.2018 в 00:57

MainController

 public function sayHello(string $name) {
        $this->view->renderHtml('main/hello.php', ['name' => $name, 'title' => 'Страница приветствия']);
    }

header

<title><?= $title ?? 'my blog' ?></title>
ivashkevich 08.11.2018 в 10:38

Отлично! Не забывайте переносить для функций открывающую фигурную скобку на отдельную строку.

bildep 18.11.2018 в 18:21

MainController.php

<?php
namespace MyProject\Controllers;

use MyProject\View\View;

class MainController
{

    private $view;

    public function __construct()
    {
        $this->view = new View(__DIR__ . '/../../../templates');
    }

    public function main()
    {
        $articles = [
            ['name' => 'Статья 1', 'text' => 'Текст статьи 1'],
            ['name' => 'Статья 2', 'text' => 'Текст статьи 2'],
        ];
        $this->view->renderHtml('main/main.php', ['articles' => $articles]);
    }

    public function sayHello(string $name)
    {

        $this->view->renderHtml('main/hello.php', ['name' => $name, 'title' => "Страница приветствия" ]);
    }

    public function sayBye(string $name)
    {
        echo 'Пока, ' . $name;
    }
}

header.php

<!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <title><?=$title ?? 'Мой блог';?></title>
    <link rel="stylesheet" href="/styles.css">
</head>
<body>

<table class="layout">
    <tr>
        <td colspan="2" class="header">
            Мой блог
        </td>
    </tr>
    <tr>
        <td>
ivashkevich 19.11.2018 в 21:53

Ты за пару дней решил весь курс пройти?) Супер-прогресс! Программировал до этого?

virtual2018 26.12.2018 в 10:19

MainController.php

    public function sayHello(string $name)
    {
        $this->view->renderHtml('main/hello.php', ['name' => $name, 'title' => 'Страница приветствияs']);
}

header.php

    <title><?= $title ?? 'Мой блог'?></title>
ivashkevich 26.12.2018 в 23:37

Отлично!

alepawka 02.01.2019 в 11:24

не понятно про
renderHtml('main/main.php', ['articles' => $articles]);
зачем тут массив? я так и не понял
и для чего применять extract в методе renderHTML??

ivashkevich 02.01.2019 в 21:28

extract из ключей массива делает переменные. Внутри метода renderHtml после вызова extract появится переменная $articles, значением которой будет значение элемента массива.

alepawka 02.01.2019 в 12:03
<title><?= $title ?? 'Мой блог ?>'</title> //header.php
$this->view -> readerHTML('/main/hello.php',['name' => $name],'title' = 
                'Страница приветствия']);//maincontroller.php
ivashkevich 02.01.2019 в 21:28

Не работает.

alepawka 04.01.2019 в 07:53

$this->view -> readerHTML('/main/hello.php',['name' => $name],'title' =>
'Страница приветствия']);

ivashkevich 04.01.2019 в 08:55

Я вижу что не работает, даже не запуская. Вы себя пытаетесь обмануть?)

Bogdan 10.01.2019 в 17:48
$this->view -> readerHTML('/main/hello.php',['name' => $name],'title' =>
'Страница приветствия']);

если я правильно понял, то у тебя закрыта скобка после => $name], а дальше пошла фигня))

ivashkevich 11.01.2019 в 11:09

Именно)

virtual2018 02.01.2019 в 15:10

Вопрос по примеру с обработкой ошибки, в этом коде

public function renderHtml(string $templateName, array $vars = [])
{
    extract($vars);

    ob_start();
    include $this->templatesPath . '/' . $templateName;
    $buffer = ob_get_contents();
    ob_end_clean();

    $error = 'В шаблоне была ошибка!';

    if (empty($error)) {
        echo $buffer;
    } else {
        echo $error;
    }
}

всегда будет сообщение об ошибке в шаблоне, так как мы "влоб" указали $error. Как узнать, что в шаблоне ошибка?

ivashkevich 02.01.2019 в 21:29

Просто передавайте её через переменные для шаблона, при вызове renderHtml

landialog 06.01.2019 в 23:09

Честно говоря запутался. Решение в комментах уже видел, но сам бы не сделал.
Не понятно как title с контроллера попадает в шаблон header.php, ведь передача идет на main.php?
Почему title сделали в методе sayHello?
Есть схожесть передачи переменных в шаблон (на фр.ворке Laravel). Но там как-то изящнее

ivashkevich 06.01.2019 в 23:14
  1. header подключается внутри main и переменная в нём доступна.
  2. Данные из контроллера передаются в шаблон, непонятен ваш вопрос.
Bogdan 10.01.2019 в 17:08

MainController.php

<?php

namespace MyProject\Controllers;

use MyProject\View\View;

class MainController
{
    private $view;

    public function __construct()
    {
        $this->view = new View(__DIR__ . '/../../../templates');
    }

    public function main()
    {
        $articles = [
            ['name' => 'Статья 1', 'text' => 'Текст статьи 1'],
            ['name' => 'Статья 2', 'text' => 'Текст статьи 2'],
        ];
        $this->view->renderHtml('main/main.php', 'Мой блог', ['articles' => $articles]);
    }

    public function sayHello(string $name)
    {
        $this->view->renderHtml('main/hello.php', 'Страница приветствия' , ['name' => $name]);
    }

View.php

<?php

namespace MyProject\View;

class View
{
    private $templatesPath;

    public function __construct(string $templatesPath)
    {
        $this->templatesPath = $templatesPath;
    }

    public function renderHtml(string $templateName, string $title, array $vars = [] )
    {
        array_push($vars, $title);
        extract($vars); // в неё передаётся массив ['key1' => 1, 'key2' => 2, ...],
        //                 а после её вызова у нас имеются переменные $key1 = 1 и $key2 = 2, ... .

        ob_start();
        include $this->templatesPath . '/' . $templateName;
        $buffer = ob_get_contents(); // весь этот поток вывода положить во временный буфер вывода
        ob_end_clean();

        echo $buffer;
    }

}

main.php

<?php include __DIR__ . '/../headerTop.php'; ?>
    <title><?= $title ?></title>
<?php include __DIR__ . '/../headerBot.php'; ?>
<?php foreach ($articles as $article): ?>
    <h2><?= $article['name'] ?></h2>
    <p><?= $article['text'] ?></p>
    <hr>
<?php endforeach; ?>
<?php include __DIR__ . '/../footer.php'; ?>

hello.php

<?php include __DIR__ . '/../headerTop.php'; ?>
    <title><?= $title ?></title>
<?php include __DIR__ . '/../headerBot.php'; ?>
    Привет, <?= $name ?>!!!
<?php include __DIR__ . '/../footer.php'; ?>
ivashkevich 11.01.2019 в 11:13

Зачем два header-а и между ними вывод $title? Не нужно ещё один аргумент в renderHtml. Используйте существующие.

Bogdan 11.01.2019 в 21:32

я изначально думал что надо разбить еще хедер на 2 части, что б вынести title (а разметку оставить нетронутой, и потом не искать где и что выводится), так как мы сделали с хедером и футером, потом уже посмотрел как делали другие и все исправил. Спасибо

excent63 14.02.2019 в 12:04

Добрый день!
Вот решение дз:

//header.php
<title><?=$title ?? 'Мой блог';?></title>

//MainController.php
public function sayHello(string $name)
    {
        $this->view->renderHtml('main/hello.php',['name'=>$name, 'title'=> 'Страница приветствия!']);
    }
ivashkevich 17.02.2019 в 21:59

Отлично!

[email protected] 15.03.2019 в 15:29

я,может, чего не понял, но как в самом начале при переходе по http://myproject.loc/, нам выдает страницу с блогом,если блог находится в другой директории, а в контроллере мы просто включили этот файл

ivashkevich 17.03.2019 в 23:23

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

Alexander 23.03.2019 в 22:27

Изначально не полностью понял про extract и создавал сначала переменную(как в коде снизу), а потом передавал в массив $vars, но после по комментам понял, что можно прямо так. Да и в статье ведь написано, что создается переменная из ключа.. Но да ладно, хоть разобрался) Спасибо за урок)

// MainController.php

public function sayHello(string $name)
    {
        $title = 'Страница приветсвия';
        $this->view->renderHtml('main/hello.php', ['name' => $name, 'title' => $title]);
    }

    public function sayBye(string $name)
    {
        $title = 'Страница прощания';
        $this->view->renderHtml('main/bye.php', ['name' => $name, 'title' => $title]);
    }

// header.php

<!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <title><?= $title ?? 'Мой блог' ?></title>
    <link rel="stylesheet" href="/styles.css">
</head>
<body>

<table class="layout">
    <tr>
        <td colspan="2" class="header">
            <?= $title ?? 'Мой блог' ?>
        </td>
    </tr>
    <tr>
        <td>
ivashkevich 23.03.2019 в 22:36

Отличный код =)

Evgeny 24.03.2019 в 00:10

<?php

namespace MyProject\Controllers;

use MyProject\View\View;

class MainController
{
    private $view;

    public function __construct()
    {
        $this->view = new View(__DIR__ . '/../../../templates/');
    }

    public function main(): void
    {
        $articles = [
            ['name' => 'Статья 1', 'text' => 'Текст статьи 1'],
            ['name' => 'Статья 2', 'text' => 'Текст статьи 2'],
        ];

        $this->view->renderHtml('main/main.php', ['articles' => $articles]);
    }

    public function sayHello(string $name): void
    {
        $this->view->renderHtml('main/hello.php', ['name' => $name, 'title' => 'Страница приветствия']);
    }
}

Header.php


<!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <title><?= $title ?: 'Мой блог'; ?></title>
    <link rel="stylesheet" href="/styles.css">
</head>
<body>

<table class="layout">
    <tr>
        <td colspan="2" class="header">
            Мой блог
        </td>
    </tr>
    <tr>
        <td>
ivashkevich 24.03.2019 в 00:24

Отлично

CarfikDK 26.03.2019 в 17:10

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

heder.php

<title> <?= $title ?? 'Мой блог'; ?> </title>

MainController.php

public function sayHello(string $name)
    {
        $this->view->renderHtml('main/hello.php', ['name' => $name, 'title' => 'Страница приветствия']);
    }
ivashkevich 27.03.2019 в 11:38

Отлично

[email protected] 04.04.2019 в 11:54
public function renderHtml(string $templateName, array $vars = [], string $title)
    {
        if ($title === null || empty($title)) {
            $title = "Мой блог";
        }
        extract($vars);

        ob_start();
        include $this->templatesPath . '/' . $templateName;
        $buffer = ob_get_contents();
        ob_end_clean();

        echo $buffer;

    }

<!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <title><?= $title ?></title>
    <link rel="stylesheet" href="../styles.css">
</head>
<body>

<table class="layout">
    <tr>
        <td colspan="2" class="header">
            Мой блог
        </td>
    </tr>
    <tr>
        <td>
ivashkevich 05.04.2019 в 11:14

Зачем отдельный параметр, если есть vars?

[email protected] 16.02.2020 в 12:08

Исправил.
View.php

public function renderHtml(string $templateName, array $vars = [])
    {
        extract($vars);
        if ($vars['title'] == null) {
            $title = 'Мой блог';
        }

        ob_start();
        include $this->templatesPath . '/' . $templateName;
        $buffer = ob_get_contents();
        ob_end_clean();

        echo $buffer;
    }

MainController.php

<?php

namespace MyProject\Controllers;
use MyProject\View\View;

class MainController
{
    private $view;

    public function __construct()
    {
        $this->view = new View(__DIR__ . '/../templates');
    }

    public function main()
    {
        $articles = [
            ['name' => 'Статья 1', 'text' => 'Текст статьи 1'],
            ['name' => 'Статья 2', 'text' => 'Текст статьи 2'],
        ];

        $this->view->renderHtml('main/main.php', ['articles' => $articles]);
    }

    public function sayHello(string $name)
    {
        $this->view->renderHtml('main/hello.php', ['name' => $name, 'title' => 'Страница приветствия']);
    }

    public function sayBye(string $name) {
        echo 'Пока, '. $name;
    }
}
ivashkevich 18.02.2020 в 18:15
        extract($vars);
        if ($vars['title'] == null) {
            $title = 'Мой блог';
        }

Не нужно городить костыли на этом уровне. Зачем рендереру HTML знать об отдельно взятых переменных? Правильнее написать в шаблоне:

<title><?= $title ?? 'Мой блог' ?></title>
Boodoo 14.04.2019 в 17:39

View.php

<?php
    namespace MyProject\View;

    class View
    {
        private $templatesPath;

        public function __construct(string $templatesPath)
        {
            $this->templatesPath = $templatesPath;
        }

        public function renderHtml(string $templateName, array $vars = [], string $title = 'Мой блог')
        {
            extract($vars);

            ob_start();
            include $this->templatesPath . '\\' . $templateName;
            $buffer = ob_get_contents();
            ob_end_clean();

            echo $buffer;
        }
    }

MainController.php

<?php
    namespace MyProject\Controllers;

    use MyProject\View\View;

    class MainController
    {
        private $view;

        public function __construct()
        {
            $this->view = new View(__DIR__ . '/../../templates');
        }

        public function main()
        {
            $articles = [
                ['name' => 'Статья 1', 'text' => 'Текс статьи 1'],
                ['name' => 'Статья 2', 'text' => 'Текс статьи 2']
            ];
            $this->view->renderHtml('main/main.php', ['articles' => $articles]);
        }

        public function sayHello(string $name)
        {
            $this->view->renderHtml('main/hello.php', ['name' => $name], 'Страница приветствия');
        }
    }

header.php

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title><?= $title ?></title>
    <link rel="stylesheet" href="/styles.css">
</head>
<body>
<table class="layout">
    <tr>
        <td colspan="2" class="header">
            Мой блог
        </td>
    </tr>
    <tr>
        <td>
ivashkevich 15.04.2019 в 08:09

Не нужно для тайтла делать третий аргумент. Смотрите решения выше.

Boodoo 15.04.2019 в 14:18

header.php

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title><?= $title ?? 'Мой блог' ?></title>
    <link rel="stylesheet" href="/styles.css">
</head>
<body>
<table class="layout">
    <tr>
        <td colspan="2" class="header">
            Мой блог
        </td>
    </tr>
    <tr>
        <td>

MainController.php

.....
public function sayHello(string $name)
        {
            $this->view->renderHtml('main/hello.php', ['name' => $name, 'title' => 'Страница приветствия']);
        }
ivashkevich 15.04.2019 в 14:27

Ок!

polvanovv 07.05.2019 в 09:47

MainController.php

 public function main()
    {
        $articles =[
            ['name' => 'Article 1', 'text' => 'Text of article 1'],
            ['name' => 'Article 2', 'text' => 'Text of article 2'],
        ];
        $this->view->renderHtml('main/main.php', ['articles' => $articles , 'title' => 'My blog']);
    }

    public function sayHello(string  $name)
    {
        $this->view->renderHtml('main/hello.php', ['name' => $name , 'title' => 'Welcome page']);
    }

header.php

  <meta charset="UTF-8">
    <title><?= $title ?></title>
    <link rel="stylesheet" href="/Myproject/templates/main/style.css">
ivashkevich 10.05.2019 в 13:29

Не хватает тайтла по умолчанию, пересмотрите ДЗ повнимательнее.

Dram 13.05.2019 в 20:26

К сожалению не могу продолжать делать домашку, так и не смог победить баг из прошлого урока.
У меня на странице http://localhost/hello/username

ошибка
) Fatal error: Uncaught ArgumentCountError: Too few arguments to function MyProject\Controllers\MainController::sayHello(), 0 passed in C:\OSPanel\domains\localhost\index.php on line 32 and exactly 1 expected in C:\OSPanel\domains\localhost\src\MyProject\Controllers\MainController.php on line 26

хотя все остальное работает.

ivashkevich 13.05.2019 в 23:13

Проверьте дебаггером. Теряется аргумент где-то.

ashfedor 13.06.2019 в 13:40

в header.php

<title><?= $title ?? 'Мой блог' ?></title>

в MainController.php

public function sayHello(string $name)
    {
        $this->view->renderHtml('main/hello.php', [
                'name' => $name,
                'title' => 'Приветствие пользователя' 
            ]
        );
    }

вроде все!

ivashkevich 13.06.2019 в 19:49

Отлично!

Moskva 10.07.2019 в 15:18

Сначала не понял, как требуется сделать домашку, потом подсмотрел и разобрался:)
MainController.php

public function sayHello(string $name){
        $this->view->renderHtml('main/hello.php', ['name' => $name , 'title' => 'Страница приветствия']);
    }

header.php

<!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <title><?= $title ?? 'Мой блог'?></title>
    <link rel="stylesheet" href="/style.css">
</head>
<body>
<table class="layout">
    <tr>
        <td colspan="2" class="header">
            <?= $title ?? 'Мой блог'?>
        </td>
    </tr>
    <tr>
        <td>
ivashkevich 12.07.2019 в 05:31

Отлично! Подсматривать можно)

Invo 11.07.2019 в 22:45

header.php:

<head>
    <meta charset="UTF-8">
    <title>
        <?= $title ?? "Мой блог" ?>
    </title>
    <link rel="stylesheet" href="/styles.css">
</head>

MainController:

<?php

namespace MyProject\Controllers;

use MyProject\View\View;

class MainController
{
    private $view;

    public function __construct()
    {
        $this->view = new View(__DIR__ . '/../../../templates');
    }

    public function main()
    {
        $articles = [
            ['name' => 'Статья 1', 'text' => 'Текст статьи 1'],
            ['name' => 'Статья 2', 'text' => 'Текст статьи 2']
        ];
        $this->view->renderHtml('main/main.php', ['articles' => $articles]);
    }

    public function sayHello(string $name)
    {
        $this->view->renderHtml('main/hello.php',['name' => $name, 'title' => 'Страница приветствия']);
    }

    public function sayBye(string $name)
    {
        echo 'Bye ' . $name;
    }
}
ivashkevich 12.07.2019 в 05:42

Отлично!

Вот тут нужно использовать одинарные кавычки.

<?= $title ?? "Мой блог" ?>
Iliusha99 20.07.2019 в 14:43

описание картинкиописание картинки
Поможете пути разобрать, а то ни как ни подключается файл styles.css

ivashkevich 20.07.2019 в 14:45

Напиши в личку

Metey 20.07.2019 в 17:20
<?php

namespace MyProject\Controllers;

use MyProject\View\View;

class MainController
{
    private $view;

    public function __construct()
    {
        $this->view = new View(__DIR__ . '/../../../templates');
    }

    public function main()
    {
        $articles = [
            ['name' => 'Статья 1', 'text' => 'Текст статьи 1'],
            ['name' => 'Статья 2', 'text' => 'Текст статьи 2'],

        ];

        $this->view->renderHtml('main/main.php', ['articles' => $articles]);
    }

    public function sayHello(string $name)
    {
        $this->view->renderHtml('main/hello.php', ['name' => $name, 'title' => 'Страница приветствия']);
    }
}

<!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <title><?= $title ?? 'Мой блог' ?></title>
    <link rel="stylesheet" href="/styles.css">
</head>
<body>
...........
ivashkevich 21.07.2019 в 05:16

Отлично

Iliusha99 20.07.2019 в 20:04

Очень интересно)), особенно когда в конструкторе контролера создаем объект View где сразу же вызывается и его конструктор.

Iliusha99 20.07.2019 в 20:29
Controller:
...
public function main()
    {

        $title = [ 'title' => 'Мой блог' ];

        $articles = [
            ['name' => 'Статья 1', 'text' => 'Текст статьи 1'],
            ['name' => 'Статья 2', 'text' => 'Текст статьи 2'],
        ];

        $this->view->renderHtml('main/main.php', ['articles' => $articles, 'page_title' => $title]);
    }

    public function sayHello(string $name)
    {
        $title = [ 'title' => 'Страница приветствия' ];
        $this->view->renderHtml('main/hello.php', ['name' => $name, 'page_title' => $title]);
    }
...
========================================
header.php :
<!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <title><?=$page_title['title'] ?? 'Мой блог';?></title>
    <link rel="stylesheet" href="/styles.css">
</head>
<body>

<table class="layout">
    <tr>
        <td colspan="2" class="header">
            <?=$page_title['title'] ?? 'Мой блог';?>
        </td>
    </tr>
    <tr>
        <td>
==============================
Вмешательство в View даже не потребовалось, круто)
ivashkevich 21.07.2019 в 05:18

Всё отлично, только зачем оборачивать title в ещё один массив?
$page_title['title']
Нужно, чтобы в шаблоне просто был $title

Iliusha99 21.07.2019 в 10:15

Нужно как в примерах выше проста в параметрах передавать без оборачивания в массив? Не знаю, мне такое пришло на ум, и понятнее.

ivashkevich 21.07.2019 в 14:23

Что же в этом понятнее? Простая строка для заголовка страницы - первое что приходит на ум.

Iliusha99 21.07.2019 в 14:40

Тесть вы имеете ввиду что лучше передавать $title параметром по умолчанию со значением 'Мой блог'?

ivashkevich 21.07.2019 в 14:46

Нет. Передавать надо как-то так:

$this->view->renderHtml('main/hello.php', ['name' => $name, 'title' => 'Страница приветствия']);

Не нужно передавать в значение title массив. Просто строку.

Iliusha99 21.07.2019 в 14:50

Понятно, а если нам нужно как нибудь значение title поменять, для этого нам нужно переменная нет? Чтобы вручную не записать или как?

ivashkevich 21.07.2019 в 19:21

Сформулируй вопрос более понятно. Желательно с примером кода.

Iliusha99 21.07.2019 в 19:30
 public function sayHello($text){

        $this->view->renderHtml('main/hello.php',['introducing' => $text]);
    }

Здесь например, передаем через $text, и туда может тоже хотим передавать в зависимости что находится в $title.

ivashkevich 21.07.2019 в 19:32

Не вижу в примере $title.

ivashkevich 21.07.2019 в 19:35

Как я понял, вопрос в том, как передавать другие переменные в шаблон. Вот так:

    public function sayHello(string $name)
    {
        $this->view->renderHtml('main/hello.php',['name' => $name, 'title' => 'Страница приветствия']);
    }
Iliusha99 21.07.2019 в 19:42

да, но почему объезательно через строку 'Страница приветствия', почему нельзя через переменную которую можем получать ее например из функции чтобы было универсально.

ivashkevich 21.07.2019 в 19:45

Значение можно брать откуда угодно. Хоть напрямую из строки, хоть из переменной.

Iliusha99 21.07.2019 в 19:48

Понятно.

artemship 01.08.2019 в 18:05

В header.php стало так:

<title><?= $title ?? 'Мой блог' ?></title>

В MainController.php поправил экшн:

    public function sayHello(string $name)
    {
        $this->view->renderHtml(
            'main/hello.php',
            ['name' => $name, 'title' => 'Страница приветствия']
        );
    }
ivashkevich 01.08.2019 в 20:37

Отлично

khuurak 21.08.2019 в 03:55
public function sayHello(string $name)
    {
        $this->view->renderHtml('main/hello.php', ['name' => $name, 'title' => 'Страница приветствия']);
    }

<title><?= $title ?? 'Мой блог'; ?></title>
ivashkevich 22.08.2019 в 06:52

Отлично!

fosfat 30.08.2019 в 21:08

Артем, это не критика, а просто попытка новичка в php разобраться в примере. Может, я чего-то не понял:

Ты пишешь, цитата: «Если нам понадобится в другом контроллере или другом экшне добавить логику для работы с шаблонами, нам снова придется перечислять список переменных, а затем писать include с указанием полного пути для шаблона. Звучит не очень хорошо. Поэтому мы просто вынесем логику с подключением нужного шаблона в отдельный класс».

1) Если выйти за рамки учебного примера, то в реальности и не потребуется в методе «перечислять списки переменных», которые являются аналогом БД. Если брать данные из этого примера (заголовки / текст статьи, имя пользователя), то это все будет лежать в реальной БД. Соответственно, аргумент «нам снова придется перечислять список переменных» - не представляется чем-то логичным.

2) Ты пишешь, что, цитата: «нам снова придется… писать include с указанием полного пути для шаблона. Звучит не очень хорошо».

Почему не очень хорошо? Строчка include DIR . '/../../../templates/main/main.php'; КОРОЧЕ чем строчка из нового решения: $this->view->renderHtml('main/main.php', ['articles' => $articles]);

В чем здесь «оптимизация» процесса? Ведь точно также при подключении нового шаблона мы будем из раза в раз использовать эту еще более длинную строчку.

3) В целом разве можно назвать это решение целесообразным и рациональным?

Ты ведь наоборот, на мой взгляд, все усложнил. В первом простом варианте мы для подключения нового шаблона всего лишь создали бы новый метод, а теперь с предлагаемым тобой решением все то же самое плюс «сверху» новый класс с 2 методами, 1 свойством + метод-конструктор и 1 свойство в контроллере. Вопрос: зачем? И как это можно перенести в плоскость реальной разработки?

И еще момент: я сделал файловую структуру точно такую же, как у тебя в примере. При таком положении указанная тобой строчка <link rel="stylesheet" href="/styles.css"> не будет подключать файл со стилями. Даже phpstorm выделяет ее как ошибку «Cannot resolve file», т.е. работающий вариант <link rel="stylesheet" href="/www/styles.css">.

ivashkevich 31.08.2019 в 05:08

Если коротко - чем меньше ответственности у каждого класса, тем проще. Контроллер не должен знать о том, как рисовать шаблоны. Он просто начинает использовать View для этого.

ivashkevich 31.08.2019 в 05:10

А ты php-скрипты тоже с www в пути открываешь? Если да, то смотри курс для начинающих, урок про настройку OpenServer. PhpStorm может ошибаться.

Pro100Bah 05.09.2019 в 17:02

Мне кажется или мы создавали файл style.css , a не styles, в связи с этим у коллеги выше не подключаются стили.

P.S Поправьте меня, если я ошибаюсь, если нет в уроках необходимо убрать букву *****s.css) в этом уроке)

ivashkevich 05.09.2019 в 19:40

С такими проблемами на этом этапе обучения нужно разбираться самостоятельно. А в уроке всё ок.

[email protected] 18.04.2021 в 14:09

Умело ты абзац про обработку ошибок и исключения пропустил)
А вот путь к директории с шаблонами действительно можно переместить сразу во вьюшку, ведь он не меняется, и передавать его каждый раз нет смысла.

Pro100Bah 06.09.2019 в 12:19

Сначала как начал делать домашку, подумал нужно следовать алгоритму в конце урока:
"Давайте повторим последовательность шагов, которые необходимо сделать для добавления новой странички:
-Добавляем экшн в контроллер (либо создаём ещё и новый контроллер);
-Добавляем для него роут в routes.php;
-Описываем логику внутри экшена и в конце вызываем у компонента view метод renderHtml();
-Создаём шаблон для вывода результата.
"
Но потом понял, это для создания новой странички, а мы создаем переменную для шаблона.
Результат MainController.php

namespace MyProject\Controllers;

use MyProject\View\View;

class MainController
{
    private $view;

    public function __construct()
    {
        $this->view = new View(__DIR__ . '/../../../templates');
    }

    public function main()
    {
        $articles = [
            ['name' => 'Статья 1', 'text' => 'Текст статьи 1'],
            ['name' => 'Статья 2', 'text' => 'Текст статьи 2'],
        ];
        $this->view->renderHtml('main/main.php', ['articles' => $articles]);
    }

    public function sayHello(string $name)
    {
        $this->view->renderHtml('main/hello.php', ['name' => $name, 'title' => 'Страница приветствия']); //Homework 14
    }

    public function sayBye(string $name)            //Homework 13.2
    {
        echo 'Пакедова, дружище ' . $name;
    }
}

header.php

<!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <title><?= $title ?? 'Мой блог'; ?></title>    <!-- Homework 14 -->
    <link rel="stylesheet" href="/styles.css">
</head>
<body>

<table class="layout">
    <tr>
        <td colspan="2" class="header">
            Мой блог
        </td>
    </tr>
    <tr>
        <td>

Правильно я понимаю, если необходимо изменить заголовок на всех страницах, то в header.php

<title><?= $title = 'Мой первый Framework' ?? 'Мой блог'; ?></title>    <!-- Homework 14 -->

т.е. задаем значение непосредственно в шаблоне хедера в переменную $title, а если необходимо изменить заголовок на других страницах, то необходимо делать обработку писать в контроллере?
Помогите учитель, мозг кипит.

P.S
Комментарием выше сам сделал ошибку, создав style.css вместо styles.css, поэтому и не работали стили у меня, все поправил. У Вас все действительно было верно в данном уроке)

ivashkevich 08.09.2019 в 09:26

Всё ок, кроме шаблона - непонятно для чего переменная там определяется переменная title.

shrineofamana 25.09.2019 в 16:37

Сделал через аргумент по умолчанию:

public function renderHtml(string $templateName, array $vars = [], string $title = 'Мой блог')

Но потом прочел коментарии и задумался. Получается, так делать не рекомендуется и это плохое решение?

ivashkevich 27.09.2019 в 17:56

Конечно, у нас ведь уже есть способ передачи переменных в шаблон.

XXX 01.10.2019 в 19:43

header.php

<title><?= $title ?? 'Мой Блог' ?></title>

MainController.php

public function sayHello(string $name)
    {
        $this->view->renderHtml('main/hello.php', ['name' => $name, 'title' =>'Страница приветствия']);
    }
ivashkevich 03.10.2019 в 00:11

Отлично

[email protected] 05.10.2019 в 20:53

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

[email protected] 05.10.2019 в 21:11
 public function renderHtml(string $templateName, array $vars = [])
    {
        extract($vars);

        ob_start();
        include $this->templatesPath . '/' . $templateName;
        $buffer = ob_get_contents();
        ob_end_clean();

        $error='В шаблоне была ошибка!';

        echo $buffer;

    }

В строке с include немного непонятно,откуда у нас есть путь до папки с шаблонами.

Всё,этот момент разобрал,мы его даём,когда создаём обьект View, извините конечно за вопросы,но мы как-то с кошечек на такие вещи перепрыгнули,тут по 100000 вопросов в секунду возникают)

ivashkevich 05.10.2019 в 21:40

Главное не торопись. Да, этот курс я делал более сжатым и уже не разжевывал по 10 раз всё. Но и вы уже не такие балбесы как в курсе для начинающих. Учись осмысливать сжатую информацию без воды - пригодится в дальнейшем при чтении документации.

dliashchenko 25.10.2019 в 23:20

MainController.php

public function sayHello(string $name)
    {
        $this->view->renderHtml('main/hello.php', ['name' => $name, 'title' => 'Страница приветствия']);
    }

header.php

<?= $title ?? 'Мой блог';?>
ivashkevich 26.10.2019 в 07:47

Супер!

H3licoptero 15.11.2019 в 14:18

header

<title><?= $title ?? 'Мой блог' ?></title>

Controller

 public function sayHello(string $name)
    {
        $this->view->renderHtml('main/hello.php', ['name' => $name, 'title' => 'Страница приветствия']);
    }
ivashkevich 15.11.2019 в 18:48

Отлично

VpsK 03.12.2019 в 15:21

Все потерялся на уроке 13, дальше белый шум :)), или уровень внезапно вырос, а я где то, что то не уловил.... пошел отдыхать, попробую на свежую голову вернуться к 13 уроку....

ivashkevich 05.12.2019 в 14:42

Что именно непонятно?

VpsK 11.12.2019 в 14:38

Уже нормально, просто по какой то причине уроки начали даваться только после двух подходов с перерывом на отдых ))) видимо особенность )))

ivashkevich 11.12.2019 в 17:41

Ну, они конечно посложнее стали, это действительно требует больше внимания и времени.

EugeneGrigoryev 20.01.2020 в 16:45

templates/header.php

<title><?= $title ?? 'Мой блог' ?></title>

src/MyProject/Controllers/MainController.php

public function sayHello(string $name)
    {
        $this->view->renderHtml('main/hello.php', ['name' => $name, 'title' => 'Страница приветствия']);
    }
ivashkevich 20.01.2020 в 19:02

Супер!

andreskrip 26.01.2020 в 14:30

Спасибо за урок! Изначально сам прописывал в шапке значение title через тернарный оператор:

<title><?= !empty($title) ?  $title : 'Мой блог' ?></title>

Но затем подсмотрел в комментариях и вспомнил, что мы уже где-то сталкивались с оператором объединения с null :)
header.php

<title><?= $title ?? 'Мой блог' ?></title>

MainController.php

public function sayHello(string $name): void
    {
        $this->view->renderHtml('main/hello.php', ['name' => $name, 'title' => 'Страница приветствия']);
    }
ivashkevich 28.01.2020 в 18:44

Отлично!

IgorG 07.02.2020 в 11:21

Артем, проясни пожалуйста.
Почему мы проверяем $title как переменную?

<title><?= $title ?? 'Мой блог' ?></title>

А, задаем ее в методе, как 'title'

$this->view->renderHtml('main/hello.php', ['name' => $name, 'title' => 'Страница приветствия']);

Почему не работает ?

$this->view->renderHtml('main/hello.php', ['name' => $name, 'Страница приветствия'=> $title]);
ivashkevich 12.02.2020 в 12:20

Ну так смотрите код. Там функция extract в методе renderHtml вызывается.

OneMoreTime 22.02.2020 в 03:18

templates/main/main.php

<?php include __DIR__ . '/../header.php'; ?>
<?php foreach ($articles as $article): ?>
    <h2><?= $article['name'] ?></h2>
    <p><?= $article['text'] ?></p>
    <hr>
<?php endforeach; ?>
<?php include __DIR__ . '/../footer.php'; ?>

View

public function renderHtml(string $templateName, array $vars = [])
{
    extract($vars);

    ob_start();
    include $this->templatesPath . '/' . $templateName;
    $buffer = ob_get_contents();
    ob_end_clean();

    echo $buffer;
}
  1. Нельзя ли тот же изначальный массив articles передать из контроллера в view? И насколько это хорошо вообще делать через массивы? Или это чисто для академических целей?

  2. По поводу названий страничек - это что, механизм присваивания тайтлов, который используется в реальных проектах?

  3. Почему файл routes находится в MyProject, а не например в www?

  4. Подобного рода шаблоны(для каждого назначения свой) можно оттачивать в будущем и использовать для построени подобного рода однотипных сайтов или в реальности на каждом проекте есть свои индивидуальные особенности, из-за которых модель взаимодействия MVC имеет кучу разных реализаций?

  5. На этом этапе построение подобной структуры MVC нужно уже делать с закрытыми глазами, или сейчас важнее понимать что и как работает и представлять себе принципы взаимодействия между частями этой структуры?
    Я как и многие - понимаю, как работает то, что было в уроке, но сам бы я это вряд ли написал...
ivashkevich 23.02.2020 в 19:35

Привет. А где ДЗ?

  1. Передавать во View можно что угодно, что вы хотите вывести. Если в шаблоне нужно вывести несколько новостей, то конечно стоит передать туда массив.
  2. Не понял, что за тайтлы и названия
  3. Потому что весь код кроме фронт-контроллера должен находиться не в паблик-директории (корневой директории ВЕБ-СЕРВЕРА, к которой имеют доступ пользователи). Чем меньше файлов торчит наружу, тем безопаснее.
  4. Реализация может отличаться, но суть в целом будет той же.
  5. Важно понимание сейчас, это нормально, что сейчас вы не можете воспроизвести подобное решение самостоятельно, у вас пока просто недостаточно знаний. Но всё будет)
OneMoreTime 23.02.2020 в 21:11

Передавать во View можно что угодно, что вы хотите вывести. Если в шаблоне нужно вывести несколько новостей, то конечно стоит передать туда массив.

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

Не понял, что за тайтлы и названия

title = название странички

ДЗ не выкладывал. Я после того, как самостоятельно сделаю ДЗ, смотрю комментарии. Если принципиально не отличается от множества уже сделанных и выложеных в комментариях есть смысл его постить?

ivashkevich 24.02.2020 в 04:42

Ну так вложенный массив это по сути статья. Обращаемся к его ключам - получаем поля статьи.

Нет, тогда необязательно.

OneMoreTime 24.02.2020 в 11:20

Вот изначальный массив:

$articles = [['name' => 'Статья 1', 'text' => 'Текст статьи 1'],
            ['name' => 'Статья 2', 'text' => 'Текст статьи 2']]

Тут же - так и есть

вложенный массив это по сути статья.

Далее, посредством вот этой инструкции

['articles' => $articles]

Мы делаем еще большую глубину вложенности, где уже вложенный массив - не статья, а массив статей.

Я не очень понимаю прелесть вот этой последовательности:

['articles' => $articles]
....
extract($vars);

Вместо того, чтобы просто передать в main.php заданный изначально массив

$articles = [['name' => 'Статья 1', 'text' => 'Текст статьи 1'],
            ['name' => 'Статья 2', 'text' => 'Текст статьи 2']]

И что насчет вопроса №2?

ivashkevich 25.02.2020 в 07:32

Почитайте как работает функция extract.

Да, тайтл можно передавать так на реальных проектах.

OneMoreTime 25.02.2020 в 13:29

Читал про extract, сделал через массив без упаковывания в еще один массив и потом распаковывания экстрактом, как в уроке, поэтому и спрашиваю, т.к. не понимаю зачем так сделано, если можно просто передать заданный массив и в шаблоне обойти его циклом.
В MainController в методе main задаем массив и передаем его в объект View:

public function main()
    {
        $articles = [
            ['name' => 'Статья 1', 'text' => 'Текст статьи 1'],
            ['name' => 'Статья 2', 'text' => 'Текст статьи 2'],
        ];
        $this->view->renderHtml('main/main.php', $articles);
    }

В методе renderHtml принимаем в аргументах этот массив:

public function renderHtml(string $templateName, $vars = []) {
        //extract($vars);
        ob_start();
        include $this->templatesPath.'/'.$templateName;
        $buffer = ob_get_contents();
        ob_end_clean();

        echo $buffer;
    }

В шаблоне main делаем обход массива $vars:

<?php include __DIR__ . '/../header.php'; ?>
<?php  foreach ($vars as $article): ?>
    <h2><?= $article['name'] ?></h2>
    <p><?= $article['text'] ?></p>
    <hr>
<?php endforeach; ?>
<?php include __DIR__ . '/../footer.php'; ?>
ivashkevich 25.02.2020 в 15:54

А если помимо статей еще что-то передать нужно будет? Тот же тайтл. Каким образом вы его из общей мешанины vars будете доставать?

OneMoreTime 25.02.2020 в 17:07

А если помимо статей еще что-то передать нужно будет? Тот же тайтл.

Можно передать отдельным аргументом. Если передавать одним массивом параметры, например вот так:

public function main()
    {
        $articles = [
            ['name' => 'Статья 1', 'text' => 'Текст статьи 1'],
            ['name' => 'Статья 2', 'text' => 'Текст статьи 2'],
        ];
        $this->view->renderHtml('main/main.php', ['articles' => $articles, 'title' => 'main']);
    }

, то в шаблоне бы выводил так:

<?php include __DIR__ . '/../header.php'; ?>
<?php  foreach ($vars['articles'] as $article): ?>
    <h2><?= $article['name'] ?></h2>
    <p><?= $article['text'] ?></p>
    <hr>
<?php endforeach; ?>
<?php include __DIR__ . '/../footer.php'; ?>

Т.е. опять без extract. Кроме этого, пишут, что использование extract - не совсем безопасно, особенно, если эти данные приходят от пользователя.
Но я не берусь утверждать, т.к. я не имею практического опыта, я только учусь.

ivashkevich 26.02.2020 в 20:13

Ну так ведь проще писать $articles вместо $vars['articles'], разве нет?
А почему небезопасно, вы можете сказать? В каких условиях?

OneMoreTime 26.02.2020 в 21:26

Ну так ведь проще писать $articles вместо $vars['articles'], разве нет?

Мне проще для понимания тот вариант, что я использовал. Поэтому за него и уцепился. Но тут важнее другое - что возможны различные варианты, и эти два в частности оба правильные, а не костыли. Возможно я сейчас вижу(понимаю) именно так, а через время придут другие варианты.

А почему небезопасно, вы можете сказать? В каких условиях?

Это из документации:

Внимание
Не используйте extract() на непроверенных данных, таких как пользовательский ввод (например, $_GET, $_FILES).

Dimitry 03.04.2020 в 14:39

header.php


<!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <title><?=$title?></title>
    <link rel="stylesheet" href="/styles.css">
</head>
<body>

<table class="layout">
    <tr>
        <td colspan="2" class="header">
            Мой блог
        </td>
    </tr>
    <tr>
        <td>

MainController.php

<?php

namespace MyProject\Controllers;

use MyProject\View\View;

class MainController
{
    private $view;

    public function __construct()
    {
        $this->view = new View(__DIR__ . '/../../../templates');
    }

    public function main()
    {
        $articles = [
            ['name' => 'Статья 1', 'text' => 'Текст статьи 1'],
            ['name' => 'Статья 2', 'text' => 'Текст статьи 2'],
        ];
        $title="Мой блог";
        $this->view->renderHtml('main/main.php', ['articles' => $articles, 'title'=>$title]);
    }
    public function sayHello(string $name){
        $title="Страница приветвтвия";
        $this->view->renderHtml('main/hello.php', ['name'=>$name, 'title'=>$title]);
    }
}

Домашка

ivashkevich 03.04.2020 в 18:38

В случае, когда title не передан, выводите заголовок по умолчанию - "Мой блог"

Это не реализовано

Dimitry 04.04.2020 в 05:22
//header.php

<!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <title><?=$title?? "Мой блог"?></title>
    <link rel="stylesheet" href="/styles.css">
</head>
<body>

<table class="layout">
    <tr>
        <td colspan="2" class="header">
            Мой блог
        </td>
    </tr>
    <tr>
        <td>

//MainController SayHello:

public function sayHello(string $name){

        $this->view->renderHtml('main/hello.php', ['name'=>$name, 'title'=>'Страница приветствия']);
    }
ivashkevich 04.04.2020 в 09:06
<?=$title?? "Мой блог"?>

Пробел пропустили. Для строк используются одинарные кавычки.

Dimitry 04.04.2020 в 09:42

Понял,

//header.php

<!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <title><?=$title ?? 'Мой блог'?></title>
    <link rel="stylesheet" href="/styles.css">
</head>
<body>
ivashkevich 04.04.2020 в 10:51

Отлично

Salexandr 07.04.2020 в 18:21

header.php

<title><?= $title ?? 'Мой блог' ?></title>

MainController.php

public function sayHello(string $name)
    {
        $this->view->renderHtml('main/hello.php', ['name' => $name, 'title' => 'Страница приветствия']);
    }

Со скрипом понимаю, но повторить без шпаргалки и тем более сгенерировать самостоятельно такие решения, типа объект другого класса в конструкторе становится свойством или метод View->render другог класса вызывается в экшене sayHello, тяжеловато без практики ООП.

ivashkevich 08.04.2020 в 07:52

Отлично

Со временем придет навык, не очкуйте

Alexann 11.04.2020 в 18:31

MainController.php:

...
public function main()
    {
        $articles = [
            ['name' => 'Статья 1', 'text' => 'Текст статьи 1'],
            ['name' => 'Статья 2', 'text' => 'Текст статьи 2'],
        ];
        $this->view->renderHtml('main/main.php', ['articles' => $articles]);
    }

    public function sayHello(string $name)
    {
        $title='Страница приветствия';
        $this->view->renderHtml('main/hello.php', ['name' => $name,'title'=>$title]);
    }

View.php:

...
public function renderHtml(string $templateName, array $vars = [])
    {
        extract($vars);

        if (empty($title)){
            $title='Мой блог';
        }

        ob_start();
        include $this->templatesPath . '/' . $templateName;
        $buffer = ob_get_contents();
        ob_end_clean();

        echo $buffer;
    }

header.php:

<!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <title><?= $title ?></title>
    <link rel="stylesheet" href="/styles.css">
</head>
<body>

<table class="layout">
    <tr>
        <td colspan="2" class="header">
            <?= $title ?>
        </td>
    </tr>
    <tr>
        <td>
ivashkevich 11.04.2020 в 21:42
        if (empty($title)){
            $title='Мой блог';
        }

Этому здесь совсем не место. А если ещё такие переменные потребуются? Весь метод ими заполоним? Попробуйте сделать это в шаблоне с помощью null-coalesce оператора.

Alexann 11.04.2020 в 21:59

Исправил. header.php:

<!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <title><?= $title ?? 'Мой блог' ?></title>
    <link rel="stylesheet" href="/styles.css">
</head>
<body>

<table class="layout">
    <tr>
        <td colspan="2" class="header">
            <?= $title ?? 'Мой блог' ?>
        </td>
    </tr>
    <tr>
        <td>
ivashkevich 12.04.2020 в 06:20

Отлично

Dmitry.Dudin 11.04.2020 в 20:58

MaunController.php

    public function sayHello(string $name)
    {
        $this->view->renderHtml('main/hello.php',['name'=>$name, 'title'=>'Страница приветствия']);
    }

header.php

<title><?= $title ?? 'Мой блог'; ?></title>
ivashkevich 11.04.2020 в 21:44

Отлично

[email protected] 12.04.2020 в 18:19

Сделал, глянул в коменты, понял, что криво сделал и переделал))

В header.php

<title><?= $title ?? 'Мой блог' ?></title>

В MainController.php

  public function sayHello(string $name) {
    $this->view->renderHtml('main/hello.php', ['name' => $name, 'title' => 'Страница приветствия']);
  }
ivashkevich 13.04.2020 в 14:44

Супер!

Soib 14.04.2020 в 18:59
<?php 

namespace controllers;
use View\View;
class Main
{   
    private $title;
    private $view;

    public function __construct()
    {
        $this->view = new View('templates/main');
    }

    public function main()
    {
        $this->title = "Главная страница";

        $articles = $this->getArticles();
        $vars = [
                'title' => $this->title,
                'articles' => $articles,
            ];
        $this->view->renderHtml('main.php',$vars);
    }

    public function sayHello( string $name )
    {
        $this->title = "Страница приветствия";
        $this->view->renderHtml('hello.php', ['title'=>$this->title,'name' => $name]);
    }

    public function sayBye( string $name )
    {
        return "Привет " . $name;
    }

    public function getArticles(): array
    {
        return [
                ['name' => 'Статья 1', 'text' => 'Текст статьи 1'],
                        ['name' => 'Статья 2', 'text' => 'Текст статьи 2'],
                ];
    }
}
// header.php
<!DOCTYPE html>
<html lang="ru">

<head>
    <meta charset="UTF-8">
    <title><?php echo $title ?? 'Мой блог'; ?></title>
    <link rel="stylesheet" href="/templates/assets/styles.css">
</head>

<body>
    <table class="layout">
        <tr>
            <td colspan="2" class="header">
                Мой блог
            </td>
        </tr>
        <tr>
            <td>
ivashkevich 14.04.2020 в 19:52

Отлично

Fill 16.04.2020 в 20:59

header.php

<!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <title><?= isset($htmlTitle) ? $htmlTitle : 'Мой блог' ?></title>
    <link rel="stylesheet" href="/styles.css">
</head>
...

MainController.php

<?php
...
    public function sayHello(string $name)
    {
        $htmlTitle = 'Страница приветсвия';
        $this->view->renderHtml('main/hello.php', ['name' => $name, 'htmlTitle' => $htmlTitle]);
    }
ivashkevich 17.04.2020 в 09:11

Ок, а можно было так:

<?= $htmlTitle ?? 'Мой блог' ?>
Timurik 26.04.2020 в 14:17

У меня получилось так
header.php:

<!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <title><?= empty($title) ? 'Мой блог' : $title; ?></title>
    <link rel="stylesheet" href="/styles.css">
</head>
<body>

<table class="layout">
    <tr>
        <td colspan="2" class="header">
            Мой блог
        </td>
    </tr>
    <tr>
        <td>

hello.php

<?php $title = 'Страница приветствия'; ?>
<?php include __DIR__ . '/../header.php'; ?>
    Привет, <?= $name ?>!!!
<?php include __DIR__ . '/../footer.php'; ?>
ivashkevich 26.04.2020 в 14:31

Отлично! А можно написать так:

$title ?? 'Мой блог'
Timurik 26.04.2020 в 14:36

Спасибо сделал так:

<!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <title><?= $title ?? 'Мой блог' ?></title>
    <link rel="stylesheet" href="/styles.css">
</head>
<body>

<table class="layout">
    <tr>
        <td colspan="2" class="header">
            Мой блог
        </td>
    </tr>
    <tr>
        <td>

выглядит намного красивее!

ivashkevich 26.04.2020 в 17:08

Отлично)

studentDev 01.05.2020 в 11:37

MainController:

<?php
    namespace MyProject\Controllers;

    use MyProject\View\View;

    class MainController
    {
        private $view;

        public function __construct()
        {
            $this->view = new View(__DIR__ . '/../../../templates');
        }

        public function main()
        {
            $articles = [
                ['name' => 'Статья 1', 'text' => 'Текст статьи 1'],
                ['name' => 'Статья 2', 'text' => 'Текст статьи 2'],
            ];

            $this->view->renderHtml('main/main.php', ['articles' => $articles]); // VIEW: /../../../templates/main/main.php
        }
        public function sayHello(string $name)
        {
            $this->view->renderHtml('main/hello.php', ['name' => $name, 'title' => 'Страничка приветствия']);
        }
        public function sayBye(string $name)
        {
            echo 'Пока, ' . $name;
        }
    }

Header:

<!DOCTYPE html>
<html>
<head>
    <title><?= $title ?? 'Мой блог' ?></title>
    <meta charset="UTF-8">
    <link rel="stylesheet" href="/styles.css">
</head>
<body>
<table class="layout">
    <tr>
        <td colspan="2" class="header">
            Мой блог
        </td>
    </tr>
    <tr>
        <td>

Вот тут моя голова и сломалась)
Как-то так...

ivashkevich 01.05.2020 в 15:16

Отлично. А почему сломалась, если решение есть?)

OneMoreTime 01.05.2020 в 11:56

В шаблонах несколько раз в уроке присутствует:

Привет, <?= $name ?>!!!

Почему без проверки переменной на существование?
например

<?= $title ?? 'My blog'; ?>

Во всех случаях в уроке использован include для подключения файлов - шаблонов. Почему не include_once? Нужно же только по одному разу подключать шаблоны.
Или once используется только если существует вероятность повторного подключения?

ivashkevich 01.05.2020 в 15:20

Почему без проверки переменной на существование?

Потому что она всегда передаётся во View для этого шаблона из контроллера.

Или once используется только если существует вероятность повторного подключения?
Не только, но в целом да. Дополнительная защита от повторного подключения может быть.

[email protected] 28.05.2020 в 20:54

MainController.php

public function main()
    {
        $articles = [
            ['name' => 'Article 1', 'text' => 'Article`s 1 text'],
            ['name' => 'Article 2', 'text' => 'Article`s 2 text'],
        ];
        $this->view->renderHtml('main/main.php', ['articles' => $articles, 'title' => 'Title']);
    }

    public function sayHello(string $name)
    {
        $this->view->renderHtml('main/hello.php', ['name' => $name, 'title' => 'Страница приветствия']);
    }

header.php

<title><?= $title ?? 'Мой блог' ?></title>
ivashkevich 29.05.2020 в 05:26

Ну а что не придумали-то тайтл для статей?)

[email protected] 29.05.2020 в 08:27

Придумаю)

IePyton 03.06.2020 в 15:40

Артем, посмотри пожалуйста, у меня файл стилей работает только если так прописывать директорию. Если директорию прописываю так:

/style.css - как в уроке не работает
style.css - так работает только для главной страницы
и только вот так работает /phplearn.my/www/styles.css и на главной и на внутряке, какое есть решение?

домашка
header.php

<!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <title><?= $title ?? 'Мой блог' ?></title>
    <link rel="stylesheet" href="/phplearn.my/www/styles.css">
</head>
<body>

<table class="layout">
    <tr>
        <td colspan="2" class="header">
            Мой блог
        </td>
    </tr>
    <tr>
        <td>

MainController.php

<?php

namespace MyProject\Controllers;

use MyProject\View\View;

class MainController
{
    private $view;
    public function __construct()
    {
        $this->view = new View(__DIR__ . '/../../../templates');
    }

    public function main()
    {
        $articles = [
          ['name' => 'Статья 1', 'text' => 'Текст статьи 1'],
          ['name' => 'Статья 2', 'text' => 'Текст статьи 2'],
        ];
        $this->view->renderHtml('main/main.php', ['articles' => $articles]);

    }

    public function sayHello(string $name)
    {
        $this->view->renderHtml('main/hello.php', ['name' => $name, 'title' => 'Страница приветствия'],);
    }

    public function sayBay(string $name)
    {
        echo 'Пока, ' . $name;
    }
}
ivashkevich 03.06.2020 в 19:04

Эмм, так ведь в адресной строке не должно быть www. Что за веб-сервер у вас?

IePyton 04.06.2020 в 10:44

MAMP
насколько я понят вы тоже мампом сейчас пользуетесь

ivashkevich 04.06.2020 в 11:07

Да, в качестве корневой папки веб-сервера надо указывать путь вместе с www.

IePyton 05.06.2020 в 13:56

Я в мампе вобще не могу найти преферансес ((
http://joxi.ru/gmvWJgvIvlXx52
у меня просто нет этого пункта нигде.
Не сталкивались с таким?

ivashkevich 06.06.2020 в 08:27

Наверное это только в mamp pro есть
описание картинки

скриншоты можно прикреплять в редакторе комментариев

Sviatoslav 09.06.2020 в 20:13

Потерял логическую нить связки всех компонентов с фронт-контроллером.

public function sayHello(string $name)
{
    $this->view->renderHtml('main/hello.php', ['name' => $name]);
}

Как здесь "username" попадает в переменную "$name" для вывода в шаблоне?

$controller->$actionName(...$matches);

при помощи этого в index.php?

ivashkevich 10.06.2020 в 12:26

Посмотрите дебаггером)

Sviatoslav 10.06.2020 в 21:02

Посмотрел. Мое смутное ощущение оказалось верным)
Если честно, когда смотришь по ходу урока, то всё ясно, логично и понятно. Смотришь на код на следующий день и начинается паутина)
Надеюсь со временем ко мне придёт ясность при чтение кода и в ООП в целом.

ivashkevich 11.06.2020 в 20:27

И дебажьте)

[email protected] 07.07.2020 в 23:13

Добрый вечер!
ДЗ
header.php

<!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <title>Мой блог</title>
    <link rel="stylesheet" href="/style.css">
</head>
<body>

<table class="layout">
    <tr>
        <td colspan="2" class="header">
            <?= $title ?>
        </td>
    </tr>
    <tr>
        <td>

MainController.php

<?php
namespace MyProject\Controllers;
use MyProject\View\View;
class MainController{
    private $view;
    public function __construct()
    {
        $this->view = new View(__DIR__ . '/../../../templates');
    }

    public function main(){
       $articles = [
           ['name' => 'Статья 1', 'text' => 'Текст статьи 1'],
           ['name' => 'Статья 2', 'text' => 'Текст статьи 2']
           ];
       $title = 'Учебный сайт';

        $this->view->renderHtml('main/main.php', ['articles' => $articles, 'title' => $title ?? 'Мой блог']);
    }
    public function sayHello(string $name){
        $title = 'Страница приветствия';
        $this->view->renderHtml('main/hello.php', ['name' => $name, 'title' => $title ?? 'Мой блог']);
    }
    public function  sayBye(string $name){
        echo 'Пока, ' . $name;
    }
}

Артем, правильно ли я понимаю, что в данном примере мы имеем
фронт-контроллер - index.php
контроллер - MainController.php + View.php
представление - main.php, hello.php, footer.php, header.php
модель в нашем случае размещена также в файле MainController.php, это данные, которые мы храним в переменных.
True или False?)

ivashkevich 08.07.2020 в 14:33

Тайтл в итоге не выводится. Значение по умолчанию стоит применять в шаблоне, чтобы не обрабатывать каждый раз в контроллере переменную $title.

фронт-контроллер - index.php

да

контроллер - MainController.php + View.php

нет. контроллер - это MainController. Представление - View

представление - main.php, hello.php, footer.php, header.php

это просто шаблоны, к модели MVC они никак не относятся

модель в нашем случае размещена также в файле MainController.php, это данные, которые мы храним в переменных

а это совсем всё неправда. Модель - это слой, в котором хранится бизнес-логика и обрабатываются данные. У нас пока что нет как таковой модели, но за одну модель можно принять одну статью, если очень грубо упростить. То есть вот этот массив:

['name' => 'Статья 1', 'text' => 'Текст статьи 1']

наша простейшая модель, представляющая собой одну статью.

[email protected] 08.07.2020 в 16:18

Тайтл в итоге не выводится. Значение по умолчанию стоит применять в шаблоне, чтобы не обрабатывать каждый раз в контроллере переменную $title.

Исправил.

<?php
namespace MyProject\Controllers;
use MyProject\View\View;
class MainController{
    private $view;
    public function __construct()
    {
        $this->view = new View(__DIR__ . '/../../../templates');
    }

    public function main(){
       $articles = [
           ['name' => 'Статья 1', 'text' => 'Текст статьи 1'],
           ['name' => 'Статья 2', 'text' => 'Текст статьи 2']
           ];
       $title = 'Учебный сайт';

        $this->view->renderHtml('main/main.php', ['articles' => $articles, 'title' => $title]);
    }
    public function sayHello(string $name){
        $title = 'Страница приветствия';
        $this->view->renderHtml('main/hello.php', ['name' => $name, 'title' => $title]);
    }
    public function  sayBye(string $name){
        echo 'Пока, ' . $name;
    }
}
<!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <title><?= $title ?? 'Мой блог' ?> </title>
    <link rel="stylesheet" href="/style.css">
</head>
<body>

<table class="layout">
    <tr>
        <td colspan="2" class="header">
            <?= $title ?? 'Мой блог' ?>
        </td>
    </tr>
    <tr>
        <td>
[email protected] 08.07.2020 в 16:20

За разъяснения очень благодарен, спасибо!

ivashkevich 09.07.2020 в 05:19

Отлично)

VitaliyB 06.08.2020 в 06:57

MyController.php

 public function sayHello(string $name)
    {
        $this->view->renderHtml('main/hello.php', ['name' => $name, 'title' => 'Страница приветствия']);
    }

header.php

<title><?= $title ?? 'Мой блог' ?></title>

routes.php

'~(.*)$~' => [\MyProject\Controllers\MainController::class, 'title']
ivashkevich 07.08.2020 в 17:56

Супер!

demos 03.09.2020 в 14:25

mainController.php :

<?php

namespace MyProject\Controllers;

use MyProject\View\View;

class MainController
{
    private $view;

    public function __construct()
    {
        $this->view = new View(__DIR__ . '/../../../templates');
    }

    public function main()
    {

        $articles = [
            ['name' => 'Статья 1', 'text' => 'Текст статьи 1'],
            ['name' => 'Статья 2', 'text' => 'Текст статьи 2'],
        ];
        $this->view->renderHtml('main/main.php', ['articles' => $articles]);
    }
    public function sayHello(string $name)
    {
        $this->view->renderHtml('main/hello.php', ['name' => $name ,'title' => 'Страница приветствия']  );
    }

}

header.php:

<!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <title><?= $title ?? 'Мой блог' ?></title>
    <link rel="stylesheet" href="/styles.css">
</head>
<body>

<table class="layout">
    <tr>
        <td colspan="2" class="header">
            Мой блог
        </td>
    </tr>
    <tr>
        <td>
ivashkevich 03.09.2020 в 17:51

Отлично

Ysup 05.09.2020 в 22:17

Ребята, что означает слово 'экшн' в данных уроках?

ivashkevich 06.09.2020 в 14:36

Метод контроллера, к которому привязан роут.

Ysup 09.09.2020 в 01:00

Артем, спасибо. Теперь понял.

SkSeMi 22.11.2020 в 00:54

Почему в реиспользовании шаблонов не используется рекурсивно снова метод рендеринга?
Пример реиспользования шаблона до конца не раскрыт - используется статические внутреннние шаблоны, без передачи например каких либо переменных.
Каким образом можно сделать так, чтобы вместо

<?php include __DIR__ . '/../header.php'; ?>
<?php foreach ($articles as $article): ?>
    <h2><?= $article['name'] ?></h2>
    <p><?= $article['text'] ?></p>
    <hr>
<?php endforeach; ?>
<?php include __DIR__ . '/../footer.php'; ?>

использовать

<?php include __DIR__ . '/../header.php'; ?>
<?php foreach ($articles as $article): ?>
    <h2><?= $article['name'] ?></h2>
    <p><?= $article['text'] ?></p>
    <hr>
<?php endforeach; ?>
<?php $this-view-renderHtml(__DIR__ . '/../footer.php'); ?>
ivashkevich 23.11.2020 в 17:38

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

MikeSiebel 29.11.2020 в 22:38

Добрый день!

MainController.php

<?php
namespace MyProject\Controllers;
use MyProject\View\View;
class MainController{
    private $view;
    public function __construct(){…}
    public function main(){…}    
    public function sayHello(string $name)
    {
        $this->view->renderHtml('main/hello.php', ['name' => $name, 'title' => 'Страница приветствия']);
    }
}

header.php

<!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <title><?= $title ?? 'Мой блог' ?></title>
    <link rel="stylesheet" href="/styles.css">
</head>
<body>
<table class="layout">
    <tr>
        <td colspan="2" class="header">
            Мой блог
        </td>
    </tr>
    <tr>
        <td>
ivashkevich 01.12.2020 в 04:08

Супер!

[email protected] 30.11.2020 в 00:33

1) Появилась проблема со стилями в последнем примере, когда стили вынесли в отдельный файл, я думаю надо в .htaccess добавить отдельный роутинг для них, так как если выбрать главную страницу http://phpzone.loc/Primer2-Arhitectura/5-view/Primer5, чтобы стили отображались нужно написать так: <link rel="stylesheet" href="styles.css"> А если перейти по этой ссылке http://phpzone.loc/Primer2-Arhitectura/5-view/Primer5/hello/username, то так <link rel="stylesheet" href="../styles.css">. Проблема появляется, так как добавляется hello в пути к файлу, приходится переходить на уровень выше. Всё зависит от ссылки. Пришлось добавить такую ссылку, чтобы всё работало: <link rel="stylesheet" href="/Primer2-Arhitectura/5-view/Primer5/styles.css">

2) Также не знаю почему, но если удалить из файла index.php:

use MyProject\Models\Users\User;
use MyProject\Models\Articles\Article;
use MyProject\Controllers\MainController;
use MyProject\View\View;

то код продолжает работать, как буд-то это не нужно, phpStorm выделяет его красным.

3) Домашка:

namespace MyProject\Controllers;
use MyProject\View\View;
class MainController
{
    private $view;

    public function __construct()
    {
        $this->view = new View(__DIR__ . '/../../../templates');
    }
    public function main()
    {

        $title = "Главная страница";

       /* Давайте теперь попробуем передавать в шаблон переменные. Вместо явно заданных статей сделаем переменную со статьями:*/
        $articles = [
            ['name' => 'Статья 1', 'text' => 'Всем привет, это текст первой статьи1'],
            ['name' => 'Статья 2', 'text' => 'Всем привет, это текст второй статьи2']
        ];

        //echo 'Главная страница';
        //include __DIR__ . '/../../../templates/main/main.php';
        $this->view->renderHtml('main/main.php', ['articles' => $articles], $title); //Тут происходит ввод данных и получение результата в $this->view. Тут логика с подключением нужного шаблона в отдельном классе View
    }

/*Давайте в наш контроллер вернём экшн из прошлых уроков, который выводил приветствие:*/

    public function sayHello(string $name)
    {
        $title = "Страница приветствия";
        $this->view->renderHtml('main/hello.php', ['name' => $name], $title);
    }

В файле header всё ОК! В view.php добавил public function renderHtml(string $templateName, array $vars = [], string $title) {}
Согласен, так проще: $this->view->renderHtml('main/hello.php', ['name' => $name, 'title' => 'Страница приветствия']);

ivashkevich 01.12.2020 в 19:29
  1. Пересмотри урок про абсолютные и относительные ссылки. В твоём случае путь будет /styles.css для всех страниц
  2. Что-то определенно не так. Автозагрузку делал? include не напиханы по всему коду?
  3. А если потом еще description появится? Тоже параметр заводить отдельный? А, всё, увидел коммент
pixel 14.12.2020 в 20:02

Добавил title в массив $vars
MainController.php

<?php

namespace MyProject\Controllers;

use MyProject\View\View;

class MainController
{
    private $view;

    public function __construct()
    {
        $this->view = new View(__DIR__ . '/../../templates');
    }

    public function main()
    {
        $articles = [
            ['name' => 'Статья 222', 'text' => 'Текст статьи 1'],
            ['name' => 'Статья 2', 'text' => 'Текст статьи 2'],
        ];
        $this->view->renderHtml('main/main.php', ['articles' => $articles, 'title' => 'Мой блог']);
    }

    public function sayHello(string $name)
    {
        $this->view->renderHtml('main/hello.php', ['name' => $name, 'title' => 'Страница приветствия']);
    }

    public function sayBye(string $name)
    {
        $this->view->renderHtml('main/bye.php', ['name' => $name, 'title' => 'Страница выхода']);
    }
}

header.php

<!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <title>
        <?= $title ?>
    </title>
    <link rel="stylesheet" href="/styles.css">
</head>
<body>

<table class="layout">
    <tr>
        <td colspan="2" class="header">
            <?= $title ?>
        </td>
    </tr>
    <tr>
        <td>
ivashkevich 17.12.2020 в 17:46

Ок. Но нужно еще сделать заголовок по умолчанию, в случае когда title не передали

Egor.Ka 22.03.2021 в 18:28

Долго делал, из-за большого потока информации все смешалось в голове). Вроде пока читаешь, понятно, как начинаешь делать, теряешься и приходится снова читать и разбираться в этом, да и в предыдущих уроках)

Header.php

<title><?=  $title ?? 'Мой блог'; ?></title>

MainController.php

public function sayHello(string $name)
    {
        $this->view->renderHtml('main/hello.php', ['name' => $name, 'title' => 'Страница приветствия']);
    }
ivashkevich 26.03.2021 в 17:32

По коду всё ок.

А торопиться не надо)

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