Поддержать проект
Новый комментарий

ArtemijeKA 28.10.2018 в 09:50

Ооочень насыщенный. Как бы все переварить.

ivashkevich 28.10.2018 в 10:22

Да, тема не самая простая. Изучай в несколько подходов.

sirserik 03.03.2019 в 15:39

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

ivashkevich 03.03.2019 в 21:50

Привет. Репа тут - https://gitlab.com/ivashkevitch/myproject

Dram 17.05.2019 в 18:32

С сожалением должен признать что уроки превратились в ctrl C => ctrl V. Очень много материала вываливается за один урок, и я уже перестал что-то понимать сам. Да и домашки опять нет.
Если что-то неудачно скопировал - ошибку найти практически не возможно с нашим уровнем :((

ivashkevich 17.05.2019 в 21:56

Попробуйте не бежать вперед как можно быстрее, а разбираться более глубоко в теме. Ученик, дошедший до данного урока уже сам должен разбираться в ошибках. Учитесь дебажить. Опыт других учеников показывает, что с уроками всё в порядке.

andreskrip 30.01.2020 в 17:25

Переставайте делать ctrl+c=>ctrl+v. Пишите код от руки, так будете лучше и понимать что вы пишете и запоминать построение кода. Мне очень помогло еще на курсе php для начинающих. При этом я еще и конспект от руки веду, чтобы когда писал дополнительно в голове проговаривал и понимал/запоминал. :)

ashfedor 17.06.2019 в 14:08

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

sergey.demin1997@gmail.com 19.07.2019 в 01:41

Немного непонятки, почему при вардампе вот этого $article = Article::getById($articleId);
Он говорит что это обьект

ivashkevich 19.07.2019 в 07:03

А что там должно быть?

Metey 20.07.2019 в 22:11

отличный урок!!

Тема мне кажется тут ошибка в коде :
в этой строке <p>Автор: <?= $article->getAuthor()->getNickname() ?></p>
Должно же быть getAuthorId() вместо getAuthor() ?????

<?php include DIR . '/../header.php'; ?>
<h1><?= $article->getName() ?></h1>
<p><?= $article->getText() ?></p>
<p>Автор: <?= $article->getAuthor()->getNickname() ?></p>
<?php include DIR . '/../footer.php'; ?>

ivashkevich 21.07.2019 в 05:33

Нет, всё правильно. Посмотри внимательно на метод getAuthor.

Metey 22.07.2019 в 08:42

это я у себя тут что-то начудил, нашел ошибку)

Iliusha99 21.07.2019 в 16:23

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

ivashkevich 21.07.2019 в 19:18

Сможешь через несколько уроков, не бойся

vtolstov 03.10.2019 в 08:23

Вот это жееесть! Вроде осилил, но придется еще не раз это переосмыслить.

ivashkevich 03.10.2019 в 17:16

Изи, изи)

Pro100Bah 07.10.2019 в 17:02

Предыдущие вопросы сами собой отпали, но чтоб все это переварить, ладно справимся)))

P.S.
Прям кайфанул от урока)))

ivashkevich 07.10.2019 в 17:15

Еее!

prinzplanloser0514@gmail.com 08.10.2019 в 22:27

Что-то я пропустил

   public function main()
    {
        $articles = $this->db->query('SELECT * FROM `articles`;', [], Article::class);
        $this->view->renderHtml('main/main.php', ['articles' => $articles]);
    }
}

['articles' => $articles] вот этот момент зачем нам нужен?

ivashkevich 08.10.2019 в 22:34

Переменную в шаблон передаём таким образом. Этот массив потом попадает в функцию extract, перед подключением шаблона.

iluha22 29.10.2019 в 06:35

У меня после всех манипуляций на странице "http://newproj.loc/articles/2" вышла следующая ошибка:

Fatal error:
Uncaught TypeError:
Return value of MyProject\Models\ActiveRecordEntity::getById() must be an instance of MyProject\Models\ActiveRecordEntity or null, array returned in C:\OSPanel\domains\newproj.loc\src\MyProject\Models\ActiveRecordEntity.php:54 Stack trace: #0 C:\OSPanel\domains\newproj.loc\src\MyProject\Controllers\ArticlesController.php(20): MyProject\Models\ActiveRecordEntity::getById(2) #1 C:\OSPanel\domains\newproj.loc\www\index.php(30): MyProject\Controllers\ArticlesController->view(2) #2 {main} thrown in C:\OSPanel\domains\newproj.loc\src\MyProject\Models\ActiveRecordEntity.php on line 54

