yaleksandr89
@yaleksandr89
Junior backend developer

Как правильно реализовать реализовать классы Родитель->Потомок?

Здравствуйте.
Не так давно стал изучать ООП, поэтому прощу строго не судить :)
Нужно решить такую задачу. Есть класс:
class Subscribe

<?php declare(strict_types=1);
class SubscribeController
{
    public function notify(Request $request)
    {
        $email = $request->json('from.email');
        if (!isset($email)) {
            return self::userError('from.email is missing.');
        }
        if (!is_string($email)) {
            return self::userError('from.email must be a string.');
        }

        $name = $request->json('from.name');
        if (isset($name) && !is_string($name)) {
            return self::userError('from.name must be either null or a string.');
        }

        try {
            $mailer = Factory::createMailer(app()->basePath(), new EmailAddress($email, $name));
            $mailer->notify('тут название события', new EmailAddress('тут почта', 'тут имя'));
        } catch (Exception $e) {
            return self::error($e->getMessage());
        }

        return self::ok();
    }

    privat static function userError($message)
    {
        return self::error($message, 400);
    }

    privat static function error($message, $code = 500)
    {
        return response()->json($message, $code);
    }

    privat static function ok()
    {
        return response()->json("ok");
    }
}


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

Так как в программирование занимаюсь от силы 6-7 месяцев и до этого шпарил исключительно на процедурке, первое что я сделал в такой ситуации - наговнокодил :) т.е. тупо скопировал содержимое этого класса, дал ему другое название и поменял тип события, фактически изменения (не считая переименования класса) были лишь в одной строке:
$mailer->notify('тут название события', new EmailAddress('тут почта', 'тут имя'));

Понял, что так дела не делаются, попытался вспомнить те статьи и видео, которые я смотрел по ООП (Где объяснялось: есть общий класс Животные, а есть классы Собака, Кошка и т.д.). Решил сделать нечто похожее. Сделать один общий класс SubscribeController и extends создать классы New, Didgest и т.д.

Переименовал приватные методы (обрабатывающие ошибки в protect), вынес в класс-родитель все что смог вынести и классы-потомки стали выглядеть примерно так:
Пример класса потомка

class Didgest extends SubscribeController
{
public function notify(Request $request)
    {
        $email = $request->json('from.email');
        if (!isset($email)) {
            return self::userError('from.email is missing.');
        }
        if (!is_string($email)) {
            return self::userError('from.email must be a string.');
        }

        $name = $request->json('from.name');
        if (isset($name) && !is_string($name)) {
            return self::userError('from.name must be either null or a string.');
        }

        try {
            $mailer = Factory::createMailer(app()->basePath(), new EmailAddress($email, $name));
            $mailer->notify('didgest', new EmailAddress('email', 'name'));
        } catch (Exception $e) {
            return self::error($e->getMessage());
        }

        return self::ok();
    }
}


Но даже тут видно, что копипасты крайне много осталось, фактически, в зависимости от типа события, мне нужно лишь менять название здесь:
$mailer->notify('--->NEW<---', new EmailAddress('email', 'name'));
   $mailer->notify('--->DIDGEST<---, new EmailAddress('email', 'name'));


Собственно подскажите, как можно убрать в класс-родитель(SubscribeController):
$email = $request->json('from.email');
        if (!isset($email)) {
            return self::userError('from.email is missing.');
        }
        if (!is_string($email)) {
            return self::userError('from.email must be a string.');
        }

        $name = $request->json('from.name');
        if (isset($name) && !is_string($name)) {
            return self::userError('from.name must be either null or a string.');
        }


Если его убрать в общий класс, то начинают ругаться переменные: $email, $name, что вполне логично, а как их сделать видимыми из класса-родителя в классах-потомках ума не приложу :( или может вы подскажите, какой-то более элегантный способ в такой ситуации.

Буду очень признателен за помощь!
  • Вопрос задан
  • 118 просмотров
Пригласить эксперта
Ответы на вопрос 2
gzhegow
@gzhegow
Думал, стану умнее, когда адаптируюсь, но нет
Вот как я понимал события

<?php

$events = [];

$on = function (string $name, callable $func) use (&$events)
{
  $events[ $name ][] = $func;
};

$fire = function (string $name, $emitter, ...$arguments) use (&$events)
{
  if (! isset($events[ $name ])) return;
  
  foreach ($events[ $name ] as $func) {
    call_user_func($func, $name, $emitter, ...$arguments);
  }
};

// когда машина выйдет с завода - поехали!
$on('car-created', function ($event, $car, ...$comments) { var_dump($car, $comments); });

// ...some application code

// пришло время, тачка готова.
$fire('car-created', $car, 'faster', 'darling');


Что тут есть. Есть массив, хранилище, где будут лежать инструкции $func "что сделать", привязанные на ключ $name - "когда сделать".

Есть функция $on, которая тупо на некое имя записывает в хранилище что делать.
Есть функция $fire, которая "стреляет" - начинает выполнять всё, что висит на этом `$name`. В параметре эмиттер может быть что угодно, что душе хочется - обычно это виновник торжества, из-за чего событие стрельнуло.

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

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

Пока просто вот так отнесись к этому
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы
от 150 000 до 180 000 руб.
N1.RU Новосибирск
от 100 000 руб.
16 сент. 2019, в 18:39
2000 руб./за проект
16 сент. 2019, в 18:30
3000 руб./за проект
16 сент. 2019, в 18:27
1500 руб./в час