wooserv/php-objectid
Generate and work with MongoDB-style ObjectId values in PHP. Create new ObjectIds, parse and validate existing ones, convert to hex strings, and access parts like timestamp for sorting or debugging. Lightweight utility with no database required.
Installation
composer require wooserv/php-objectid
Add to composer.json if not using autoloading:
"autoload": {
"psr-4": {
"App\\": "app/",
"Wooserv\\ObjectId\\": "vendor/wooserv/php-objectid/src/"
}
}
Run composer dump-autoload.
First Use Case Generate an ObjectId in a Laravel model:
use Wooserv\ObjectId\ObjectId;
class User extends Model {
protected static function boot() {
parent::boot();
static::creating(function ($model) {
$model->id = ObjectId::generate();
});
}
}
Where to Look First
Wooserv\ObjectId\ObjectId class for core methods.Wooserv\ObjectId\ObjectIdInterface for type-hinting.Generating IDs
// Basic generation
$id = ObjectId::generate(); // e.g., "507f1f77bcf86cd799439011"
// Custom timestamp (seconds since epoch)
$id = ObjectId::generate(1609459200); // Fixed timestamp
Validation
use Wooserv\ObjectId\ObjectId;
if (ObjectId::isValid($id)) {
// Process valid ObjectId
}
Integration with Eloquent
// Override Laravel's default incrementing ID
class User extends Model {
public $incrementing = false;
protected $keyType = 'string';
protected $primaryKey = 'id';
protected static function boot() {
parent::boot();
static::creating(function ($model) {
$model->id = ObjectId::generate();
});
}
}
Batch Generation
$batch = [];
for ($i = 0; $i < 10; $i++) {
$batch[] = ObjectId::generate();
}
Custom ID Length The package defaults to 24 chars (MongoDB-style). Extend for custom lengths:
class CustomObjectId extends ObjectId {
public static function generate(int $timestamp = null, int $length = 16): string {
$bytes = parent::generateBytes($timestamp);
return substr(base_convert(bin2hex($bytes), 16, 36), 0, $length);
}
}
Hybrid IDs (e.g., UUID + ObjectId)
Combine with ramsey/uuid for hybrid use cases:
use Ramsey\Uuid\Uuid;
$hybridId = Uuid::uuid4()->toString() . '-' . ObjectId::generate();
Database Indexing Ensure your MongoDB-compatible database indexes ObjectId fields:
Schema::create('users', function (Blueprint $table) {
$table->string('id', 24)->primary();
$table->index('id'); // Explicit index (if needed)
});
API Responses Serialize ObjectIds in JSON APIs:
return response()->json([
'data' => [
'id' => $user->id, // Automatically cast to string
'name' => $user->name
]
]);
Non-Unique IDs in Distributed Systems ObjectIds are time-based and machine-dependent by default. In distributed environments, collisions are theoretically possible (though unlikely). Mitigate by:
$id = ObjectId::generate() . str_pad($counter++, 4, '0', STR_PAD_LEFT);
Timestamp Precision The package uses Unix timestamps (seconds). For millisecond precision, extend:
class MillisecondObjectId extends ObjectId {
public static function generate(int $timestamp = null): string {
$timestamp = $timestamp ?? (int)(microtime(true) * 1000);
return parent::generate($timestamp / 1000);
}
}
Case Sensitivity ObjectIds are case-sensitive in MongoDB. Ensure consistency:
$id = strtolower(ObjectId::generate()); // Force lowercase
Performance in Loops Avoid regenerating IDs in tight loops. Pre-generate if possible:
$ids = array_map(fn() => ObjectId::generate(), range(1, 1000));
Invalid ID Errors
Use ObjectId::isValid() to validate before operations:
if (!ObjectId::isValid($id)) {
throw new \InvalidArgumentException("Invalid ObjectId: {$id}");
}
Timestamp Mismatches If IDs appear "old" or "future," check your server clock sync:
$timestamp = ObjectId::parse($id)->getTimestamp();
Database Compatibility Test with your DB driver (e.g., MongoDB, PostgreSQL UUID extension). Some drivers may require type casting:
// PostgreSQL example
$table->uuid('id')->default(\DB::raw("gen_random_uuid()")); // Fallback
Custom ID Formats
Override generateBytes() for non-standard formats:
class CustomFormatObjectId extends ObjectId {
protected static function generateBytes(int $timestamp): string {
$bytes = parent::generateBytes($timestamp);
// Modify bytes (e.g., XOR with a salt)
return $bytes ^ "\xAA\xBB\xCC";
}
}
Integration with Laravel Scopes Add ObjectId-based query scopes:
class User extends Model {
public function scopeByObjectId($query, $id) {
return $query->where('id', $id);
}
}
Event Dispatching Trigger events on ID generation:
ObjectId::generating(function ($id) {
event(new ObjectIdGenerated($id));
});
Testing Mock ObjectId in tests:
$mockId = '507f1f77bcf86cd799439011';
ObjectId::shouldReceive('generate')->andReturn($mockId);
How can I help you explore Laravel packages today?