Skip to content

Instantly share code, notes, and snippets.

@kefzce
Last active December 8, 2017 18:23
Show Gist options
  • Save kefzce/28bb14674a40b54aed6c4702eaf8dc18 to your computer and use it in GitHub Desktop.
Save kefzce/28bb14674a40b54aed6c4702eaf8dc18 to your computer and use it in GitHub Desktop.
<?php
try {
/** @var \Telegram\Bot\Objects\User $userUpdate */
$userUpdate = $update->getFrom();
/** @var \Telegram\Bot\Objects\Chat $chatUpdate */
$chatUpdate = $update->getChat();
$userExist = User::where('user_id', '=', $userUpdate->getId())->first();
$chatExist = Chat::where('chat_id', '=', $chatUpdate->getId())->first();
if ($userExist && ! $chatExist) {
$chat = Chat::create([
'chat_id' => $chatUpdate->getId(),
'title' => $chatUpdate->getTitle(),
'type' => $chatUpdate->getType(),
]);
$userExist->chat()->save($chat);
$message = Message::create([
'message_id' => $update->getMessage()->getMessageId() ?? $update->getEditedMessage()->getMessageId(),
'user_id' => $messageUpdate->getFrom()->getId(),
'chat_id' => $messageUpdate->getChat()->getId(),
'text' => $messageUpdate->getText(),
]);
$userExist->messages()->save($message);
} elseif (! $userExist && ! $chatExist) {
$user = User::create([
'user_id' => $userUpdate->getId(),
'first_name' => $userUpdate->getFirstName(),
'last_name' => $userUpdate->getLastName(),
'username' => $userUpdate->getUsername(),
'language_code' => $userUpdate->getLanguageCode(),
]);
$chat = Chat::create([
'chat_id' => $chatUpdate->getId(),
'title' => $chatUpdate->getTitle(),
'type' => $chatUpdate->getType(),
]);
$user->chat()->save($chat);
$message = Message::create([
'message_id' => $update->getMessage()->getMessageId() ?? $update->getEditedMessage()->getMessageId(),
'user_id' => $messageUpdate->getFrom()->getId(),
'chat_id' => $messageUpdate->getChat()->getId(),
'text' => $messageUpdate->getText(),
]);
$chat->messages()->save($message);
$user->messages()->save($message);
} elseif (! $userExist && $chatExist) {
$user = User::create([
'user_id' => $userUpdate->getId(),
'first_name' => $userUpdate->getFirstName(),
'last_name' => $userUpdate->getLastName(),
'username' => $userUpdate->getUsername(),
'language_code' => $userUpdate->getLanguageCode(),
]);
$message = Message::create([
'message_id' => $update->getMessage()->getMessageId() ?? $update->getEditedMessage()->getMessageId(),
'user_id' => $messageUpdate->getFrom()->getId(),
'chat_id' => $messageUpdate->getChat()->getId(),
'text' => $messageUpdate->getText(),
]);
$chatExist->messages()->save($message);
$user->chat()->save($chatExist);
$user->messages()->save($message);
} elseif ($userExist && $chatExist) {
$message = Message::create([
'message_id' => $update->getMessage()->getMessageId() ?? $update->getEditedMessage()->getMessageId(),
'user_id' => $messageUpdate->getFrom()->getId(),
'chat_id' => $messageUpdate->getChat()->getId(),
'text' => $messageUpdate->getText(),
]);
$chatExist->messages()->save($message);
$userExist->messages()->save($message);
}
} catch (FatalThrowableError $exception) {
}
}
<?
User(users table) && chat(chats table) linked through pivot_table chat_user:
Schema::create('chat_user', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id')->unsigned();
$table->foreign('user_id')->references('id')->on('users');
$table->integer('chat_id')->unsigned();
$table->foreign('chat_id')->references('id')->on('chats');
});
Message(messages table) && chat(chats table) linked throught pivot_table chat_message:
Schema::create('chat_message', function (Blueprint $table) {
$table->increments('id');
$table->integer('message_id')->unsigned();
$table->integer('chat_id')->unsigned();
$table->foreign('message_id')->references('id')->on('messages')->onDelete('cascade');
$table->foreign('chat_id')->references('id')->on('chats')->onDelete('cascade');
$table->timestamps();
});
/**
*Нужно разделить лапшу в слушателе таким образом, что бы избавиться от веток условий if elseif,сохранить SRP и сейвить все в моделях,
*причем вариант с дополнительными методами для каждой сущности, вроде $this->createMessageFromUpdate не нравится
*интересует что то вроде дополнительной прослойки между моделью и апдейтом, которая и разрулила бы это все, по возможности,
*если есть более true way варианты, буду рад.
**/
/**
*Апдейт, это некая post информация, которая прилетела по ендпоинту мне на сервер.
**/
Route::post('/webhook', 'Bots\TelegramController@webhook');
TelegramController@webhook:
$update = $this->telegram->getWebhookUpdate();
event(new UpdateWasReceived($update)); //Простая реализация Observer pattern
'App\Events\Bots\UpdateWasReceived' => [ //Событие
'App\Listeners\Bots\ProcessingUpdates', //Слушатели
'App\Listeners\Bots\DoSomeOtherStuff',
],
@bagart
Copy link

