I am currently creating a blog where each Post row in my database will have a unique hash attribute that is based of the post's id (incrementing, always unique).
This my Post model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Hashids;
class Post extends Model
{
public function setTitleAttribute($value)
{
$this->attributes['title'] = $value;
if (! $this->exists) {
$this->attributes['slug'] = str_slug($value);
}
}
public function setIdAttribute($value) {
$this->attributes['id'] = $value;
$this->attributes['hash'] = Hashids::encode($value);
}
}
When I run this factory
$factory->define(App\Post::class, function (Faker\Generator $faker) {
return [
'title' => $faker->sentence(mt_rand(3, 10)),
'content' => join("
", $faker->paragraphs(mt_rand(3, 6))),
'author' => $faker->name,
'category' => rand(1, 20),
];
});
The setIdAttribute($value) function is getting called, but my hash attribute is not being set. I am not sure if it is getting overwritten or what.
If I move the line
$this->attributes['hash'] = Hashids::encode($value);
to the function
public function setTitleAttribute($value)
and encode the title attribute it works fine, but I want to encode the 'id' attribute. Any idea how I would do this?
You can add the following to your model:
/**
* Events
*/
public static function boot()
{
parent::boot();
static::created(function($model)
{
$model->hash = Hashids::encode($model->id);
$model->slug = str_slug($model->title);
}
}
It's likely setIdAttribute($value)
isn't being called until after the insert runs because it doesn't know the ID until then.
The real issue is you can't set a hash of the id
in the same query because the id
isn't going to be known (assuming it's auto_incrementing) until after the insert.
Because of this, the best you can probably do here is fire some code on the model's saved
event.
In that model, you can probably do something like...
public static function boot()
{
parent::boot();
static::flushEventListeners(); // Without this I think we have an infinite loop
static::saved(function($post) {
$post->hash = Hashids:encode($post->id);
$post->save();
});
}