Чат Telegram
Группа ВКонтакте
Новый комментарий


Galay

Итак, с первым пунктом про хранение классов в отдельных классах мы разобрались.

Наверно имеловь ввиду "хранение классов в отдельных папках"?

ivashkevich

В отдельных файлах. Спасибо, исправил =)

Sparky

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

Sparky

Код ошибки:

Warning: require_once(/var/www/html/php-learn/Sparky-project/www/../src/MyProject\Models\Users\User.php): failed to open stream: No such file or directory in /var/www/html/php-learn/Sparky-project/www/index.php on line 11

Fatal error: require_once(): Failed opening required '/var/www/html/php-learn/Sparky-project/www/../src/MyProject\Models\Users\User.php' (include_path='.:/usr/share/php') in /var/www/html/php-learn/Sparky-project/www/index.php on line 11
Sparky

окей, помощи особо не вижу, пофиксил сам. Заменил обратные слеши через str_replace, таким образом путь стал правильным

ivashkevich

Да, всё дело именно в них. Разница в том, что я писал урок под виндой, а там в путях как раз обратные слэши. Ваше решение с использованием str_replace - в самый раз.

Tina

А говорите Иван что за 2 года не было такой проблемы с которой сталкиваются маководы

ivashkevich

Так вы про это ничего не говорили.
P.S. я не Иван

prinzplanloser0514@gmail.com

Кто же ты,тайный незнакомец)

ivashkevich

Кек)

Benya

Та же проблема что у Sparky, что то до конца не понял как ее решить?

den

Достаточно просто так:

require_once __DIR__ . '/../src/' . str_replace('\\', '/', $className) . '.php';
ivashkevich

Спасибо что подменили меня =)

ArtemijeKA

Не разобрался с ошибкой:

Fatal error: Uncaught Error: Class 'models\articles\Article' not found in /namespaces/public_html/index.php on line 18

var_dump();

/namespaces/public_html/index.php:11:string 'models\articles\Article' (length=23)
/namespaces/public_html/index.php:12:string '/namespaces/public_html/../src/models/articles/Article.php' (length=125)

PS У меня только нет папки MyProject и все папки маленькими буквами.

ivashkevich

Если еще актуально - напиши в личку.

ArtemijeKA

Нет, только что понял свой косяк.

ArtemijeKA

Дело в том, что я указал:

namespace models\articles\Article;
namespace models\users\User;

А надо было просто путь до класса без самого класса:

namespace models\articles;
namespace models\users;
ivashkevich

Нэймспейсы должны быть с большой буквы, это стандарт PSR-4. Чуть позже о нем расскажу.

ArtemijeKA

Получается и папки в src тоже...

ivashkevich

Да. А зачем не по урокам делали?

ArtemijeKA

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

ArtemijeKA

Еще оформительский вопрос остался.
Как правильнее обращаться к классу при создании объекта?
В документации http://php.net/manual/ru/language.namespaces.rationale.php
внизу, в дополнении кто-то написал якобы по PSR стандарту:

<?php $tool = new Pierstoval\Tools\MyTool(); ?>
  • то есть без корневого слеша.
ivashkevich

Можно и полный неймспейс указывать, а можно через use в начале файла. Второй вариант предпочтительнее.

ArtemijeKA

Я извиняюсь, вопрос был о дотошном перфекционизме как правильнее):

$tool = new Pierstoval\Tools\MyTool();

или

$tool = new \Pierstoval\Tools\MyTool();

Я так понял с корневым \ - более универсально использовать.

ivashkevich

С корневым правильно. Можете прочитать про PSR-4.

ArtemijeKA

Что-то я не понимаю почему у меня нет ошибки как в этом уроке когда надо добавить в Article.php

public function __construct(string $title, string $text, \MyProject\Models\Users\User $author)

и

public function getAuthor(): \MyProject\Models\Users\User

У меня без явного определения пространства имен отрабатывается код::

{path}/namespaces/public_html/index.php:20:
object(Models\Users\User)[1]
  private 'name' => string 'Иван' (length=8)
{path}/namespaces/public_html/index.php:21:
object(Models\Articles\Article)[2]
  private 'title' => string 'Заголовок' (length=18)
  private 'text' => string 'Текст' (length=10)
  private 'author' => 
    object(Models\Users\User)[1]
      private 'name' => string 'Иван' (length=8)

