tobento/service-message

Messages for PHP applications.

1.0.2 2024-03-01 18:48 UTC

This package is auto-updated.

Last update: 2024-03-30 19:04:23 UTC


README

Messages for PHP applications.

Table of Contents

Getting started

Add the latest version of the Message service project running this command.

composer require tobento/service-message

Requirements

  • PHP 8.0 or greater

Highlights

  • Framework-agnostic, will work with any project
  • Decoupled design

Documentation

Message

Create Message

use Tobento\Service\Message\Message;
use Tobento\Service\Message\MessageInterface;

$message = new Message(
    level: 'success',
    message: 'Hello :name, welcome back',
    context: ['logged_in' => 'John'],
    key: 'user.name', // null|string
    parameters: [':name' => 'John'],
    logged: false,
);

var_dump($message instanceof MessageInterface);
// bool(true)

Parameters explanation

Parameter Description
level Any level. It's up to you.
message The message.
context Any context for the message.
key A key which might be used for an identifier for input data for instance.
parameters Any parameters used for Modifiers.
logged Used as to know if message has been logged already as not to log muliple times.

Message Factory

createMessage

use Tobento\Service\Message\MessageFactory;
use Tobento\Service\Message\MessageFactoryInterface;
use Tobento\Service\Message\MessageInterface;

$messageFactory = new MessageFactory();

var_dump($messageFactory instanceof MessageFactoryInterface);
// bool(true)

$message = $messageFactory->createMessage(
    level: 'error',
    message: 'Any error message',
    context: [],
    key: null,
    parameters: [],
    logged: false,
);

var_dump($message instanceof MessageInterface);
// bool(true)

createMessageFromArray

use Tobento\Service\Message\MessageFactory;
use Tobento\Service\Message\MessageFactoryInterface;
use Tobento\Service\Message\MessageInterface;

$messageFactory = new MessageFactory();

var_dump($messageFactory instanceof MessageFactoryInterface);
// bool(true)

$message = $messageFactory->createMessageFromArray([
    'level' => 'error',
    'message' => 'Any error message',
    'context' => [],
    'key' => null,
    'parameters' => [],
    'logged' => false,
]);

var_dump($message instanceof MessageInterface);
// bool(true)

Message Interface

The message interface has the following methods:

use Tobento\Service\Message\Message;
use Tobento\Service\Message\MessageInterface;

$message = new Message('error', 'Any error message');

var_dump($message instanceof MessageInterface);
// bool(true)

var_dump($message->level());
// string(5) "error"

var_dump($message->message());
// string(17) "Any error message"

var_dump($message->context());
// array(0) { }

var_dump($message->key());
// NULL or string if a key is set.

var_dump($message->parameters());
// array(0) { }

var_dump($message->parameter('name', 'default'));
// string(7) "default"

var_dump($message->logged());
// bool(false)

With methods

You may use the with prefixed methods returning a new instance.

use Tobento\Service\Message\Message;
use Tobento\Service\Message\MessageInterface;

$message = new Message('error', 'Any error message');

var_dump($message instanceof MessageInterface);
// bool(true)

$newMessage = $message->withLevel('success');

var_dump($newMessage === $message);
// bool(false)

$newMessage = $message->withMessage('Hello :name, welcome back');

$newMessage = $message->withContext(['logged_in' => 'John']);

$newMessage = $message->withKey('user.name');

$newMessage = $message->withParameters([':name' => 'John']);

$newMessage = $message->withLogged(false);

Render Message

use Tobento\Service\Message\Message;

$message = new Message('error', 'Any error message');

<?= $message ?>
// is escaped

<?= $message->message() ?>
// is NOT escaped

Messages

Create Messages

use Tobento\Service\Message\Messages;
use Tobento\Service\Message\MessagesInterface;
use Tobento\Service\Message\MessageFactoryInterface;
use Tobento\Service\Message\ModifiersInterface;
use Psr\Log\LoggerInterface;

$messages = new Messages(
    messageFactory: null, // null|MessageFactoryInterface
    modifiers: null, // null|ModifiersInterface
    logger: null, // null|LoggerInterface
);

var_dump($messages instanceof MessagesInterface);
// bool(true)

Parameters explanation

