0
\$\begingroup\$

Is this a good approach for validating user input in a chatbot? I am writing an autoposter telegram bot in PHP using the php-telegram-bot library (by Longman). I have a Task class that stores information about the task (repetition period, message data, etc.).

class Task
{

    #[ORM\Id]
    #[ORM\Column(type: 'integer')]
    #[ORM\GeneratedValue]
    private int|null $id;

    #[ORM\Column(type: 'boolean')]
    private bool $isOn;

    #[ORM\Column(type: 'time')]
    private DateTime $startAt;

    #[ORM\Column(type: 'integer')]
    private int $repeatIntervalSeconds;

    #[ORM\Column(type: 'datetime')]
    private DateTime $endAt;

    #[ORM\Column(type: 'simple_array')]
    private array $chats = [];

    #[ORM\Column(type: 'integer')]
    private int $messageChatId;

    #[ORM\Column(type: 'integer')]
    private int $messageId;

    //...
}

I also have a command /taskcreate that consistently asks questions like "Send the date and time when the message replay will be disabled." and waits for the user's response. The problem is that I also have commands like /taskchangerepetition or /taskchangemessage that need to duplicate the user input validation code. The question is: what is the best way to implement this validation, should I create a static validator class or should I do the validation in the Task class itself? Or there are other ways. Currently I am using this:


// TaskcreateCommand.php

// State machine
// Every time a step is achieved the state is updated
// ...
case 3:

    if ($text === '' || !TaskValidator::validateEndAt($text)) {
        $notes['state'] = 3;
        $this->conversation->update();
        $data['text'] = '👉 Send the date and time when the message replay will be disabled.' . PHP_EOL . PHP_EOL . 
                        '❓ You must specify the date in the format dd/mm/yy hh:mm' . PHP_EOL . 'Example: 15/08/23 02:59';

        if ($text !== '') {
            $data['text'] = '⚠️ Invalid format';
        }

        $result = Request::sendMessage($data);
        break;
    }

    $notes['end_at'] = $text;
    $text             = '';

// TaskValidator.php

public static function validateEndAt($input): bool {

    $dateObj = DateTime::createFromFormat('d.m.Y H:i', $input);
    $now = new DateTime('now');

    return $dateObj !== false && $dateObj > $now;
        
}
\$\endgroup\$
2
  • \$\begingroup\$ You've flagged your question as php orm and telegram, but then say you're trying to validate input, which is entirely independent of all 4 tags you've listed \$\endgroup\$ Commented Aug 28, 2023 at 17:06
  • \$\begingroup\$ State machines are modeled with the momento pattern. Validation is typically done with a Chain of responsibility. \$\endgroup\$ Commented Aug 28, 2023 at 17:09

1 Answer 1

1
\$\begingroup\$

I think the best option is to implement the validate function inside task class. It should be a behaviour of the task class.

And why don't you use polymorphism here? You have Task class but you have at least 3 types of Task here: CreateCommnad, ChangeRepetition, ChangeMessage

You can have a called basic validate function in Task class and extend or change the implementation in subclasses to fit the expected input.

Assuming you know about OOP, that's one way we can use to eliminate code duplication and avoid switch/case condition. Then you can use Factory pattern to create Task

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.