Все, обнаружил свой косяк: не поставил тип переменной User для переменной $author в Article.php.
Это я так понимаю чтобы автором статьи не мог стать кто-то отличный от User (например кот или пес))

ivashkevich

Да, Вы всё верно поняли)

virtual2018

Я правильно понимаю, что мы здесь пишем конструкции вида:

<index.php>
$author = new \MyProject\Models\Users\User('Иван');
$article = new \MyProject\Models\Articles\Article('Заголовок', 'Текст', $author);

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

<?php

use MyProject\Models\Users\User as UserAlias;
use MyProject\Models\Articles\Article as ArticleAlias;

function myAutoLoader(string $className)
{
    var_dump($className);
    require_once __DIR__ . '/../src/' . $className . '.php';
}

spl_autoload_register('myAutoLoader');

$author = new UserAlias('Иван');
$article = new ArticleAlias('Заголовок', 'Текст', $author);
ivashkevich

Вообще без псевдонимов, просто use. Но об этом дальше.

landialog

Решение c заменой слешов есть в комментах и оно рабочее. Но как тогда будет код выглядеть на Linux если не использовать ф-ю str_replace (замену слешов)?

require_once __DIR__ . '/../src/' . $className . '.php';

И спасибо за урок, пока поковырялся воспроизвести тоже самое, пришло понимание как это должно работать.

ivashkevich

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

landialog

может что-то я неправильно делаю, но я пробую устанавливать в таком виде: require_once __DIR__ . '\..\src\' . $className . '.php'; и PhpStorm выдает ошибку в результате ничего не работает

ivashkevich

Ну так а чего слэши обратные?

landialog

Подскажите лучше сразу правильный вариант, иначе я не догоню. Я месяц как перешёл на Линукс и для меня не все иногда понятно :)

ivashkevich

Правильный вариант в уроке приведен. Там слэши в другую сторону.

Waldemar

"Добавим var_dump() с выводом переменной $className." - добавил, не сработало, не вывелась информация по именам классов, т.е. всё осталось без изменений.

object(MyProject\Models\Articles\Article)[2]
  private 'title' => string 'Заголовок' (length=18)
  private 'text' => string 'Текст' (length=10)
  private 'author' => 
    object(MyProject\Models\Users\User)[1]
      private 'name' => string 'Иван' (length=8)
ivashkevich

А подключения файлов убрали в самом начале?

AxLT

Вот такой вопрос появился. При подключении файлов:

function myAutoLoader(string $className)
{
    var_dump($className);
    require_once __DIR__ . '/../src/' . $className . '.php';
}

Мы получаем из $className путь с обратными слешами

string 'MyProject\Models\Users\User' (length=20)

и если подставить то что мы получили к require_once то выходит:

require_once __DIR__ . '/../src/MyProject\Models\Users\User.php' //как это работает то?)
ivashkevich

Почитайте комментарии)

fosfat

Прочитал все комментарии, но прямого ответа на вопрос человека выше не нашел. Есть просто комменты про решение проблемы обратного слеша у пользователей на Маке.

Поэтому присоединюсь: как это работает, что мы соединяем "стандартные" слеши в пути с обратными слешами? Почему не возникает конфликта?

ivashkevich

Потому что это винда и ей плевать на наклон слеша)

Art

Доброе утро! Не совсем очевидно, как упаковывать дочерние и родительские КЛАССЫ относительно друг друга в файловой системе, и как должны при этом формироваться неймсппейсы в соответствии с psr-4?

Так же не понятно, как в таком случае поступать с трейтами и интерфейсами, по идее их также нужно упаковывать в отдельные файлы?

ivashkevich

Каждый класс, интерфейс или трейт должен лежать в отдельном файле. Имя файла должно совпадать с его именем. Касательно того, как должны выстраиваться неймспейсы - тут нет однозначного ответа, все зависит от бизнес-логики и инфраструктуры проекта.

Art

Артем, спасибо, принято!)

Danya

spl_autoload_register - Регистрирует заданную функцию в качестве реализации метода __autoload(). , которая загружает все неопределенные классы , я все верно понял ?)