Parameter Description
messageFactory Used for creating messages.
modifiers Used for modifying message. See Modifiers for more detail.
logger If a logger is set, messages will be logged right after messages are added and log parameter is set to true.

withMessageFactory

use Tobento\Service\Message\Messages;
use Tobento\Service\Message\MessageFactory;
use Tobento\Service\Message\MessageFactoryInterface;

$messages = new Messages();

$newMessages = $messages->withMessageFactory(
    messageFactory: new MessageFactory()
);

var_dump($newMessages->messageFactory() instanceof MessageFactoryInterface);
// bool(true)

withModifiers

use Tobento\Service\Message\Messages;
use Tobento\Service\Message\Modifiers;
use Tobento\Service\Message\ModifiersInterface;

$messages = new Messages();

$newMessages = $messages->withModifiers(
    modifiers: new Modifiers()
);

var_dump($newMessages->modifiers() instanceof ModifiersInterface);
// bool(true)

withLogger

use Tobento\Service\Message\Messages;
use Psr\Log\LoggerInterface;

$messages = new Messages();

$newMessages = $messages->withLogger(
    logger: null // null|LoggerInterface
);

var_dump($newMessages->logger() instanceof LoggerInterface);
// bool(false) as null

Messages Factory

You might want to use the message factory to create the messages.

use Tobento\Service\Message\MessagesFactory;
use Tobento\Service\Message\MessagesFactoryInterface;
use Tobento\Service\Message\MessageFactoryInterface;
use Tobento\Service\Message\MessagesInterface;
use Tobento\Service\Message\ModifiersInterface;
use Psr\Log\LoggerInterface;

$messagesFactory = new MessagesFactory(
    messageFactory: null, // null|MessageFactoryInterface
    modifiers: null, // null|ModifiersInterface
    logger: null, // null|LoggerInterface
);

var_dump($messagesFactory instanceof MessagesFactoryInterface);
// bool(true)

$messages = $messagesFactory->createMessages();

var_dump($messages instanceof MessagesInterface);
// bool(true)

Add Messages

By using the addMessage method:

use Tobento\Service\Message\Messages;
use Tobento\Service\Message\Message;

$messages = new Messages();

$messages->addMessage(
    message: new Message('error', 'Error message'),
    log: false,
);

By using the add method:

use Tobento\Service\Message\Messages;

$messages = new Messages();

$messages->add(
    level: 'error',
    message: 'Error message',
    context: [],
    key: null, // null|string
    parameters: [],
    log: false,
);

By using the push method:

use Tobento\Service\Message\Messages;
use Tobento\Service\Message\MessagesInterface;

$someMessages = new Messages();
$someMessages->add('error', 'Error message');

$messages = new Messages();
$messages->add('success', 'Success message');

$messages->push(
    messages: $someMessages // array|MessagesInterface
);

$messages->push(
    messages: [
        ['level' => 'info', 'message' => 'Some info'],
    ]
);

By using the withMessage method returning a new instance:

use Tobento\Service\Message\Messages;
use Tobento\Service\Message\MessageInterface;

$someMessages = new Messages();
$someMessages->add('error', 'Error message');

$messages = new Messages();
$messages->add('success', 'Success message');

$newMessages = $messages->withMessage(
    ...$someMessages // MessageInterface
);

Filter Messages

Filter methods always returning a new instance.

filter

use Tobento\Service\Message\Messages;
use Tobento\Service\Message\MessageInterface;

$messages = new Messages();
$messages->add('success', 'Success message');
$messages->add('error', 'Error message');

$messages = $messages->filter(
    fn(MessageInterface $m): bool => $m->level() === 'error'
);

key

Filters messages by its key:

use Tobento\Service\Message\Messages;

$messages = new Messages();
$messages->add(level: 'success', message: 'Success message', key: 'foo');
$messages->add('error', 'Error message');

$messages = $messages->key('foo');

only

Filters messages only with the levels specified:

use Tobento\Service\Message\Messages;

$messages = new Messages();
$messages->add('success', 'Success message');
$messages->add('error', 'Error message');
$messages->add('info', 'Info message');

$messages = $messages->only(levels: ['info', 'success']);

except

Filters messages except with the levels specified:

