This Laravel application includes a secure private messaging system that allows users to send direct messages to each other.
- Private Messaging: Users can send and receive private messages to/from other users
- Message Encryption: All messages are encrypted in the database using Laravel's encryption
- Read Receipts: Track when messages have been read
- Real-time Conversations: View message history between users
- Security: Authorization policies ensure users can only view their own messages
- RESTful API: Complete API endpoints for messaging operations
| Column | Type | Description |
|---|---|---|
| id | bigint | Primary key |
| sender_id | bigint | Foreign key to users table |
| recipient_id | bigint | Foreign key to users table |
| body | text | Encrypted message content |
| read_at | timestamp | When message was read (nullable) |
| created_at | timestamp | When message was created |
| updated_at | timestamp | When message was updated |
All endpoints require authentication via Laravel Sanctum.
GET /api/messages
Returns list of all conversations for the authenticated user.
Response:
[
{
"user": {
"id": 2,
"name": "John Doe",
"email": "john@example.com"
},
"last_message": {
"id": 5,
"body": "Hello!",
"created_at": "2026-02-14T12:00:00.000000Z"
},
"unread_count": 3
}
]GET /api/messages/{userId}
Returns all messages between authenticated user and specified user.
Response:
{
"messages": [
{
"id": 1,
"sender_id": 1,
"recipient_id": 2,
"body": "Hello!",
"read_at": null,
"created_at": "2026-02-14T12:00:00.000000Z"
}
],
"user": {
"id": 2,
"name": "John Doe"
}
}POST /api/messages
Request Body:
{
"recipient_id": 2,
"body": "Hello, this is my message"
}Response:
{
"message": {
"id": 1,
"sender_id": 1,
"recipient_id": 2,
"body": "Hello, this is my message",
"created_at": "2026-02-14T12:00:00.000000Z"
},
"success": true
}PATCH /api/messages/{messageId}/read
Response:
{
"success": true,
"message": {
"id": 1,
"read_at": "2026-02-14T12:05:00.000000Z"
}
}DELETE /api/messages/{messageId}
Response:
{
"success": true,
"message": "Message deleted successfully"
}GET /api/messages/users
Returns list of all users except the authenticated user.
GET /api/messages/unread-count
Returns count of unread messages for authenticated user.
Response:
{
"count": 5
}GET /messages
View all conversations with unread counts and last messages.
GET /messages/{userId}
View and send messages to a specific user.
- Encryption: All message bodies are encrypted using Laravel's
Cryptfacade before storage - Authorization: MessagePolicy ensures users can only:
- View messages they sent or received
- Update/delete their own sent messages
- Delete messages they received
- Authentication: All routes require authentication via Sanctum
- Validation:
- Users cannot send messages to themselves
- Recipients must exist in the database
- Message body is required and limited to 5000 characters
// Send a message
const response = await fetch('/api/messages', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content
},
body: JSON.stringify({
recipient_id: 2,
body: 'Hello!'
})
});
const data = await response.json();use App\Models\Message;
use App\Models\User;
use Illuminate\Support\Facades\Crypt;
// Create a message
$recipient = User::find(2);
$message = Message::create([
'sender_id' => auth()->id(),
'recipient_id' => $recipient->id,
'body' => Crypt::encryptString('Hello, this is my message'),
]);
// Get messages between two users
$messages = Message::between(auth()->id(), $recipient->id)
->orderBy('created_at', 'asc')
->get();
// Mark as read
$message->markAsRead();
// Get unread messages
$unreadMessages = auth()->user()
->receivedMessages()
->unread()
->get();Relationships:
sender()- BelongsTo Userrecipient()- BelongsTo User
Methods:
markAsRead()- Mark message as readisRead()- Check if message has been read
Scopes:
between($userId1, $userId2)- Get messages between two usersunread()- Get only unread messages
New Relationships:
sentMessages()- HasMany Message (as sender)receivedMessages()- HasMany Message (as recipient)
Run the test suite:
php artisan test --filter=MessageTests include:
- Message creation and encryption
- Read receipts
- Message relationships
- API endpoints
- Authorization policies
- Validation rules
Run the migration to create the messages table:
php artisan migratePotential improvements for the messaging system:
- Real-time Updates: Integration with Laravel Echo and WebSockets for live messages
- Typing Indicators: Show when the other user is typing
- Message Attachments: Support for file uploads
- Group Messaging: Extend to support group conversations
- Message Search: Full-text search capabilities
- Notifications: Email/push notifications for new messages
- Message Reactions: Emoji reactions to messages
- Message Editing: Allow users to edit sent messages
- Message Deletion: Soft delete with retention period
- Blocked Users: Prevent messages from blocked users