ivashkevich

Да. Только с помощью spl_autoload_register можно добавить несколько функций автозагрузки.

Danya

то есть несколько аргуметов в этой функции?

ivashkevich

Нет. Несколько разных функций. Почитайте документацию.

Invo

_autoload() - использовать нынче кощунство, все вокруг говорят что устарело и не стоит этого делать...

Danya

Я не совсем понял как и где мы заполняем $classname , он только вызывается в качестве аргумента , а где мы пишем $classname = путь к нужным классам. Как это работает?

Я имею ввиду вот функция , а где мы пишем $classname = путь к файлу с классом? Он что телепат и сам понимает где файлы с классами лежат =)

spl_autoload_register(function (string $className) {
    require_once __DIR__ . '/../src/' . $className . '.php';
});

А то тут неясные для меня действа происходят, объясните пожалуйста

ivashkevich

Зачем же телепат) Когда в коде встречается имя какого-то неизвестного класса, происходит вызов функции, которую мы зарегистрировали через spl_autoload_register. И в качестве аргумента передается имя вот этого неизвестного нам класса. И всё)

Iliusha99

На примере класса User это будет выглядеть следующим образом:
src/MyProject/Models/Users/User.php :

namespace MyProject\Models\Articles;

Почему начинаем именно с MyProject а не с src, как правильно путь прописать в неймспейсах, или можно любые пути прописать?

ivashkevich

src это просто папка, в которой хранится весь наш код. Внутри нее есть код с неймспейсами, в частности, начинающийся с MyProject...

Iliusha99

Да но, Models тоже папка, почему не начинаем с Models чтобы понятнее было что работаем с моделями, или чтобы лучше структурировать пути кода в проекте?

ivashkevich

Понял теперь твой вопрос. Это делается, чтобы отделить код проекта от кода подключаемых библиотек (об этом будет дальше). Код проекта выделяется в отдельный неймспейс с названием проекта. Наш учебный проект называется MyProject, отсюда и начало неймспейса. Для Фейсбука неймспейс начинается с Facebook\...

Iliusha99

Ясно, спасибо

uzabila

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

У нас есть условный домен "myproject.loc", а в нем есть папки "src" и "www". При этом файл index.php только в папке "www", так?

Т.е. для запуска скрипта мы должны именно ввести в адресной строке "myproject.loc/www/index.php"?
А если просто попробовать открыть myproject.loc при запущенном OpenServer ничего не произойдет? Или в корне будет еще один index.php? Вопрос еще с точки зрения последующего переноса проекта на хостинг, когда ты будешь просто вводить в браузере имя домена.

Спасибо заранее.

ivashkevich

Т.е. для запуска скрипта мы должны именно ввести в адресной строке "myproject.loc/www/index.php"?

Нет. В адресной строке должно быть myproject.loc

www - это корневая папка для веб-сервера, но не для всего проекта. Для этого нужно соответствующим образом настроить OpenServer. Смотрите урок об этом в курсе PHP для начинающих. На хостинге эта папка в большинстве случаев именуется public_html.

Что касается index.php, то он зарезолвится с помощью правил в .htaccess

uzabila

Понял! Спасибо :)

vtolstov

Нашел еще хорошую статью по неймспейсам и автозагрузке. Может кому пригодится для расширения данного урока: https://github.com/codedokode/pasta/blob/master/php/autoload.md

prinzplanloser0514@gmail.com

Странно,не работает автозагрузка через spl_autoload_register ,хотя пишет failed to open stream: No such file or directory,но показывает путь точно до нужного файла.

ivashkevich

Linux?

prinzplanloser0514@gmail.com

Да,я уже пофиксил)

prinzplanloser0514@gmail.com

Как в переменную $className попадает неймспейс класса,который мы хотим подключить,это магия? p.s остальное всё понял.

ivashkevich

Когда встречается не используемый ранее класс, вызывается эта функция, в аргумент прилетает полное имя класса, включая неймспейс. И да, это магия.

prinzplanloser0514@gmail.com

Это я понял,я не понял,как до аргумента долетает полное имя класса,включая неймспейс,это из-за spl_autoload_register ?

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