bagart commented Dec 3, 2017

function run() {
    try {
        
        /** @var \Telegram\Bot\Objects\User $userUpdate */
        $userUpdate = $update->getFrom();
        /** @var \Telegram\Bot\Objects\Chat $chatUpdate */
        $chatUpdate = $update->getChat();
        $user = User::where('user_id', '=', $userUpdate->getId())->first();
        $chat = Chat::where('chat_id', '=', $chatUpdate->getId())->first();
        $message_id = $update->getMessage()->getMessageId() ?? $update->getEditedMessage()->getMessageId();
        if (!$user) {
            $user = $this->createUser($userUpdate);
        }
        if (!$chatExist) {
            $chat = $this->createChat($chatUpdate);
        }
        $userExist->messages()->save(
            $this->createMessage(
                $messageUpdate,
                $message_id,
            )
        );
    } catch (FatalThrowableError $exception) { }
}

function createMessage($messageUpdate, $message_id) {
    return Message::create([
        'message_id' => $message_id,
        'user_id' => $messageUpdate->getFrom()->getId(),
        'chat_id' => $messageUpdate->getChat()->getId(),
        'text' => $messageUpdate->getText(),
    ]);
}

function createChat($chatUpdate) {
    return Chat::create([
        'chat_id' => $chatUpdate->getId(),
        'title' => $chatUpdate->getTitle(),
        'type' => $chatUpdate->getType(),
    ]);
}

function createUser($userUpdate) {
    return User::create([
        'user_id' => $userUpdate->getId(),
        'first_name' => $userUpdate->getFirstName(),
        'last_name' => $userUpdate->getLastName(),
        'username' => $userUpdate->getUsername(),
        'language_code' => $userUpdate->getLanguageCode(),
    ]);
}


@RALMAZ
Copy link

RALMAZ commented Dec 3, 2017

Сложна сложна 🐈 🐈 🐈 🐈 🐈 🐈

Голосую за распилку на 3 файла 🐈

@fesor
Copy link

fesor commented Dec 3, 2017

ох... сча... для начала попробуем представить этот код как чуть менее грамоздкие действия (дабы понять почему у нас там столько условий и столько дублирования):

 - try
  - проверить что чат существует
  - проверить что пользователь существует
  - если пользователь существует, но нет чата
     - создаем чат
     - создаем сообщение
  - иначе если пользователя нет, и чата нет
     - создаем пользователя
     - создаем чат
     - создаем сообщение
  - иначе если пользователя нет но есть чат
     - создаем пользователя
     - создаем сообщение
  - иначе если все есть
     - создаем сообщение

на лицо - не оптимизирована логика. Например стэп "создаем сообщение" присутствует во всех ветках. Можем спокойно вынести это последним пунктом в условии.

- try
 - проверить что чат существует
 - проверить что пользователь существует
 - если пользователь существует, но нет чата
    - создаем чат
 - иначе если пользователя нет, и чата нет
    - создаем пользователя
    - создаем чат
 - иначе если пользователя нет но есть чат
    - создаем пользователя
 - создаем сообщение

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

- try
 - проверить что чат существует
 - проверить что пользователь существует
 - если пользователя нет
    - создаем пользователя
 - если нет чата
    - создаем чат
 - создаем сообщение

Это то что тебе @bagart и предложил.

Голосую за распилку на 3 файла

в этом нет смысла.

@kefzce
Copy link
Author

kefzce commented Dec 3, 2017

Появился дополнительный вариант с репозиториями, в кратце его можно изобразить как то так:

$chat =  $chatRep->create()
$user = $userRep->create();
$message = $messRep->create($chat,$user);

@bagart
Copy link

bagart commented Dec 3, 2017

$message = $messRep->create($chat,$user);
в данном случае это ничего не меняет и не имеет особого смысла
message model - activerecod. доп логики при сохранение не требуется.
если всё выносить и "отказаться" от логики activerecord то кол-ва кода резко увеличится в противоречие фреймворку

ну и вообще форвардинг и редактирование по разному можно обрабатывать

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment