master

laravel/framework

Last updated at: 29/12/2023 09:22

HasUlids.php

TLDR

This file provides a trait called HasUlids which can be used to add ULID (Universally Unique Lexicographically Sortable Identifier) functionality to a model in Laravel's Eloquent ORM.

Methods

initializeHasUlids

This method is called to initialize the HasUlids trait. It sets the usesUniqueIds property of the model to true.

uniqueIds

This method returns an array of columns that should receive a unique identifier. By default, it returns an array containing the primary key column of the model.

newUniqueId

This method generates and returns a new ULID for the model. It uses Laravel's Str::ulid method to generate the ULID.

resolveRouteBindingQuery

This method is called when resolving a route binding for a model. It checks if the given value is a valid ULID for the specified field. If the value is not a valid ULID and the field is one of the unique identifier columns of the model, a ModelNotFoundException is thrown. This method overrides the default behavior of Eloquent's resolveRouteBindingQuery method.

getKeyType

This method returns the auto-incrementing key type for the model. If the primary key column is one of the unique identifier columns of the model, it returns 'string'. Otherwise, it returns the value of the keyType property of the model.

getIncrementing

This method returns a boolean value indicating whether the IDs are incrementing for the model. If the primary key column is one of the unique identifier columns of the model, it returns false. Otherwise, it returns the value of the incrementing property of the model.

<?php

namespace Illuminate\Database\Eloquent\Concerns;

use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Support\Str;

trait HasUlids
{
    /**
     * Initialize the trait.
     *
     * @return void
     */
    public function initializeHasUlids()
    {
        $this->usesUniqueIds = true;
    }

    /**
     * Get the columns that should receive a unique identifier.
     *
     * @return array
     */
    public function uniqueIds()
    {
        return [$this->getKeyName()];
    }

    /**
     * Generate a new ULID for the model.
     *
     * @return string
     */
    public function newUniqueId()
    {
        return strtolower((string) Str::ulid());
    }

    /**
     * Retrieve the model for a bound value.
     *
     * @param  \Illuminate\Database\Eloquent\Model|\Illuminate\Database\Eloquent\Relations\Relation  $query
     * @param  mixed  $value
     * @param  string|null  $field
     * @return \Illuminate\Database\Eloquent\Relations\Relation
     *
     * @throws \Illuminate\Database\Eloquent\ModelNotFoundException
     */
    public function resolveRouteBindingQuery($query, $value, $field = null)
    {
        if ($field && in_array($field, $this->uniqueIds()) && ! Str::isUlid($value)) {
            throw (new ModelNotFoundException)->setModel(get_class($this), $value);
        }

        if (! $field && in_array($this->getRouteKeyName(), $this->uniqueIds()) && ! Str::isUlid($value)) {
            throw (new ModelNotFoundException)->setModel(get_class($this), $value);
        }

        return parent::resolveRouteBindingQuery($query, $value, $field);
    }

    /**
     * Get the auto-incrementing key type.
     *
     * @return string
     */
    public function getKeyType()
    {
        if (in_array($this->getKeyName(), $this->uniqueIds())) {
            return 'string';
        }

        return $this->keyType;
    }

    /**
     * Get the value indicating whether the IDs are incrementing.
     *
     * @return bool
     */
    public function getIncrementing()
    {
        if (in_array($this->getKeyName(), $this->uniqueIds())) {
            return false;
        }

        return $this->incrementing;
    }
}