Skip to content

IDs, Tags, and Slugs

Each item recorded in an excavation usually has a unique tag. These tags are not the best choice for an SQL table's unique id as they may be composites of strings and numbers. Accordingly, the software utilizes 3 id related representation:

  • id: a unique string stored in the database and used as a primary id.
  • tag: a string corrosponding to the excavation's field registration tag given to an artifact
  • slug: a unique string used to identify an item as part of a URL. (avoiding reserved chacters, white spaces, etc.)

For example, in the Jezreel-Expedition, a ceramics instance may have the following:

  • tag: 16/S/56AR5.1
  • slug: 16.S.56.AR.5.1
  • id: 6S056AR0501

functions to convert between the different representations are a required part of the module's definitions. Please note that with reasonable id selections referencial integrity is guranteed by the MySql engine.

The software ensures the integrity of the record by requiring each module to define the id structure as a function of the registration columns and validates it before create and update operations:

php
namespace App\Models\Module\Specific\Ceramic;

class Ceramic extends DigModuleModel
{
    // other stuff
   protected function derivedId(): Attribute
    {
        return Attribute::make(
            get: fn(mixed $value, array $attributes) => $attributes['locus_id'] . $attributes['code'] .  str_pad($attributes['basket_no'], 2, '0', STR_PAD_LEFT) .  str_pad($attributes['artifact_no'], 2, '0', STR_PAD_LEFT)
        );
    }
}

////////////

namespace App\Services\App;

class MutateService extends DigModuleService
{
    // other stuff
    protected function save(array $fields): array
    {
        //copy the validated data from the validated array to the 'item' object.

        if ($this->model->derivedId !== $this->model->id) {
            throw new GeneralJsonException('Unable to save d/t inconsistency between id: "' . $this->model->id . '" and derived id: ' . $this->model->derivedId, 422);
        }
    }
}

In the case of composite ids, their components are usually called for in filtering and ordering. For query simplicity, those are also defined by the module:

php
namespace App\Models\Module\Specific\Ceramic;

class Ceramic extends DigModuleModel
{
    // other stuff
    static public function discreteFilterOptions(): array
    {
        return [
            'Season' => [
                'field' => 'locus_id',
                'start' => 1,
                'length' => 1
            ],
            'Area' => [
                'field' => 'locus_id',
                'start' => 2,
                'length' => 1
            ],
            'Registration Code' => 'code',
            'Primary Classification' => 'ceramic_primary_classification_id',
            'Locus Id' => 'locus_id' // This one is required by create to avoid duplicate ids.
            // and is not a part of the tag/filter system.
        ];
    }

    static public function orderByOptions(): array
    {
        return [
            'Season' => [
                'field' => 'locus_id',
                'start' => 1,
                'length' => 1
            ],
            'Area' => [
                'field' => 'locus_id',
                'start' => 2,
                'length' => 1
            ],
            'Locus No.' =>            [
                'field' => 'locus_id',
                'start' => 3,
                'length' => 3
            ],
            'Registration Code' => 'code',
            'Basket No.' => 'basket_no',
            'Artifact No.' => 'artifact_no',

        ];
    }
}