use Tobento\Service\Message\Messages;

$messages = new Messages();
$messages->add('success', 'Success message');
$messages->add('error', 'Error message');
$messages->add('info', 'Info message');

$messages = $messages->except(levels: ['info', 'success']);

Get Messages

all

use Tobento\Service\Message\Messages;
use Tobento\Service\Message\MessageInterface;

$messages = new Messages();
$messages->add('success', 'Success message');
$messages->add('error', 'Error message');

foreach($messages->all() as $message) {
    var_dump($message instanceof MessageInterface);
    //bool(true)
}

// or just
foreach($messages as $message) {
    var_dump($message instanceof MessageInterface);
    //bool(true)
}

first

Get the first message:

use Tobento\Service\Message\Messages;
use Tobento\Service\Message\MessageInterface;

$messages = new Messages();
$messages->add('success', 'Success message');
$messages->add('error', 'Error message');

var_dump($messages->first() instanceof MessageInterface);
// bool(true)

last

Get the last message:

use Tobento\Service\Message\Messages;
use Tobento\Service\Message\MessageInterface;

$messages = new Messages();
$messages->add('success', 'Success message');
$messages->add('error', 'Error message');

var_dump($messages->last() instanceof MessageInterface);
// bool(true)

column

use Tobento\Service\Message\Messages;

$messages = new Messages();
$messages->add('success', 'Success message');
$messages->add('error', 'Error message');

$values = $messages->column(
    column: 'message',
    index: 'key',
);

var_dump($values);
// array(2) { [0]=> string(15) "Success message" [1]=> string(13) "Error message" }

has

use Tobento\Service\Message\Messages;

$messages = new Messages();
$messages->add('success', 'Success message');
$messages->add('error', 'Error message');

var_dump($messages->has());
// bool(true)

var_dump($messages->has(levels: ['error', 'success']));
// bool(true)

var_dump($messages->has(levels: ['error', 'info']));
// bool(false)

Messages Aware

You might support messages in any class by using the HasMessages trait:

use Tobento\Service\Message\HasMessages;
use Tobento\Service\Message\MessagesAware;
use Tobento\Service\Message\MessagesInterface;

class Foo implements MessagesAware
{
    use HasMessages;
}

$foo = new Foo();

var_dump($foo->messages() instanceof MessagesInterface);
// bool(true)

Modifiers

Modifiers can be used for modifying the message such as translating.

Create Modifiers

use Tobento\Service\Message\Modifiers;
use Tobento\Service\Message\ModifiersInterface;
use Tobento\Service\Message\Modifier;

$modifiers = new Modifiers(
    new Modifier\ParameterReplacer(),
);

var_dump($modifiers instanceof ModifiersInterface);
// bool(true)

Add Modifier

use Tobento\Service\Message\Modifiers;
use Tobento\Service\Message\Modifier;

$modifiers = new Modifiers();

$modifiers->add(new Modifier\ParameterReplacer());

Prepend Modifier

Adds a modifier to the beginning.

use Tobento\Service\Message\Modifiers;
use Tobento\Service\Message\Modifier;

$modifiers = new Modifiers();

$modifiers->add(new Modifier\ParameterReplacer());

$modifiers->prepend(new Modifier\Pluralization());

Modify Message

use Tobento\Service\Message\Modifiers;
use Tobento\Service\Message\Modifier;
use Tobento\Service\Message\Message;

$modifiers = new Modifiers(
    new Modifier\ParameterReplacer(),
);

$message = new Message(
    level: 'success',
    message: 'Hello :name, welcome back',
    parameters: [':name' => 'John'],
);

$newMessage = $modifiers->modify($message);

var_dump($newMessage->message());
// string(24) "Hello John, welcome back"

var_dump($newMessage === $message);
// bool(false)

Get Modifiers

use Tobento\Service\Message\Modifiers;
use Tobento\Service\Message\ModifierInterface;
use Tobento\Service\Message\Modifier;

$modifiers = new Modifiers(
    new Modifier\ParameterReplacer(),
);

foreach($modifiers->all() as $modifier) {
    var_dump($modifier instanceof ModifierInterface);
    // bool(true)
}

Modifier

Pluralization

