Чат Telegram
Группа ВКонтакте

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

Новый комментарий


tomsonst
// 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

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

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

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

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

ivashkevich

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

Sparky

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

computerix
//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

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

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

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

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

computerix

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

ArtemijeKA

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

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

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

array $vars = []
ivashkevich

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

ArtemijeKA

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

ArtemijeKA

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

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

http://php_book/mvc/www/index.php
ivashkevich

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

ArtemijeKA

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

ivashkevich

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

SBTesla
//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

Супер! =)

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

Отлично!

AxLT

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

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

а так нет?

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

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

demyanovpaul@yandex.ru

Сделайте чтобы 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

То что нужно!

Todd

MainController

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

header

<title><?= $title ?? 'my blog' ?></title>
ivashkevich

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

bildep

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

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

virtual2018

MainController.php

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

header.php

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

Отлично!

alepawka

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

ivashkevich

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

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

Не работает.

alepawka

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

ivashkevich

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

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

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

ivashkevich

Именно)

virtual2018

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

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

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

landialog

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

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

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

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

Bogdan

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

excent63

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

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

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

Отлично!

radinpasha13@gmail.com

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

ivashkevich

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

Alexander

Изначально не полностью понял про 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

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

Evgeny

<?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

Отлично

lordbear53@gmail.com

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

heder.php

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

MainController.php

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

Отлично

babls2332@gmail.com
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

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

Boodoo

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

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

Boodoo

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

Ок!

polvanovv

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

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

Dram

К сожалению не могу продолжать делать домашку, так и не смог победить баг из прошлого урока.
У меня на странице 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

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

ashfedor

в header.php

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

в MainController.php

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

вроде все!

ivashkevich

Отлично!

Moskva

Сначала не понял, как требуется сделать домашку, потом подсмотрел и разобрался:)
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

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

Invo

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

Отлично!

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

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

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

ivashkevich

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

Metey
<?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

Отлично

Iliusha99

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

Iliusha99
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

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

Iliusha99

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

ivashkevich

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

Iliusha99

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

ivashkevich

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

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

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

Iliusha99

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

ivashkevich

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

Iliusha99
 public function sayHello($text){

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

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

ivashkevich

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

ivashkevich

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

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

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

ivashkevich

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

Iliusha99

Понятно.

artemship

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

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

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

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

Отлично

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

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

Отлично!

fosfat

Артем, это не критика, а просто попытка новичка в 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

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

ivashkevich

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

Pro100Bah

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

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

ivashkevich

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

Pro100Bah

Сначала как начал делать домашку, подумал нужно следовать алгоритму в конце урока:
"Давайте повторим последовательность шагов, которые необходимо сделать для добавления новой странички:
-Добавляем экшн в контроллер (либо создаём ещё и новый контроллер);
-Добавляем для него роут в 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

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

shrineofamana

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

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

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

ivashkevich

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

XXX

header.php

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

MainController.php

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

Отлично

prinzplanloser0514@gmail.com

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

prinzplanloser0514@gmail.com
 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

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

Онлайн обучение PHP
Путь с полного нуля до джуниора!
Начать бесплатно
Логические задачи с собеседований