Вот и всё тут. И не могу найти где собака зарыта.

ivashkevich 29.10.2019 в 06:56

Ошибку не пробовал прочитать?

iluha22 29.10.2019 в 07:10

Вернутое значение getById должно быть экземпляром или нулем, массив получился в ActiveRecordEntity на 54 строке.
И про что это!? ))

 public static function getById(int $id): ?self
    {
        $db = new Db();
        $entities = $db->query(
            'SELECT * FROM `' . static::getTableName() . '` WHERE id=:id;',
            [':id' => $id],
            static::class
        );
// стр.54:
        return $entities ? $entities[0] : null;
    }
ivashkevich 29.10.2019 в 09:41

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

iluha22 29.10.2019 в 09:58

Потому что так в уроке было показано(!) :)

ivashkevich 29.10.2019 в 10:03

Дебаггер в руки и вперёд

iluha22 29.10.2019 в 12:05

Всё как всегда банально оказалось.
В подключении к дб осталась старая запись:

return $sth->fetchAll();

А должно было быть через классы:

return $sth->fetchAll(\PDO::FETCH_CLASS, $className);

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

ivashkevich 29.10.2019 в 12:32

Красава!

iluha22 29.10.2019 в 12:38

Та ваще капец, моск ломает нещадно... фуф...

ivashkevich 29.10.2019 в 13:08

Сам порешал, молодец. Учись читать ошибки, в них всё есть.

zeexo 22.11.2019 в 23:53

ivashkevich, спасибо за урок!
Всё доступно и понятно.
Подскажите, как расширить этот класс?
Например:

$article = Article::getById($articleId);

Как грамотно реализовать добавление дополнительных условий?
Например, вместо getById учитывать несколько условий: WHERE x = 'y' AND a = 'b' ORDER BY k DESC LIMIT n;

ivashkevich 23.11.2019 в 06:02

Судя по запросу вам требуется уже не способ достать по ID, а что-то другое. Просто добавляете в нужную сущность метод findByXAndA()

daneela 04.12.2019 в 21:55
 public function __set(string $name, $value)
    {
        $camelCaseName = $this->underscoreToCamelCase($name);
        $this->$camelCaseName = $value;
    }

    private function underscoreToCamelCase(string $source): string
    {
        return lcfirst(str_replace('_', '', ucwords($source, '_')));
    }

Эти два метода не работают в паттерне, из-за этого не могу вывести никнейм, в чем может быть проблема?Когда методы возвращаю в Article.php всё работает

ivashkevich 05.12.2019 в 14:53

Вы уверены, что понимаете, что такое паттерн?

daneela 05.12.2019 в 22:06

Ошибся, буду дальше изучать

ivashkevich 07.12.2019 в 19:50

С вопросом-то разобрались?) Если нет - напишите лучше в телегу или ВК.

zeexo 19.12.2019 в 01:42

А как можно реализовать findAllCount() по аналогии с findAll(), только запросом COUNT(*) ?
Собственно, получить количество записей таблицы, в рамках работы с ActiveRecord.

ivashkevich 19.12.2019 в 07:44

А в чём проблема? Вы же сами написали ответ на свой вопрос - запросом COUNT(*)

zeexo 19.12.2019 в 15:11

Вопрос в самой реализации кода в ActiveRecordEntity.php

Например код:

    public static function findAllCount(): array
    {
        $db = Db::getInstance();
        return $db->query('SELECT COUNT(*) FROM `' . static::getTableName() . '`;', [], static::class);
    }

Результат просто объект:

array(1) { [0]=> object(App\Models\Model)#8 (2) { ["id":protected]=> NULL ["cOUNT(*)"]=> string(3) "N" } }

Вопрос в том, как грамотно выводить просто число сразу из ActiveRecord при использовании:

Model::findAllCount(); //должно отдавать кол-во записей числом
ivashkevich 21.12.2019 в 20:07

Ну, начать стоит с того, почему вы выбрали тип static::class в качестве результата запроса? Вам ведь нужно только число, для чего его в объект запихивать? Пробовали погуглить по этой теме? Я вот погуглил и нашел ответ на второй позиции поисковика - тут.

andreskrip 30.01.2020 в 17:31

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

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

ivashkevich 31.01.2020 в 13:18

На здоровье)

OneMoreTime 07.03.2020 в 13:33

1.

