Model Urls

This functionality allows you to generate custom urls for your model records.
The generated url will be stored inside the urls database table.

Usage

Your models should use the Varbox\Traits\HasUrl trait and the Varbox\Options\UrlOptions class. The trait contains an abstract method getUrlOptions() that you must implement yourself.

Here's an example of how to implement the trait:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;
use Varbox\Options\UrlOptions;
use Varbox\Traits\HasUrl;

class YourModel extends Model
{
    use HasUrl;

    /**
     * The` attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'name',
        'slug',
    ];

    /**
     * Get the options for the HasUrl trait.
     *
     * @return UrlOptions
     */
    public function getUrlOptions(): UrlOptions
    {
        return UrlOptions::instance()
            ->routeUrlTo(YourController::class, 'yourShowMethod')
            ->generateUrlSlugFrom('name')
            ->saveUrlSlugTo('slug');
    }
}

The routeUrlTo() method is mandatory and it's used to specify to what controller and method to dispatch the request, when accessing the generated url in your browser.

The generateUrlSlugFrom() and saveUrlSlugTo() are mandatory and they're used by the underlying Varbox\Traits\HasSlug trait which is used by the Varbox\Traits\HasUrl trait.

For more information on how slugs work refer to the Model Slugs documentation section.


Next you should create the table column that you've specified for the saveUrlSlugTo() method.

Schema::table('your_table', function (Blueprint $table) {
    $table->string('slug')->nullable()->unique();
});

Generate Url

After you've done the above steps, generating a url for a model record will be done automatically when you'll be saving that model record. A new entry for the url will be stored inside the urls table.

$model = YourModel::create([
    'name' => 'Initial name'
]); // url is "initial-name"

$model->update([
    'name' => 'Modified name'
]); // url is "modified-name"

Fetch The Url

To get the full url of a model use the getUrl() method present on the trait.

$model = YourModel::find($id);

$model->getUrl();

To get only the relative url of a model use the getUri() method present on the trait.

$model = YourModel::find($id);

$model->getUri();

Disable Url Generation

By default, a url will be generated for your model record each time you create or update one.
To save the model without generating a url use the doGenerateUrl() method.

// url will not be generated
$model = YourModel::doNotGenerateUrl()->create([
    ...
]);

// url will not be generated here as well
$model->doNotGenerateUrl()->update([
    ...
]);

If you're doing multiple operations on the same model in the same request and at some point you want to generate a url for it, you can enable it back up by using the doGenerateUrl() method.

// url will not be generated
$model = YourModel::doNotGenerateUrl()->create([
    ...
]);

// url will be generated
$model->doGenerateUrl()->update([
    ...
]);

Customizations

The url functionality offers a variety of customizations to fit your needs.

Define Route Dispatch

You can specify to what controller and method to dispatch the request, when accessing the generated url in your browser, by using the routeUrlTo() method in your definition of the getUrlOptions() method.

/**
 * Get the options for the HasUrl trait.
 *
 * @return UrlOptions
 */
public function getUrlOptions(): UrlOptions
{
    return UrlOptions::instance()
        ->routeUrlTo(YourController::class, 'yourShowMethod')
}

Change Separator

By default the url is generated by concatenating the prefix, attribute and suffix using a slash /

You can change the url separator by using the glueUrlWith() method in your definition of the getUrlOptions() method.

/**
 * Get the options for the HasUrl trait.
 *
 * @return UrlOptions
 */
public function getUrlOptions(): UrlOptions
{
    return UrlOptions::instance()
        ->glueUrlWith('-');
}

Set Url Prefix

You can prefix the generated url with a value by using the prefixUrlWith() method in your definition of the getUrlOptions() method.

/**
 * Get the options for the HasUrl trait.
 *
 * @return UrlOptions
 */
public function getUrlOptions(): UrlOptions
{
    return UrlOptions::instance()
        ->prefixUrlWith(function ($prefix, $model) {
            foreach ($model->ancestors()->get() as $ancestor) {
                $prefix[] = $ancestor->slug;
            }

            return implode('/' , (array)$prefix);
        });
}

Set Url Suffix

You can suffix the generated url with a value by using the suffixUrlWith() method in your definition of the getUrlOptions() method.

/**
 * Get the options for the HasUrl trait.
 *
 * @return UrlOptions
 */
public function getUrlOptions(): UrlOptions
{
    return UrlOptions::instance()
        ->suffixUrlWith(function ($suffix, $model) {
            foreach ($model->descendants()->get() as $ancestor) {
                $suffix[] = $ancestor->slug;
            }

            return implode('/' , (array)$suffix);
        });
}

Disable Cascade Update

By default, when updating a model record's url that has children, it's underlying children's urls will also be updated to reflect the change.

You can disable this using the doNotUpdateCascading() method in your definition of the getUrlOptions() method.

/**
 * Get the options for the HasUrl trait.
 *
 * @return UrlOptions
 */
public function getUrlOptions(): UrlOptions
{
    return UrlOptions::instance()
        ->doNotUpdateCascading();
}

The Model

Up until this point you've learned how to use the functionality exposed by the HasUrl trait.
However, there's also a Varbox\Models\Url model that manages the urls.

Below you'll find some basic functionalities of the Varbox\Models\Url model, but you can always inspect the model yourself, or even extend it.

Get Original Model

You can get the original model using the urlable relation method.

use Varbox\Models\Url;

$url = Url::find($id);
$model = $url->urlable;

Get Accessed Url Model

To get your actual model instance when accessing its url in the browser, you might be tempted to use the urbale() method from the Varbox\Models\Url model. However, that won't be necessary because the route dispatcher already takes care of attaching the model instance.

To fetch your model instance when accessing its url use $request->route()->action['model'] directly from your controller method.

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class YourController extends Controller
{
    /**
     * @param Request $request
     * @return \Illuminate\View\View
     */
    public function show(Request $request)
    {
        $model = $request->route()->action['model'] ?? null;

        return view('your.view')->with([
            'model' => $model
        ]);
    }
}

Overwrite Bindings

In your projects, you may stumble upon the need to modify the behavior of these classes, in order to fit your needs. Varbox makes this possible via the config/varbox/bindings.php configuration file. In that file, you'll find every customizable class the platform uses.

For more information on how the class binding works, please refer to the Custom Bindings documentation section.

Varbox\Models\Url

Found in config/varbox/bindings.php at models.url_model key.
This class represents the url model.

Implementation Example

For an implementation example of this functionality please refer to the Full Example page.