PHPackages                             dnj/laravel-ticketing - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. dnj/laravel-ticketing

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

dnj/laravel-ticketing
=====================

Package used for the ticketing system.

102PHP

Since Jan 27Pushed 3y ago1 watchersCompare

[ Source](https://github.com/dnj/laravel-ticketing)[ Packagist](https://packagist.org/packages/dnj/laravel-ticketing)[ RSS](/packages/dnj-laravel-ticketing/feed)WikiDiscussions master Synced 1mo ago

READMEChangelogDependenciesVersions (1)Used By (0)

Laravel Ticketing
=================

[](#laravel-ticketing)

[![Latest Version on Packagist](https://camo.githubusercontent.com/7adf2876feff3077106491dfcb78d362ea1781e5cec801f9c2ed6f60d7cdec41/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f646e6a2f6c61726176656c2d7469636b6574696e672e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/dnj/laravel-ticketing)[![Total Downloads](https://camo.githubusercontent.com/f008a6a23db1b7d990116e80e756d4732e9f61a28f759aa024cbd34c6d24f041/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f646e6a2f6c61726176656c2d7469636b6574696e672e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/dnj/laravel-ticketing)[![Software License](https://camo.githubusercontent.com/55c0218c8f8009f06ad4ddae837ddd05301481fcf0dff8e0ed9dadda8780713e/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d627269676874677265656e2e7376673f7374796c653d666c61742d737175617265)](https://github.com/dnj/laravel-ticketing/blob/master/LICENSE)[![Testing status](https://github.com/dnj/laravel-ticketing/actions/workflows/ci.yml/badge.svg)](https://github.com/dnj/laravel-ticketing/actions/workflows/ci.yml)

Introduction
------------

[](#introduction)

This package will help you for manage tickets and support your clients.

- Features include:
    - Department Management
    - Ticket Management
    - Ticket Messages Management
    - Ticket Attachments Management
- Latest versions of PHP and PHPUnit and PHPCsFixer
- Best practices applied:
    - [`README.md`](https://github.com/dnj/laravel-ticketing/blob/master/README.md) (badges included)
    - [`LICENSE`](https://github.com/dnj/laravel-ticketing/blob/master/LICENSE)
    - [`composer.json`](https://github.com/dnj/laravel-ticketing/blob/master/composer.json)
    - [`phpunit.xml`](https://github.com/dnj/laravel-ticketing/blob/master/phpunit.xml)
    - [`.gitignore`](https://github.com/dnj/laravel-ticketing/blob/master/.gitignore)
    - [`.php-cs-fixer.php`](https://github.com/dnj/laravel-ticketing/blob/master/.php-cs-fixer.php)

Installation
------------

[](#installation)

Require this package with composer.

```
composer require dnj/laravel-ticketing
```

Laravel uses Package Auto-Discovery, so doesn't require you to manually add the ServiceProvider.

#### Copy the package config to your local config with the publish command:

[](#copy-the-package-config-to-your-local-config-with-the-publish-command)

```
php artisan vendor:publish --provider="dnj\Ticket\TicketServiceProvider"
```

#### Config file

[](#config-file)

```
use dnj\Filesystem\Local\Directory;

return [
    // If set True we will migrate and validate title field for ticket.
    'title' => true,

    // Define your user model class for connect tickets to users. | example: App\User:class
    'user_model' => null,

    /**
     * By default, the dnj/local-filesystem package is used to store files.
     * According to the Directory class, you can specify the main path for storing file
     */
    'attachment_root' => new Directory(public_path('ticket')),

    /**
     * Specifies the number of folders to create for storage based on the file hash
     * If the hash of your file is 8c7dd922ad47494fc02c388e12c00eac and dir_layer_number is 2,
     * the file is saved with this structure :  [path]/8c/7d/8c7dd922ad47494fc02c388e12c00eac.jpg
     */
    'dir_layer_number' => 2,

    /**
     * You can set the validations you want to store files from here.
     */
    'attachment_rules' => [
        'mimes:jpg,png,txt', 'mimetypes:text/plain,image/jpeg,image/png', 'max:1024',
  ]
];
```

---

ℹ️ **Note**

> User activity logs are disabled by default, if you want to save them set `$userActivityLog` to true.

Example :

```
use dnj\Ticket\Contracts\IDepartmentManager;

$departmentManager = app(IDepartmentManager::class);
$department = $departmentManager->store(
  title:'Sell Department',
  userActivityLog: true
); // returns an Department model which implementes IDepartment
```

Working With Departments:
-------------------------

[](#working-with-departments)

Search departments:

```
use dnj\Ticket\Contracts\IDepartmentManager;
use dnj\Ticket\Contracts\IDepartment;

$departmentManager = app(IDepartmentManager::class);

 /**
 * @param array{title?:string,created_start_date?:string,created_end_date?:string,updated_start_date?:string,updated_end_date?:string}|null $filters
 * @var iterable $departments
 */
$departments = $departmentManager->search(
  filters:['title' => 'sales']
);
```

Create new department:

```
use dnj\Ticket\Contracts\IDepartmentManager;

$departmentManager = app(IDepartmentManager::class);

 /**
 * @param string $title
 * @param bool $userActivityLog = false
 * @return IDepartment
 */

$department = $departmentManager->store(title:'Sell Department');
```

Show department:

```
use dnj\Ticket\Contracts\IDepartmentManager;

$departmentManager = app(IDepartmentManager::class);

/**
 * @param  int $id
 * @return IDepartment
 */
$department = $departmentManager->find(id:1);
```

Update department:

```
use dnj\Ticket\Contracts\IDepartmentManager;

$departmentManager = app(IDepartmentManager::class);

/**
 * @param int $id
 * @param array{title?:string} $changes
 * @param bool $userActivityLog = false
 * @return IDepartment
 */
$department = $departmentManager->update(
  id:1,
  changes: ['title' => 'Support']
);
```

Delete department:

```
use dnj\Ticket\Contracts\IDepartmentManager;

$departmentManager = app(IDepartmentManager::class);

/**
 * @param int $id
 * @param bool $userActivityLog = false
 * @return void
 */
$departmentManager->destroy(
  id:1,
  userActivityLog: false, // Prevent saving a log for authenticated user
);
```

---

Working With Tickets:
---------------------

[](#working-with-tickets)

Search tickets:

```
use dnj\Ticket\Contracts\ITicketManager;
use dnj\Ticket\Contracts\ITicket;
use dnj\Ticket\Enums\TicketStatus;

$ticketManager = app(ITicketManager::class);

/**
 * @param array{title?:string,client_id?:int,department_id?:int,status?:TicketStatus[],created_start_date?:DateTimeInterface,created_end_date?:DateTimeInterface,updated_start_date?:DateTimeInterface,updated_end_date?:DateTimeInterface}|null $filters
 * @param bool $userActivityLog = false
 * @return iterable
 */

$tickets = $ticketManager->search(
  filters: [
    'client_id' => 1,
    'status' => [TicketStatus::UNREAD, TicketStatus::IN_PROGRESS],
  ]
);
```

Create new ticket:

```
use dnj\Ticket\Managers\TicketManager;

$ticketManager = app(ITicketManager::class);

/**
 * @param int $clientId
 * @param int $departmentId
 * @param string $message
 * @param array $files
 * @param string|null $title = null
 * @param int|null $userId = null
 * @param dnj\Ticket\Enums\TicketStatus|null $status = null
 * @param bool $userActivityLog = false
 * @throws ITicketTitleHasBeenDisabledException if $title is set but title is disabled
 * @return IMessage
 */
$message = $ticketManager->store(
    clientId: 1,
    departmentId: 1,
    message:'First message for ticket',
    files:[],
    title:'Ticket subject',
    userId: auth()->user()->id,
    status: null
  );
```

Show ticket:

```
use dnj\Ticket\Managers\TicketManager;

$ticketManager = app(ITicketManager::class);

/**
 * @param int id
 * @return ITicket
 */
$ticket = $ticket->find(id:1);
```

Update ticket :

```
use dnj\Ticket\Managers\TicketManager;

$ticketManager = app(ITicketManager::class);

/**
 * @param int $id
 * @param array{title?:string,client_id?:int,department_id?:int,status?:TicketStatus} $changes
 * @param bool $userActivityLog = false
 * @return ITicket
 */
$ticket = $ticket->update(
  id: 1,
  changes: ['client_id' => 3],
  userActivityLog: true
);
```

Delete ticket :

```
use dnj\Ticket\Managers\TicketManager;

$ticketManager = app(ITicketManager::class);

/**
 * @param int $id
 * @param bool $userActivityLog = false
 * @return void
 */
$ticket->destroy(id:1);
```

---

Working With Ticket Messages:
-----------------------------

[](#working-with-ticket-messages)

Search ticket messages :

```
use dnj\Ticket\Contracts\IMessageManager;
use dnj\Ticket\Contracts\IMessage;

$messageManager = app(IMessageManager::class);

/**
 * @param int $ticketId
 * @param array{user_id?:int,sort?:string,created_start_date?:DateTimeInterface,created_end_date?:DateTimeInterface,updated_start_date?:DateTimeInterface,updated_end_date?:DateTimeInterface}|null $filters
* @return iterable
*/

$ticketMessages = $messageManager->search(
  ticketId:5,
  filters:[
    'user_id' => 1,
  ]
);
```

Create new ticket message :

---

```
use dnj\Ticket\Contracts\IMessageManager;
use dnj\Ticket\Contracts\IMessage;
use dnj\Ticket\Enums\TicketStatus;

$messageManager = app(IMessageManager::class);

/**
 * @param int $ticketId
 * @param string $message
 * @param array $files
 * @param int|null $userId = null
 * @param bool $userActivityLog = false
 * @return IMessage
 */
$ticketMessage = $messageManager->store(
    ticketId: 1,
    message: 'Second message for ticket',
    files: [113],
    userId: auth()->user()->id
  );
```

Show ticket message:

---

```
use dnj\Ticket\Contracts\IMessageManager;
use dnj\Ticket\Contracts\IMessage;

$messageManager = app(IMessageManager::class);

/**
 * @param int id
 * @return IMessage
 */
$ticketMessage = $messageManager->find(id:4);
```

Update ticket message:

---

```
use dnj\Ticket\Contracts\IMessageManager;
use dnj\Ticket\Contracts\IMessage;

$messageManager = app(IMessageManager::class);

/**
 * @param int $id
 * @param array{message?:string,userId?:int} $changes
 * @param bool $userActivityLog = false
 * @return IMessage
 */
$ticketMessage = $messageManager->update(
  id:1,
  changes: ['message'=>'Ticket message has updated']
);
```

Delete ticket message:

```
use dnj\Ticket\Contracts\IMessageManager;

$messageManager = app(IMessageManager::class);

/**
 * @param int $id
 * @param bool $userActivityLog = false
 * @return void
 */
$messageManager->destroy(id:1);
```

---

Ticket Attachment basic usage:
------------------------------

[](#ticket-attachment-basic-usage)

Search ticket attachment :

---

```
use dnj\Ticket\Contracts\IAttachmentManager;
use dnj\Ticket\Contracts\IAttachment;

$attachmentManager = app(IAttachmentManager::class);

/**
* @param int $messageId
* @return iterable
*/

$ticketAttachment = $attachmentManager->search(messageId:5);
```

Create new ticket attachment:

```
use dnj\Ticket\Contracts\IAttachmentManager;
use dnj\Ticket\Contracts\IAttachment;
use Illuminate\Http\UploadedFile;

$attachmentManager = app(IAttachmentManager::class);

/**
 * @param UploadedFile $file
 * @param int $messageId
 * @param bool $userActivityLog = false
 * @return IAttachment
 */
$attachment = $attachmentManager->storeByUpload(
  file: UploadedFile::fake()->image('avatar.jpg'),
  messageId: 2,
);
```

Show the attachment model using it's ID:

```
use dnj\Ticket\Contracts\IAttachmentManager;
use dnj\Ticket\Contracts\IAttachment;

$attachmentManager = app(IAttachmentManager::class);

/**
 * @param int $id
 * @return IAttachment
 */
$attachment = $attachmentManager->find(id:4);
```

Find orphan attachments:

This method helps you find stray files that are not attached to a message

```
use dnj\Ticket\Contracts\IAttachmentManager;
use dnj\Ticket\Contracts\IAttachment;

$attachmentManager = app(IAttachmentManager::class);

/**
 * @param int id
 * @return iterable
 */
$orphans = $attachmentManager->findOrphans();
```

Update attachment:

```
use dnj\Ticket\Contracts\IAttachment;
use dnj\Ticket\Contracts\IAttachmentManager;

$attachmentManager = app(IAttachmentManager::class);

/**
 * @param int $id
 * @param array{message_id?:int} $changes
 * @param bool $userActivityLog = false
 * @throws dnj\Ticket\Contracts\Exceptions\IAttachmentAlreadyAsignedException if you double assign a attachment
 * @return IAttachment
 */
$attachment = $attachmentManager->update(
  id:1,
  changes: [message_id => 5]
);
```

Delete ticket attachment:

```
use dnj\Ticket\Contracts\IAttachmentManager;

$attachmentManager = app(IAttachmentManager::class);

/**
 * @param int $id
 * @param bool $userActivityLog = false
 * @return void
 */
$attachmentManager->destroy(id:1);
```

HOWTO use Restful API
---------------------

[](#howto-use-restful-api)

A document in YAML format has been prepared for better familiarization and use of package web services. which is placed in the [`docs`](https://github.com/dnj/laravel-ticketing/blob/master/docs/openapi.yaml) folder.

To use this file, you can import it on the [stoplight.io](https://stoplight.io) site and see all available web services.

Contribution
------------

[](#contribution)

Contributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are greatly appreciated.

If you have a suggestion that would make this better, please fork the repo and create a pull request. You can also simply open an issue with the tag "enhancement". Don't forget to give the project a star! Thanks again!

1. Fork the Project
2. Create your Feature Branch (`git checkout -b feature/AmazingFeature`)
3. Commit your Changes (`git commit -m 'Add some AmazingFeature'`)
4. Push to the Branch (`git push origin feature/AmazingFeature`)
5. Open a Pull Request

Security
--------

[](#security)

If you discover any security-related issues, please email  instead of using the issue tracker.

License
-------

[](#license)

The MIT License (MIT). Please see [License File](https://github.com/dnj/laravel-ticketing/blob/master/LICENSE) for more information.

###  Health Score

14

—

LowBetter than 2% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity3

Limited adoption so far

Community11

Small or concentrated contributor base

Maturity23

Early-stage or recently created project

 Bus Factor1

Top contributor holds 69.8% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

### Community

Maintainers

![](https://www.gravatar.com/avatar/73cf0aeb62f80ed9937e3a39a8dfda10b94c36cc7028e9f0a95e04eb8a346db4?d=identicon)[dnj](/maintainers/dnj)

---

Top Contributors

[![mohaphez](https://avatars.githubusercontent.com/u/20874565?v=4)](https://github.com/mohaphez "mohaphez (44 commits)")[![yeganemehr](https://avatars.githubusercontent.com/u/16887332?v=4)](https://github.com/yeganemehr "yeganemehr (19 commits)")

---

Tags

laravelphpticket

### Embed Badge

![Health badge](/badges/dnj-laravel-ticketing/health.svg)

```
[![Health](https://phpackages.com/badges/dnj-laravel-ticketing/health.svg)](https://phpackages.com/packages/dnj-laravel-ticketing)
```

###  Alternatives

[psalm/plugin-laravel

Psalm plugin for Laravel

3274.9M308](/packages/psalm-plugin-laravel)[carlson/nova-link-field

A Laravel Nova field for HTML links.

22426.3k](/packages/carlson-nova-link-field)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