public function getAuthor(): User
    {
        return User::getById($this->authorId);
    }
<p>Автор: <?= $article->getAuthor()->getNickname() ?></p>

Я до того, как прочитал готовое решение в уроке, пробовал сам делать и сделал сразу в геттере получение и никнейма.

public function getAuthor (): string
    {
        return User::getById($this->authorId)->getNickname();
    }

а в шаблоне уже выводил

<p>Автор:<?= $article->getAuthor()?></p>

Посему у меня возник вопрос : А есть ли разница?

2. Есть ли случаи, когда НУЖНО применять не позднее, а именно раннее связывание? Если да, то можно какие-то примеры?

3. В примере всего две таблицы в БД и данные в них перемежаются, поэтому использован всего один, общий шаблон(и для статей и для юзеров) между БД и "основной программой", хотя в итоге по факту наследования этот шаблон делится уже на два отдельных. А если бы свойства/методы не перемежались у статей и узеров, это были бы отдельные шаблоны? Т.е. фактически для связи основной программы с отдельной таблицей в БД - отдельный шаблон? Префикс ActiveRecord - обязательный в названии класса-шаблона?

ivashkevich 09.03.2020 в 08:14
  1. Тогда название метода некорректно. Он возвращает не автора, а его никнейм.
  2. В любом случае, когда не нужно позднее. Пример: когда вам нужно обращаться к имени класса, в котором код был НЕ ВЫЗВАН, а НАПИСАН, будет использоваться self, а не static.
  3. CRUD-операции для всех сущностей почти всегда будут одинаковыми, поэтому код для работы с БД не требует каких-то особых изменений, в зависимости от конкретной сущности. ActiveRecord даёт нам явно понять какой именно паттерн используется для реализации ORM. Так просто понятнее и является правилом хорошего тона.
Ember 02.04.2020 в 14:35

А не является ли тут нарушением MVC то, что шаблон по сути обращается к модели за автором? По идее это же работа контроллера. Вьюха не должна знать откуда брать данные, ее задача же просто отобразить уже готовые из контроллера.

ivashkevich 02.04.2020 в 15:26

Если хотите, можете сделать и так. Здесь шаблон использует только получение свойства модели, это допустимо.

Ed8L 27.10.2020 в 15:03

Я для тега title передаю название статьи так:

$title = $article->getName(); //ArticlesController.php
<?= $title ?? 'Мой блог' ?> //header.php

Это норм так делать?
И насчет комментария Ember.

$article->getName()
$article->getText()
$article->getAuthor()->getNickname()

Вы сказали получать свойство модели в шаблоне допустимо. А вообще передаваемые переменные в шаблоны надо в контроллере создавать, да?
Просто я подумал что если вы в шаблоне получаете свойства модели, то на то есть причина.

ivashkevich 28.10.2020 в 20:26

Это норм так делать?

Ну в целом да. Просто можно строку по умолчанию брать из какого-нибудь конфига.

А вообще передаваемые переменные в шаблоны надо в контроллере создавать, да?

Ну, если переменная передается из контроллера, то она там и определяется (создаётся, как вы сказали).

Timurik Patron 30.04.2020 в 07:25

Спасибо за урок, очень интересный!
Хотел попросить, если имеется такая возможность, скинуть исходники предыдущего урока, чтобы можно было ещё раз построчно пробежаться по каждому изменению. До этого урока всё понимал быстро, а здесь почему-то мозг взрывается)

ivashkevich 30.04.2020 в 11:42

Сорян, не осталось исходников

Timurik Patron 30.04.2020 в 11:57

Ничего страшного, с 8-го урока пробегусь ещё раз всё руками забью, даже лучше усвою программу.

paskelas 29.05.2020 в 10:05

Так как создание самого этого класса нам не нужно, то делаем его абстрактным.

Может быть, не "создание класса не нужно" , а "создание объектов этого класса не нужно"? Класс-то создается в итоге, а его объекты нет.

ivashkevich 29.05.2020 в 12:52

Конечно да) Спасибо, исправил

tomas Patron 22.08.2020 в 17:50

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

ivashkevich 23.08.2020 в 09:15

Главное понимать как работает на данном этапе. Чуть позже сможете самостоятельно повторить. Еще чуть позже - улучшить.

SkSeMi 21.10.2020 в 19:02

Поясните как быть если запрос в СУБД затрагивает несколько таблиц? То есть тогда каким образом указывать класс объектом которого орм должна дать ответ. И как сам тогда скл запрос вид должен иметь?

