PHPackages                             dgtlss/routa - 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. [API Development](/categories/api)
4. /
5. dgtlss/routa

ActiveLibrary[API Development](/categories/api)

dgtlss/routa
============

Automatically generate resource route URLs on Laravel models using a trait.

1.0.0(7mo ago)319MITPHPPHP ^8.3CI passing

Since Oct 1Pushed 7mo agoCompare

[ Source](https://github.com/dgtlss/routa)[ Packagist](https://packagist.org/packages/dgtlss/routa)[ RSS](/packages/dgtlss-routa/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (1)Dependencies (3)Versions (2)Used By (0)

Routa
=====

[](#routa)

**Routa** makes working with Laravel resource routes easy by adding dynamic URL accessors to your Eloquent models. It supports standard resource URLs (`index`, `show`, `create`, `update` `edit`, `destroy`), collection operations, nested route parameters, signed URLs, Blade directives, Artisan generators, and JSON export for frontend consumption.

[![Latest Version on Packagist](https://camo.githubusercontent.com/2ef8b90498d2e1373fc1689cc372861a81421a87e27b12dbfa0d99ddeb7dc7ee/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6467746c73732f726f7574612e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/dgtlss/routa)[![Total Downloads](https://camo.githubusercontent.com/e5372260f4205ec01035c477f9c07378dcff9dc8443626e870ada555a9db5e98/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f6467746c73732f726f7574612e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/dgtlss/routa)[![GitHub Tests](https://camo.githubusercontent.com/2de77e715fa3804b6f47e27b46f7c0bbf75a511a12fb88315d185d3460f233ee/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f6467746c73732f726f7574612f72756e2d74657374732e796d6c3f6272616e63683d6d61696e266c6162656c3d7465737473267374796c653d666c61742d737175617265)](https://github.com/dgtlss/routa/actions)[![License](https://camo.githubusercontent.com/d0a264e59aefd7903980fbfd4e7335fd858b5303e0d9a143c32bc55454f8a773/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f6467746c73732f726f7574612e7376673f7374796c653d666c61742d737175617265)](https://github.com/dgtlss/routa/blob/main/LICENSE)[![Laravel](https://camo.githubusercontent.com/c102a71e96e65d5ad81e6a909b055ef18ee469764f309b16c80d9d0525cde3af/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c61726176656c2d313125323025374325323031322d7265643f7374796c653d666c61742d737175617265266c6f676f3d6c61726176656c)](https://laravel.com)

---

📦 Installation
--------------

[](#-installation)

### Step 1: Install via Composer

[](#step-1-install-via-composer)

```
composer require dgtlss/routa
```

### Step 2: Publish the Configuration (Optional but Recommended)

[](#step-2-publish-the-configuration-optional-but-recommended)

```
php artisan vendor:publish --tag=routa-config
```

This will create a `config/routa.php` file where you can customize Routa's behavior.

---

🚀 Quick Start
-------------

[](#-quick-start)

### 1. Add the Trait to Your Model

[](#1-add-the-trait-to-your-model)

Let's say you have a `Product` model with resource routes:

```
// app/Models/Product.php
namespace App\Models;

use Dgtlss\Routa\Traits\ResourceRoutes;
use Illuminate\Database\Eloquent\Model;

class Product extends Model
{
    use ResourceRoutes;

    protected $guarded = [];

    public static function getResourceRouteBase(): string
    {
        return 'products'; // This should match your route name
    }
}
```

### 2. Define Your Resource Routes

[](#2-define-your-resource-routes)

In your `routes/web.php` or `routes/api.php`:

```
use App\Http\Controllers\ProductController;
use Illuminate\Support\Facades\Route;

Route::resource('products', ProductController::class);
```

### 3. Use the Dynamic URLs

[](#3-use-the-dynamic-urls)

Now you can access all resource URLs directly from your model instances:

```
$product = Product::find(1);

// All available URLs
echo $product->index_url;      // https://your-app.com/products
echo $product->create_url;     // https://your-app.com/products/create
echo $product->show_url;       // https://your-app.com/products/1
echo $product->edit_url;       // https://your-app.com/products/1/edit
echo $product->update_url;     // https://your-app.com/products/1
echo $product->destroy_url;    // https://your-app.com/products/1
```

---

🧰 Features
----------

[](#-features)

### ✅ Standard Resource URLs

[](#-standard-resource-urls)

Routa automatically generates these URL accessors for your models:

AccessorDescriptionExample Usage`show_url`View a single resource`$product->show_url``edit_url`Edit form for a resource`$product->edit_url``update_url`Update a resource (PUT/PATCH)`$product->update_url``destroy_url`Delete a resource`$product->destroy_url``index_url`List all resources`$product->index_url``create_url`Create form for new resource`$product->create_url`### ✅ Collection Operations

[](#-collection-operations)

Work with multiple models and include route URLs for each item:

MethodDescriptionExample Usage`routeMap()`Get route maps for all models in collection`$products->routeMap()``withRoutes()`Append route URLs to each model`$products->withRoutes()``withRoutes()`Add routes to individual model`$product->withRoutes()``toArrayWithRoutes()`Get model array with routes included`$product->toArrayWithRoutes()`### ✅ Signed URLs

[](#-signed-urls)

Generate secure, signed URLs for public access or temporary links:

```
// Individual signed URLs
echo $product->signed_show_url;    // Signed version of show_url
echo $product->signed_edit_url;    // Signed version of edit_url
echo $product->signed_update_url;  // Signed version of update_url
echo $product->signed_destroy_url; // Signed version of destroy_url

// Get all signed URLs as an array
$signedRoutes = $product->signedRouteMap();
```

**Enable Signed URLs Globally:**Set `signed_urls => true` in your `config/routa.php` file, and all URLs will automatically be signed.

**Enable Signed URLs per Model:**

```
class Product extends Model
{
    use ResourceRoutes;

    protected static bool $useSignedUrls = true;
    // ... rest of the model
}
```

### ✅ Nested Route Parameters

[](#-nested-route-parameters)

Perfect for nested resources like `users/{user}/products/{product}`:

```
// In your routes file
Route::resource('users.products', ProductController::class);
```

```
// In your Product model
class Product extends Model
{
    use ResourceRoutes;

    protected static array $resourceRouteParams = [
        'user' => 'user_id', // 'user' is the route parameter, 'user_id' is the model attribute
    ];

    public static function getResourceRouteBase(): string
    {
        return 'users.products';
    }
}
```

Now when you access URLs, Routa automatically includes the user parameter:

```
$product = Product::find(1);
$product->user_id = 5; // The user this product belongs to

echo $product->show_url; // https://your-app.com/users/5/products/1
echo $product->edit_url; // https://your-app.com/users/5/products/1/edit
```

### ✅ Blade Directives

[](#-blade-directives)

Use routes directly in your Blade templates:

```

View Product
Edit Product

View Product

Delete
```

### ✅ Artisan Commands

[](#-artisan-commands)

#### Generate a Routa-Enabled Model

[](#generate-a-routa-enabled-model)

```
php artisan routa:model Product
```

This creates a new model file with the ResourceRoutes trait already set up:

```
// app/Models/Product.php
namespace App\Models;

use Dgtlss\Routa\Traits\ResourceRoutes;
use Illuminate\Database\Eloquent\Model;

class Product extends Model
{
    use ResourceRoutes;

    protected $guarded = [];

    public static function getResourceRouteBase(): string
    {
        return 'products';
    }
}
```

#### Export Routes as JSON

[](#export-routes-as-json)

Perfect for passing URLs to your frontend JavaScript:

```
# Basic export
php artisan routa:export "App\Models\Product" --id=1

# Pretty-printed JSON
php artisan routa:export "App\Models\Product" --id=1 --pretty
```

**Output:**

```
{
  "index": "https://your-app.com/products",
  "create": "https://your-app.com/products/create",
  "show": "https://your-app.com/products/1",
  "edit": "https://your-app.com/products/1/edit",
  "update": "https://your-app.com/products/1",
  "destroy": "https://your-app.com/products/1"
}
```

### ✅ Route Maps

[](#-route-maps)

Get all URLs as an array - perfect for admin panels or bulk operations:

```
$product = Product::find(1);

// Get all standard URLs
$routes = $product->routeMap();
/*
[
    'index' => 'https://your-app.com/products',
    'create' => 'https://your-app.com/products/create',
    'show' => 'https://your-app.com/products/1',
    'edit' => 'https://your-app.com/products/1/edit',
    'update' => 'https://your-app.com/products/1',
    'destroy' => 'https://your-app.com/products/1'
]
*/

// Get all signed URLs
$signedRoutes = $product->signedRouteMap();
/*
[
    'index' => null,
    'create' => null,
    'show' => 'https://your-app.com/products/1?signature=abc123...',
    'edit' => 'https://your-app.com/products/1/edit?signature=abc123...',
    'update' => 'https://your-app.com/products/1?signature=abc123...',
    'destroy' => 'https://your-app.com/products/1?signature=abc123...'
]
*/
```

### ✅ Collection Support

[](#-collection-support)

Work with multiple models and include route URLs for each item - perfect for API responses:

```
// Get all products with their route URLs
$products = Product::all();

// Option 1: Get array of route maps for each product
$routeMaps = $products->routeMap();
/*
[
    ['show' => 'https://your-app.com/products/1', 'edit' => 'https://your-app.com/products/1/edit', ...],
    ['show' => 'https://your-app.com/products/2', 'edit' => 'https://your-app.com/products/2/edit', ...],
    ['show' => 'https://your-app.com/products/3', 'edit' => 'https://your-app.com/products/3/edit', ...]
]
*/

// Option 2: Append routes to each model (Recommended for APIs)
$productsWithRoutes = $products->withRoutes();
/*
[
    {
        "id": 1,
        "name": "Product 1",
        "price": 29.99,
        "routes": {
            "index": "https://your-app.com/products",
            "create": "https://your-app.com/products/create",
            "show": "https://your-app.com/products/1",
            "edit": "https://your-app.com/products/1/edit",
            "update": "https://your-app.com/products/1",
            "destroy": "https://your-app.com/products/1"
        }
    },
    {
        "id": 2,
        "name": "Product 2",
        "price": 39.99,
        "routes": {
            "index": "https://your-app.com/products",
            "create": "https://your-app.com/products/create",
            "show": "https://your-app.com/products/2",
            "edit": "https://your-app.com/products/2/edit",
            "update": "https://your-app.com/products/2",
            "destroy": "https://your-app.com/products/2"
        }
    }
]
*/
```

**Individual Model Methods:**

```
$product = Product::find(1);

// Add routes to the model
$productWithRoutes = $product->withRoutes();
echo $productWithRoutes->routes['show']; // https://your-app.com/products/1

// Get model as array with routes included
$arrayWithRoutes = $product->toArrayWithRoutes();
// Returns: ['id' => 1, 'name' => 'Product', 'routes' => [...], ...]
```

---

⚙️ Configuration
----------------

[](#️-configuration)

Publish the config file to customize Routa's behavior:

```
php artisan vendor:publish --tag=routa-config
```

### `config/routa.php`

[](#configroutaphp)

```
return [
    /*
    |--------------------------------------------------------------------------
    | Route Prefix
    |--------------------------------------------------------------------------
    |
    | This value will be prepended to all route names unless overridden
    | on the model with `protected static $resourceRoutePrefix`.
    | Example: 'admin' would make routes like 'admin.products.show'
    |
    */

    'route_prefix' => null,

    /*
    |--------------------------------------------------------------------------
    | Verify Routes Exist
    |--------------------------------------------------------------------------
    |
    | If enabled, Routa will check if the named route exists using
    | Route::has(). If it doesn't exist, the URL will return null.
    | Set to false if you want to generate URLs even when routes don't exist.
    |
    */

    'verify_routes_exist' => true,

    /*
    |--------------------------------------------------------------------------
    | Fallback Prefix for Resource Route Base
    |--------------------------------------------------------------------------
    |
    | When a model doesn't define `$resourceRouteBase`, this prefix will
    | be used for auto-generated base route names like 'app.products'.
    |
    */

    'base_fallback_prefix' => 'app',

    /*
    |--------------------------------------------------------------------------
    | Use Signed URLs
    |--------------------------------------------------------------------------
    |
    | If true, Routa will generate signed URLs where applicable.
    | This can be overridden per model using $useSignedUrls property.
    |
    */

    'signed_urls' => false,
];
```

### Configuration Examples

[](#configuration-examples)

#### Admin Panel Routes

[](#admin-panel-routes)

```
// config/routa.php
return [
    'route_prefix' => 'admin',
];

// Your model
class Product extends Model
{
    use ResourceRoutes;

    // No need to specify prefix here, it will use the config
    public static function getResourceRouteBase(): string
    {
        return 'products';
    }
}

// Generated route names will be: admin.products.index, admin.products.show, etc.
```

#### API Routes

[](#api-routes)

```
// config/routa.php
return [
    'route_prefix' => 'api.v1',
];

// Generated route names will be: api.v1.products.index, api.v1.products.show, etc.
```

---

🧪 Testing
---------

[](#-testing)

### Test Helpers

[](#test-helpers)

Routa includes a helpful test assertion to verify all routes are working:

```
// tests/Feature/ProductTest.php
public function test_product_routes_are_valid()
{
    $product = Product::factory()->create();

    // This will assert that all URLs in routeMap() are valid and non-null
    $this->assertRoutaRoutesValid($product);
}
```

### Running Tests

[](#running-tests)

```
# Run Routa's test suite
composer test

# Or using Laravel's test runner
php artisan test
```

---

🧠 Advanced Usage
----------------

[](#-advanced-usage)

### API Controllers with Collection Routes

[](#api-controllers-with-collection-routes)

Perfect for building APIs that include route URLs for frontend consumption:

```
// app/Http/Controllers/ProductController.php
class ProductController extends Controller
{
    public function index()
    {
        $products = Product::all();

        // Return products with route URLs included
        return response()->json($products->withRoutes());
    }

    public function show(Product $product)
    {
        // Return single product with routes
        return response()->json($product->withRoutes());
    }
}
```

**API Response Example:**

```
{
    "data": [
        {
            "id": 1,
            "name": "Laptop",
            "price": 999.99,
            "routes": {
                "show": "https://api.yourapp.com/products/1",
                "edit": "https://api.yourapp.com/products/1/edit",
                "update": "https://api.yourapp.com/products/1",
                "destroy": "https://api.yourapp.com/products/1"
            }
        }
    ]
}
```

### Custom Route Bases

[](#custom-route-bases)

You can customize the route base per model:

```
class Product extends Model
{
    use ResourceRoutes;

    public static function getResourceRouteBase(): string
    {
        return 'catalog.items'; // Custom route base
    }
}

// This will generate routes like: catalog.items.index, catalog.items.show, etc.
```

### Model-Level Configuration

[](#model-level-configuration)

Override global settings per model:

```
class Product extends Model
{
    use ResourceRoutes;

    // Override global route prefix
    protected static string $resourceRoutePrefix = 'admin';

    // Override route verification
    protected static bool $verifyRoutesExist = false;

    // Enable signed URLs just for this model
    protected static bool $useSignedUrls = true;

    public static function getResourceRouteBase(): string
    {
        return 'products';
    }
}
```

### Multiple Nested Parameters

[](#multiple-nested-parameters)

Handle deeply nested routes:

```
// routes/web.php
Route::resource('companies.departments.teams', TeamController::class);

// app/Models/Team.php
class Team extends Model
{
    use ResourceRoutes;

    protected static array $resourceRouteParams = [
        'company' => 'company_id',
        'department' => 'department_id',
    ];

    public static function getResourceRouteBase(): string
    {
        return 'companies.departments.teams';
    }
}

// Usage
$team = Team::find(1);
$team->company_id = 5;
$team->department_id = 10;

echo $team->show_url; // /companies/5/departments/10/teams/1
```

---

🐛 Troubleshooting
-----------------

[](#-troubleshooting)

### URLs Return Null

[](#urls-return-null)

If your URLs are returning `null`, check:

1. **Route Names Match**: Ensure your route names match your `getResourceRouteBase()` return value
2. **Route Verification**: If `verify_routes_exist` is true, the route must exist
3. **Model Attributes**: For nested routes, ensure the required attributes (like `user_id`) are set

```
// Debug route names
$routeName = $product->getFullRouteName('show');
dd($routeName, Route::has($routeName));
```

### Route Names Don't Match

[](#route-names-dont-match)

Use Laravel's `route:list` command to see your actual route names:

```
php artisan route:list --name=product
```

### Nested Routes Not Working

[](#nested-routes-not-working)

Ensure you've defined the `$resourceRouteParams` correctly:

```
// Route: users/{user}/products/{product}
// Model needs:
protected static array $resourceRouteParams = [
    'user' => 'user_id', // route_parameter => model_attribute
];
```

---

🔮 Roadmap
---------

[](#-roadmap)

- `routa:test` generator for test scaffolding
- Multiple-model export: `php artisan routa:export-all`
- Optional middleware bindings (e.g. signed + throttled)
- Support for custom route parameters
- Integration with Laravel's route caching

---

🙌 Contributing
--------------

[](#-contributing)

Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.

### Development Setup

[](#development-setup)

```
# Clone the repository
git clone https://github.com/dgtlss/routa.git
cd routa

# Install dependencies
composer install

# Run tests
composer test
```

---

📄 License
---------

[](#-license)

The MIT License (MIT). Please see [License File](LICENSE) for more information.

---

🤝 Support
---------

[](#-support)

If you encounter any issues or have questions, please:

1. Check the [troubleshooting section](#-troubleshooting)
2. Search existing [GitHub Issues](https://github.com/dgtlss/routa/issues)
3. Create a new issue if needed

---

**Happy coding with Routa! 🚀**

###  Health Score

35

—

LowBetter than 80% of packages

Maintenance63

Regular maintenance activity

Popularity10

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity50

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% 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.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

229d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/f86c3be8ba6d2b7a1fce05177ef066b040564e52cc0415a50ff259906b62f133?d=identicon)[dgtlss](/maintainers/dgtlss)

---

Top Contributors

[![nlangerdevtbg](https://avatars.githubusercontent.com/u/169651551?v=4)](https://github.com/nlangerdevtbg "nlangerdevtbg (2 commits)")

---

Tags

dgtlsslaravellaravel-frameworklaravel-packagelaravel-routeslaravel11laravel12mvcphpphp8resource-routesresourcesrouta

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/dgtlss-routa/health.svg)

```
[![Health](https://phpackages.com/badges/dgtlss-routa/health.svg)](https://phpackages.com/packages/dgtlss-routa)
```

###  Alternatives

[mollie/laravel-mollie

Mollie API client wrapper for Laravel &amp; Mollie Connect provider for Laravel Socialite

3624.1M28](/packages/mollie-laravel-mollie)[mll-lab/laravel-graphiql

Easily integrate GraphiQL into your Laravel project

683.2M9](/packages/mll-lab-laravel-graphiql)[spatie/laravel-route-discovery

Auto register routes using PHP attributes

23645.0k2](/packages/spatie-laravel-route-discovery)[esign/laravel-conversions-api

A laravel wrapper package around the Facebook Conversions API

69145.4k](/packages/esign-laravel-conversions-api)[didww/didww-api-3-php-sdk

PHP SDK for DIDWW API 3

1218.2k](/packages/didww-didww-api-3-php-sdk)[surface/laravel-webfinger

A Laravel package to create an ActivityPub webfinger.

113.8k](/packages/surface-laravel-webfinger)

PHPackages © 2026

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