use Tobento\Service\Message\Modifier\Pluralization;
use Tobento\Service\Message\ModifierInterface;
use Tobento\Service\Message\Message;

$modifier = new Pluralization(key: 'count');

var_dump($modifier instanceof ModifierInterface);
// bool(true)

$message = new Message(
    level: 'success',
    message: 'One item created|Many items created',
    parameters: ['count' => 5],
);

$newMessage = $modifier->modify($message);

var_dump($newMessage->message());
// string(18) "Many items created"

var_dump($newMessage === $message);
// bool(false)

Parameter Replacer

use Tobento\Service\Message\Modifier\ParameterReplacer;
use Tobento\Service\Message\ModifierInterface;
use Tobento\Service\Message\Message;

$modifier = new ParameterReplacer();

var_dump($modifier instanceof ModifierInterface);
// bool(true)

$message = new Message(
    level: 'success',
    message: 'Hello :name, welcome back',
    parameters: [':name' => 'John'],
);

$newMessage = $modifier->modify($message);

var_dump($newMessage->message());
// string(24) "Hello John, welcome back"

var_dump($newMessage === $message);
// bool(false)

Limit Length

use Tobento\Service\Message\Modifier\LimitLength;
use Tobento\Service\Message\ModifierInterface;
use Tobento\Service\Message\Message;

$modifier = new LimitLength(
    length: 15,
    parameterKey: 'limit_length',
);

var_dump($modifier instanceof ModifierInterface);
// bool(true)

$message = new Message(
    level: 'success',
    message: 'Some very long message',
    parameters: [
        // used instead of default if set.
        'limit_length' => 10,
    ],
);

$newMessage = $modifier->modify($message);

var_dump($newMessage->message());
// string(10) "Some ve..."

var_dump($newMessage === $message);
// bool(false)

Translator

For more information about the translator, check out the Translation Service documentation.

use Tobento\Service\Translation;
use Tobento\Service\Message\Modifier\Translator;
use Tobento\Service\Message\ModifierInterface;
use Tobento\Service\Message\Message;

$translator = new Translation\Translator(
    new Translation\Resources(
        new Translation\Resource('*', 'en', [
            'Some error occured' => 'Some error occured',
        ]),
        new Translation\Resource('*', 'de', [
            'Some error occured' => 'Ein Fehler is passiert',
        ]),
    ),
    new Translation\Modifiers(
        new Translation\Modifier\Pluralization(),        
        new Translation\Modifier\ParameterReplacer(),
    ),
    new Translation\MissingTranslationHandler(),
    'de',
);

$modifier = new Translator(
    translator: $translator,
    src: '*',
);

var_dump($modifier instanceof ModifierInterface);
// bool(true)

$message = new Message(
    level: 'error',
    message: 'Some error occured',
);

$newMessage = $modifier->modify($message);

var_dump($newMessage->message());
// string(22) "Ein Fehler is passiert"

var_dump($newMessage === $message);
// bool(false)

Parameter Translator

Sometimes you might need to translate message parameters:

use Tobento\Service\Translation;
use Tobento\Service\Message\Modifier\ParameterTranslator;
use Tobento\Service\Message\ModifierInterface;
use Tobento\Service\Message\Message;

$translator = new Translation\Translator(
    new Translation\Resources(
        new Translation\Resource('*', 'en', [
            'title' => 'title',
        ]),
        new Translation\Resource('*', 'de', [
            'title' => 'Titel',
        ]),
    ),
    new Translation\Modifiers(
        new Translation\Modifier\Pluralization(),        
        new Translation\Modifier\ParameterReplacer(),
    ),
    new Translation\MissingTranslationHandler(),
    'de',
);

$modifier = new ParameterTranslator(
    parameters: [':attribute'],
    translator: $translator,
    src: '*',
);

var_dump($modifier instanceof ModifierInterface);
// bool(true)

$message = new Message(
    level: 'error',
    message: 'The :attribute is invalid.',
    parameters: [
        ':attribute' => 'title',
    ],
);

$newMessage = $modifier->modify($message);

var_dump($newMessage->parameters()[':attribute']);
// string(5) "Titel"

var_dump($newMessage->message());
// string(26) "The :attribute is invalid."

var_dump($newMessage === $message);
// bool(false)

Credits