Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.mejik.web.id/llms.txt

Use this file to discover all available pages before exploring further.

This is an excellent architectural choice that balances the flexibility of MongoDB with the structural benefits of normalization. Using assetTag as the relationship key is a common pattern for linking documents when a human-readable identifier is preferred over MongoDB’s ObjectId. Here is a complete example of the Laravel Eloquent models for this system, using the jenssegers/laravel-mongodb package.

Prerequisites

  1. Install the MongoDB Eloquent Package:
composer require jenssegers/mongodb
  1. Configure config/database.php: Add a new connection for MongoDB.
// config/database.php

'connections' => [
    // ... other connections

    'mongodb' => [
        'driver'   => 'mongodb',
        'host'     => env('DB_HOST', '127.0.0.1'),
        'port'     => env('DB_PORT', 27017),
        'database' => env('DB_DATABASE', 'homestead'),
        'username' => env('DB_USERNAME', 'homestead'),
        'password' => env('DB_PASSWORD', 'secret'),
        'options'  => [
            'database' => 'admin' // required with Mongo 3+
        ]
    ],
],

1. Base and Lookup Models

These are foundational models that other entities will reference.

App\Models\User

This is the standard User model, but it needs to extend the MongoDB model.
// app/Models/User.php
namespace App\Models;

use Illuminate\Foundation\Auth\User as Authenticatable;
use Jenssegers\Mongodb\Eloquent\Model; // Use this if not using authentication traits
// Or for a full auth user:
// use Jenssegers\Mongodb\Auth\User as Authenticatable;

class User extends Model // or Authenticatable
{
    protected $connection = 'mongodb';
    protected $collection = 'users';

    protected $fillable = [
        'name',
        'email',
        'password',
    ];
}

App\Models\Status

A simple lookup collection for asset statuses.
// app/Models/Status.php
namespace App\Models;

use Jenssegers\Mongodb\Eloquent\Model;

class Status extends Model
{
    protected $connection = 'mongodb';
    protected $collection = 'statuses';

    protected $fillable = ['name']; // e.g., 'In Use', 'In Storage'
}

2. Normalized Sub-Entity Models

These models contain data related to an asset and are linked via assetTag.

App\Models\Asset\Location

// app/Models/Asset/Location.php
namespace App\Models\Asset;

use Jenssegers\Mongodb\Eloquent\Model;

class Location extends Model
{
    protected $connection = 'mongodb';
    protected $collection = 'asset_locations';

    protected $fillable = [
        'assetTag',
        'building',
        'floor',
        'room',
        'description',
    ];

    // Note: Defining the inverse relationship is complex because a location
    // doesn't know if its assetTag belongs to 'assets' or 'itAssets' collection.
    // It's often omitted, as queries typically start from the asset itself.
}

App\Models\Asset\PurchaseInfo

// app/Models/Asset/PurchaseInfo.php
namespace App\Models\Asset;

use Jenssegers\Mongodb\Eloquent\Model;

class PurchaseInfo extends Model
{
    protected $connection = 'mongodb';
    protected $collection = 'asset_purchase_info';

    protected $fillable = [
        'assetTag',
        'purchaseDate',
        'vendor',
        'cost',
        'warrantyExpiryDate',
    ];

    protected $casts = [
        'purchaseDate' => 'datetime',
        'warrantyExpiryDate' => 'datetime',
        'cost' => 'float',
    ];
}

App\Models\Asset\Assignment

// app/Models/Asset/Assignment.php
namespace App\Models\Asset;

use App\Models\User;
use Jenssegers\Mongodb\Eloquent\Model;

class Assignment extends Model
{
    protected $connection = 'mongodb';
    protected $collection = 'asset_assignments';

    protected $fillable = [
        'assetTag',
        'userId',
        'assignmentDate',
    ];

    protected $casts = [
        'assignmentDate' => 'datetime',
    ];

    /**
     * Get the user this asset is assigned to.
     */
    public function user()
    {
        return $this->belongsTo(User::class, 'userId');
    }
}

3. Abstract Base Asset Model

