ChatifyPHP

Backend Customization

Override models, policies, resolvers, actions, middleware, rate limiters, and more

Chatify is designed to be extended. This page covers every backend customization hook.

Publishing assets

The installer publishes common assets automatically, but you can also publish specific groups using tags:

php artisan vendor:publish --tag=chatify-config
php artisan vendor:publish --tag=chatify-migrations
php artisan vendor:publish --tag=chatify-channels
php artisan vendor:publish --tag=chatify-views
php artisan vendor:publish --tag=chatify-assets
php artisan vendor:publish --tag=chatify-patterns
php artisan vendor:publish --tag=chatify-sounds
php artisan vendor:publish --tag=chatify-frontend
php artisan vendor:publish --tag=chatify-lang
TagWhat it publishesDestination
chatify-configConfiguration fileconfig/chatify.php
chatify-migrationsDatabase migrationsdatabase/migrations/
chatify-channelsBroadcast channel definitionsroutes/chatify/channels.php
chatify-viewsBlade views (layout + page)resources/views/vendor/chatify/
chatify-assetsCompiled frontend bundlepublic/vendor/chatify/
chatify-patternsWallpaper SVG patternspublic/vendor/chatify/patterns/
chatify-soundsSound filespublic/vendor/chatify/sounds/
chatify-frontendVue 3 frontend source coderesources/vendor/chatify/frontend/
chatify-langLanguage fileslang/vendor/chatify/

Custom models

Override any Chatify model by extending it and updating the config:

// app/Models/ChatConversation.php
namespace App\Models;

use Chatify\Models\Conversation;

class ChatConversation extends Conversation
{
    // Add custom methods, scopes, or relationships
}
// config/chatify.php
'models' => [
    'conversation' => App\Models\ChatConversation::class,
],

All Chatify internals resolve models through the config, so your custom class will be used everywhere.

Custom RecipientResolver

The RecipientResolver determines whether one user can message another. The default implementation blocks messaging when either user has blocked the other.

To customize, implement the Chatify\Contracts\RecipientResolver interface:

namespace App\Chat;

use Chatify\Contracts\RecipientResolver;
use Illuminate\Database\Eloquent\Model;

class CustomRecipientResolver implements RecipientResolver
{
    public function canMessage(Model $sender, Model $recipient): bool
    {
        if ($sender->getKey() === $recipient->getKey()) {
            return false;
        }

        // Add your own logic: subscription checks, role restrictions, etc.
        return $sender->hasActiveSubscription();
    }
}

Bind it in a service provider:

use App\Chat\CustomRecipientResolver;
use Chatify\Contracts\RecipientResolver;

$this->app->bind(RecipientResolver::class, CustomRecipientResolver::class);

Custom policies

Chatify registers policies for Conversation and Message models. To override them, define your own policies and register them in your AuthServiceProvider:

use App\Policies\CustomConversationPolicy;
use Chatify\Models\Conversation;
use Illuminate\Support\Facades\Gate;

Gate::policy(Conversation::class, CustomConversationPolicy::class);

ConversationPolicy methods

MethodParametersDescription
view$user, $conversationCan view the conversation
create$userCan create conversations (default: always true)
update$user, $conversationCan update conversation settings
updateGroup$user, $conversationCan edit group info (name, description, avatar)
addParticipants$user, $conversationCan add participants to a group
removeParticipant$user, $conversation, $targetUserIdCan remove a participant
manageParticipantRole$user, $conversationCan change participant roles
transferOwnership$user, $conversationCan transfer group ownership
leave$user, $conversationCan leave a group
delete$user, $conversationCan delete the conversation
hide$user, $conversationCan hide the conversation from inbox
clear$user, $conversationCan clear all messages (saved messages only)

MessagePolicy methods

MethodParametersDescription
view$user, $messageCan view the message
create$user, $messageCan create a message in the conversation
update$user, $messageCan edit the message (sender only)
delete$user, $messageCan delete the message (sender only)
hide$user, $messageCan hide the message for themselves

Custom actions

Chatify uses action classes for core operations. You can replace any action by binding your own implementation in the container:

use App\Chat\Actions\CustomSendMessage;
use Chatify\Actions\Messages\SendMessage;

$this->app->bind(SendMessage::class, CustomSendMessage::class);

Extending ChatifyMessenger

The ChatifyMessenger facade resolves to the Chatify\ChatifyMessenger class. You can extend it by binding a custom class:

$this->app->bind('ChatifyMessenger', function () {
    return new \App\Chat\ExtendedChatifyMessenger();
});

Rate limiters

Chatify registers two rate limiters in the service provider:

LimiterDefaultApplied to
chatify-messages60 requests/minute per userMessage send, typing, search, forward
chatify-uploads10 requests/minute per userAvatar upload, attachment upload, background upload, settings update

To customize, redefine them in your AppServiceProvider:

use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Support\Facades\RateLimiter;

RateLimiter::for('chatify-messages', function ($request) {
    return Limit::perMinute(120)->by($request->user()?->getKey() ?: $request->ip());
});

RateLimiter::for('chatify-uploads', function ($request) {
    return Limit::perMinute(20)->by($request->user()?->getKey() ?: $request->ip());
});

Custom middleware

API middleware

Set the API middleware stack via environment variable:

CHATIFY_API_MIDDLEWARE=web,auth,verified

Web middleware

Override the web route middleware in config:

'web' => [
    'middleware' => ['web', 'auth', 'verified'],
],

Route bindings

Chatify registers custom route model bindings for conversation and message that scope queries to the authenticated user's conversations. This means a user can never access a conversation or message they are not a participant of, regardless of policy.

If you need to customize this behavior, you can override the bindings in your RouteServiceProvider.

On this page