composer require rtippin/messenger
- Installs the base messenger files, publishing the
messenger.php
configuration file andMessengerServiceProvider
. - This will also register the published service provider in your
app.php
configuration file inside theproviders
array. - You will be asked to confirm running this command, as well as an option to run the migrations before completion.
- If your
Provider|User
models you are registering inMessenger
use UUIDs instead of auto-incrementing integers as their primary keys, add the--uuids
flag when installing.
- If your
php artisan messenger:install
#If your providers use UUIDs
php artisan messenger:install --uuids
- If you opted to not migrate while using the
messenger:install
command above, be sure you run it yourself before using the messenger system.
php artisan migrate
- Providers are the model's from your application you register into
Messenger
. - For most applications, you will only register your
User
model.- If you had a
User
and aTeacher
model, you can register both models withMessenger
, allowing teachers to have their own inbox, and able to message users as a teacher.
- If you had a
- Your provider models will also use the internal Messenger.php model, which acts as a settings model, as well as allowing reverse searching. More on this below, after registering providers.
- Head over to your new
App\Providers\MessengerServiceProvider
- Using the
Messenger
facade, add all provider models you want to register intoMessenger
. The defaultApp\Models\User
is already preset, you just need to un-comment it.
Default:
<?php
namespace App\Providers;
use App\Models\User;
use Illuminate\Support\ServiceProvider;
use RTippin\Messenger\Facades\Messenger;
class MessengerServiceProvider extends ServiceProvider
{
/**
* Bootstrap services.
*
* @return void
*/
public function boot()
{
Messenger::registerProviders([
User::class,
]);
}
}
- Each provider you register must implement the
MessengerProvider
interface. - You should use the included
Messageable
trait on your providers to satisfy theMessengerProvider
interface. - Override the
getProviderSettings()
method on each provider model you register. - The
alias
will be auto-generated if null or not set. When auto-generating, the lower-snake case of the model's name will be used.
Example:
<?php
namespace App\Models;
use Illuminate\Foundation\Auth\User as Authenticatable;
use RTippin\Messenger\Contracts\MessengerProvider;
use RTippin\Messenger\Traits\Messageable;
class User extends Authenticatable implements MessengerProvider
{
use Messageable; //Default trait to satisfy MessengerProvider interface
public static function getProviderSettings(): array
{
return [
'alias' => 'user',
'searchable' => true,
'friendable' => true,
'devices' => true,
'default_avatar' => public_path('vendor/messenger/images/users.png'),
'cant_message_first' => [],
'cant_search' => [],
'cant_friend' => [],
];
}
}
- You must implement the
getProviderSearchableBuilder()
method on providers you want to be searchable. Included is aSearch
trait that works out of the box with the default laravelUser
model.- You must also ensure
searchable
in the providersgetProviderSettings()
method is true (default).
- You must also ensure
- If you have different columns used to search for your provider, you can skip using the included
Search
trait, and define thepublic static getProviderSearchableBuilder()
method yourself.- The query builder will be passed, along with the original full string search term, and an array of the search term exploded via spaces and commas.
Example:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Foundation\Auth\User as Authenticatable;
use RTippin\Messenger\Contracts\MessengerProvider;
use RTippin\Messenger\Traits\Messageable;
class User extends Authenticatable implements MessengerProvider
{
public static function getProviderSearchableBuilder(Builder $query,
string $search,
array $searchItems)
{
$query->where(function (Builder $query) use ($searchItems) {
foreach ($searchItems as $item) {
$query->orWhere('first_name', 'LIKE', "%{$item}%")
->orWhere('last_name', 'LIKE', "%{$item}%");
}
})->orWhere('email', '=', $search);
}
}
- Allows your provider to be friended / have friends.
- Set
friendable
in the providersgetProviderSettings()
method to true (default).
- Devices are a helpful way for you to attach a listener onto the PushNotificationEvent. When any broadcast over a private channel occurs, we forward a stripped down list of all recipients/providers and their types/IDs, along with the original data broadcasted, and the event name.
- To use this event, you must be using the
default
broadcast driver set by this package,BroadcastBroker
, and havepush_notifications
enabled. How you use the data from the event to send push notifications (FCM, APN, etc.) is up to you!
- To use this event, you must be using the
- Provider interactions, defined in each providers
getProviderSettings()
method, give fine grain control over how they can interact with other providers, should you have multiple. - For each interaction, list the provider classes you want to deny that action from the parent provider.
public static function getProviderSettings(): array
{
return [
//.....
'cant_message_first' => [],
'cant_search' => [],
'cant_friend' => [],
];
}
cant_message_first
revokes permissions to initiate a private conversation with the given providers. This does not stop or alter private threads already created, nor does it impact group threads. Creating a new private thread is referred to as "messaging first".
Example: A user may not start the conversation with a company, but a company may start the conversation with the user. Once the private thread is created, it is business as usual!
//User
public static function getProviderSettings(): array
{
return [
'cant_message_first' => [Company::class],
];
}
//Company
public static function getProviderSettings(): array
{
return [
'cant_message_first' => [],
];
}
cant_search
Filters search results, omitting the listed providers.
Example: A user may not search for companies, but a company can search for users.
//User
public static function getProviderSettings(): array
{
return [
'cant_search' => [Company::class],
];
}
//Company
public static function getProviderSettings(): array
{
return [
'cant_search' => [],
];
}
cant_friend
Revokes permission to initiate a friend request with the listed providers. This permission only impacts when one provider sends another a friend request. Cancelling / Accepting / Denying a friend request, or your list of actual friends, is not impacted by this permission.
Example: A user may not send a friend request to a company, but a company can send a friend request to a user.
//User
public static function getProviderSettings(): array
{
return [
'cant_friend' => [Company::class],
];
}
//Company
public static function getProviderSettings(): array
{
return [
'cant_friend' => [],
];
}
- To grab your providers name, the default method returns the
name
column from your model, stripping tags and making words uppercase. You may overwrite the way the name on your model is returned using the below method.
Example: Combining two columns first
and last
for the name
public function getProviderName(): string
{
return strip_tags(ucwords($this->first." ".$this->last));
}
- When provider avatars are enabled, the default column used on each provider models table for the avatar is of type
string/nullable
namedpicture
.- You may overwrite the column name on your provider model using the below method, should your column be named differently.
Example:
public function getProviderAvatarColumn(): string
{
return 'avatar';
}
- If your provider (Eg:
User
) does not have any "avatar/picture" column, or you wish to add a new custom one for use with messenger only, you may create a custom migration to add your new column (must benullable
).
Example Migration and new avatar column override for User
:
//Your migration
Schema::table('users', function (Blueprint $table) {
$table->string('messenger_avatar')->nullable();
});
//User model override
public function getProviderAvatarColumn(): string
{
return 'messenger_avatar';
}
- When online status is enabled, the default column used on each provider models table is of type
timestamp
namedupdated_at
. - This is used to show when a provider was last active, and will be updated to the current timestamp when you use the messenger status heartbeat.
- You may overwrite the column name on your provider model using the below method, should your column be named differently.
Example:
public function getProviderLastActiveColumn(): string
{
return 'last_active';
}
- The Messenger.php model allows your providers to have individual "settings", such as online status and notification sound toggles.
- A
whereHasMorph
query will be used through themessengers
table, enabling your providers search for others through the API. - By default, the
Messenger
model will be created if it does not exist for a provider when accessing themessenger/heartbeat
ormessenger/settings
API. - To ensure your providers are kept in sync, it is best that you attach the messenger model yourself anytime one of your providers is created.
- If you are installing
Messenger
into an application with existing providers/users, you can use the command below to attach the Messenger.php model to all existing records for each of the providers you registered above.
php artisan messenger:attach:messengers
See the Command's documentation for more information.
- When one of your registered providers is created, such as a new
User
, you should attach the Messenger.php model using one of the methods below:
Example using a User model
use App\Models\User;
use RTippin\Messenger\Facades\Messenger;
$user = User::create([
'email' => 'new@example.org'
]);
Messenger::getProviderMessenger($user);
Example using a User model
use App\Models\User;
use RTippin\Messenger\Models\Messenger;
$user = User::create([
'email' => 'new@example.org'
]);
Messenger::factory()->owner($user)->create();
For your model factories, you can implement the afterCreating
hook in the configure
method to attach the messenger model
Example using a User model factory
<?php
namespace Database\Factories;
use App\Models\User;
use Illuminate\Database\Eloquent\Factories\Factory;
use RTippin\Messenger\Models\Messenger;
class UserFactory extends Factory
{
protected $model = User::class;
public function definition(): array
{
return [
'name' => $this->faker->name,
'email' => $this->faker->unique()->safeEmail,
'demo' => true,
'admin' => false,
'password' => 'password',
];
}
public function configure(): self
{
return $this->afterCreating(function (User $user) {
Messenger::factory()->owner($user)->create();
});
}
}