To avoid repeating the relationship definitions in every asset model, we create an abstract base class.
// app/Models/Asset/BaseAsset.php
namespace App\Models\Asset;

use App\Models\Status;
use Jenssegers\Mongodb\Eloquent\Model;

abstract class BaseAsset extends Model
{
    protected $connection = 'mongodb';

    /**
     * Defines the relationship from an Asset to its Location.
     * Foreign Key: 'assetTag' on the 'asset_locations' collection.
     * Local Key: 'assetTag' on this model's collection.
     */
    public function location()
    {
        return $this->hasOne(Location::class, 'assetTag', 'assetTag');
    }

    /**
     * Defines the relationship to its PurchaseInfo.
     */
    public function purchaseInfo()
    {
        return $this->hasOne(PurchaseInfo::class, 'assetTag', 'assetTag');
    }

    /**
     * Defines the relationship to its Assignment.
     */
    public function assignment()
    {
        return $this->hasOne(Assignment::class, 'assetTag', 'assetTag');
    }

    /**
     * Get the status of the asset.
     * This uses a standard ObjectId relationship.
     */
    public function status()
    {
        return $this->belongsTo(Status::class, 'statusId');
    }
}

4. Concrete Asset Models

These are the models you will interact with directly. They extend BaseAsset to inherit the common relationships.

General Asset: App\Models\Asset\GeneralAsset

// app/Models/Asset/GeneralAsset.php
namespace App\Models\Asset;

class GeneralAsset extends BaseAsset
{
    protected $collection = 'general_assets';

    protected $fillable = [
        'assetTag',
        'name',
        'manufacturer',
        'statusId', // Foreign key to the 'statuses' collection
        'category', // e.g., VEHICLE, MACHINERY
        'specifications',
    ];

    protected $casts = [
        // Cast the flexible specifications field to an array/object
        'specifications' => 'array',
    ];
}

Specific IT Asset: App\Models\Asset\ItAsset

// app/Models/Asset/ItAsset.php
namespace App\Models\Asset;

class ItAsset extends BaseAsset
{
    protected $collection = 'it_assets';

    protected $fillable = [
        // Base Fields
        'assetTag',
        'name',
        'manufacturer',
        'statusId',

        // IT Specific Fields
        'hostname',
        'macAddress',
        'ipAddress',
        'os',
        'cpu',
        'ramGb',
        'storageGb',
    ];

    protected $casts = [
        'ramGb' => 'integer',
        'storageGb' => 'integer',
    ];
}

Usage Example

Here’s how you would use these models in your controller or service.
use App\Models\Asset\GeneralAsset;
use App\Models\Asset\ItAsset;

// --- Creating a new IT Asset and its related data ---
$itAsset = ItAsset::create([
    'assetTag' => 'IT-LPT-01124',
    'name' => 'Dell Latitude 7420',
    'manufacturer' => 'Dell',
    'statusId' => '638d1d8f5d1e4e3f8b0e7b45', // ObjectId of the 'In Use' status
    'hostname' => 'LPT-JSMITH-PROD',
    'macAddress' => '9C:B6:D0:FF:1A:3E',
    'ramGb' => 16,
]);

$itAsset->location()->create([
    'building' => 'Building A',
    'floor' => '4',
    'description' => 'Desk 4-15'
]);

$itAsset->purchaseInfo()->create([
    'purchaseDate' => now()->subYear(),
    'vendor' => 'Dell Corporate Sales',
    'cost' => 1850.50,
]);

// --- Retrieving an asset with its relations (Eager Loading) ---
$assetTag = 'IT-LPT-01124';
$retrievedAsset = ItAsset::with(['location', 'purchaseInfo', 'assignment.user', 'status'])
                         ->where('assetTag', $assetTag)
                         ->first();

// You can now access related data as properties:
echo $retrievedAsset->name; // "Dell Latitude 7420"
echo $retrievedAsset->location->building; // "Building A"
echo $retrievedAsset->status->name; // "In Use"
if ($retrievedAsset->assignment) {
    echo $retrievedAsset->assignment->user->name;
}