ivashkevich 22.10.2020 в 18:48

Один класс отражает работу с одной таблицей. Соответственно в рамках паттерна ActiveRecord один запрос не должен затрагивать несколько таблиц.

SkSeMi 23.10.2020 в 13:59

Хорошо, но как быть если у меня карточка хранится в отд таблице её поля, сами данные о человеке фио и комментарий в др таблице и есть ещё третья таблица список три текст поля для карточки специальные.
Кпрточка пользователя хранится вв иде полей а одной таблице потому что в этом проекте фамилии, имён, отчества могут быть более одного. Потом год, место рождения, наличие фотографий и примечания.
Примечания в отд таблице у меня т. К. Там текст и также может храниться текст вместоварчара как у оси полей карточки.

Таким образом у меня должен быть метод в модели состоящий из нескольких орм актив запросов и потом формироваться, собираться воедино или как!? Просто что описано в статье здорово все, но мне не понятно как получить из бд подобным образом сущность если она составная из нескольких таблиц?! Спасибо!

ivashkevich 26.10.2020 в 13:24

Ну к примеру, есть у тебя Пользователь и есть Социальные_Сети_Пользователя. Тогда в том месте, где нужно получить его социальные сети нужно сделать так:

$user = User::getById(1);
$socialNetworks = $user->getSocialNetworks();

В классе User прописать этот метод:

public function getSocialNetworks(): SocialNetworks
{
    return SocialNetworks::getByColumn('user_id', $this->id);
}

Метод getByColumn может быть реализован как-то так:

public static function getByColumn(string $columnName, $value): self
{
    $db = new Db();
    $entities = $db->query(
        'SELECT * FROM `' . static::getTableName() . '` WHERE '. $columnName .'=:value;',
        [':value' => $value],
        static::class
    );
    return $entities ? $entities[0] : null;
}
SkSeMi 26.10.2020 в 13:57

Привет. Спасибо за ответ. Тогда получается согласно твоему ответу проецируя на мою проблему/вопрос получается следующее. Необходмо для получения составной сущности иметь в определенных моделях отражающих логику подсущностей методы возвращаемые необходимые значения. Эти методы уже должны быть основаны как приведеный тобой метод getByColumn с максимальной универсальностью/Унификацией?!

ТОгда в этом методе луше чтобы было return $entities ? $entities : null;
т.к. могут понадобиьтся все значения, которое может быть не одним единственным.

ivashkevich 26.10.2020 в 18:53

Если метод начинается с get, то подразумевается что он для получения одной сущности. Для получения нескольких лучше назвать метод find.
И тогда просто return $entities;
Потому что если ожидается массив сущностей, то если не нашлось ни одной, правильнее будет вернуть пустой массив, а не null (null подходит чтобы показать что одной сущности нет).

SkSeMi 26.10.2020 в 19:05

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

pixel 17.12.2020 в 05:13

Пришлось попотеть я в файле Db.php написал require_once вместо require. И при запросе автора, файл подключения оказывался пустым. И главное ошибка такая специфическая, сообщала мне, что подключение к БД осуществляется без пароля, хотя в файле с настройками всё прописано) С помощью дебага только нашел)

ivashkevich 17.12.2020 в 17:54

Хех) Молоток, что дебаггером пользуешься

MikeSiebel Patron 16.01.2021 в 23:07

Добрый день! Большое спасибо за урок!
Должен признать, действительно тяжеловато идет это ученье.
Возник вопрос по следующему предложению:
«Обратите внимание, свойства теперь становятся не private, а protected, чтобы к ним можно было достучаться из класса-родителя», - мы вроде бы должны стучаться из класса-наследника в класс-родителя…?

ivashkevich 17.01.2021 в 12:38

Привет! Спасибо, исправил ошибку)

Должен признать, действительно тяжеловато идет это ученье.

Это нормально для процесса обучения. Программирование - это не на саночках кататься) Главное не торопиться, понимать что делаешь.

ivan.tretiakov 21.02.2021 в 07:32

Артем, отличный урок, спасибо! Вопрос такой. Если одно из полей в таблице массив. Свойство класса, соответственно, тоже массив (ORM). Количество элементов в этом массиве всегда разное, от 3 до 10. Как хранить такой массив в БД? Одно из решений - сериализация и хранение под типом BLOB. Рабочий вариант или есть более современные подходы?

ivashkevich 22.02.2021 в 20:22

Хранение в json это обычная практика

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