Skip to content

Commit

Permalink
Some code cleanup, and added the value cache.
Browse files Browse the repository at this point in the history
  • Loading branch information
kirkbushell committed Feb 4, 2024
1 parent 42ae6c8 commit f179a24
Show file tree
Hide file tree
Showing 13 changed files with 149 additions and 14 deletions.
12 changes: 10 additions & 2 deletions src/Behaviours/Cacheable.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,14 @@ trait Cacheable
*/
abstract private function configuration(): array;

/**
* Template method for setting up the CacheConfig object.
*/
protected function config($relationName, $aggregateField): CacheConfig
{
return new CacheConfig($relationName, $aggregateField);
}

/**
* Helper method for easier use of the implementing classes.
*/
Expand Down Expand Up @@ -101,9 +109,9 @@ public function rebuildCacheRecord(CacheConfig $config, Model $model, $command):
/**
* Update the cache value for the model.
*/
protected function updateCacheValue(Model $model, CacheConfig $config, int $amount): void
protected function updateCacheValue(Model $model, CacheConfig $config, $value): void
{
$model->{$config->aggregateField} = $model->{$config->aggregateField} + $amount;
$model->{$config->aggregateField} = $model->{$config->aggregateField} + $value;
$model->save();
}
}
8 changes: 0 additions & 8 deletions src/Behaviours/CountCache/CountCache.php
Original file line number Diff line number Diff line change
Expand Up @@ -71,12 +71,4 @@ public function decrement(): void
$this->updateCacheValue($config->relatedModel($this->model), $config, -1);
});
}

/**
* Takes a registered counter cache, and setups up defaults.
*/
protected function config($key, string $value): CacheConfig
{
return new CacheConfig($key, $value);
}
}
2 changes: 1 addition & 1 deletion src/Behaviours/CountCache/HasCounts.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

trait HasCounts
{
public static function bootHasCounts()
public static function bootHasCounts(): void
{
static::observe(Observer::class);
}
Expand Down
2 changes: 1 addition & 1 deletion src/Behaviours/SumCache/HasSums.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

trait HasSums
{
public static function bootHasSums()
public static function bootHasSums(): void
{
static::observe(Observer::class);
}
Expand Down
4 changes: 2 additions & 2 deletions src/Behaviours/SumCache/SumCache.php
Original file line number Diff line number Diff line change
Expand Up @@ -68,13 +68,13 @@ public function update(): void
/**
* Takes a registered sum cache, and setups up defaults.
*/
protected function config($relation, string|array $sourceField): CacheConfig
protected function config($relationName, $sourceField): CacheConfig
{
$keys = array_keys($sourceField);

$aggregateField = $keys[0];
$sourceField = $sourceField[$aggregateField];

return new CacheConfig($relation, $aggregateField, $sourceField);
return new CacheConfig($relationName, $aggregateField, $sourceField);
}
}
16 changes: 16 additions & 0 deletions src/Behaviours/ValueCache/HasValues.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

namespace Eloquence\Behaviours\ValueCache;

trait HasValues
{
public static function bootHasValues(): void
{
static::observe(Observer::class);
}

public static function rebuildValueCache(): void
{
ValueCache::for(new self())->rebuild();
}
}
16 changes: 16 additions & 0 deletions src/Behaviours/ValueCache/Observer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

namespace Eloquence\Behaviours\ValueCache;

class Observer
{
public function created($model): void
{
ValueCache::for($model)->updateRelated(true);
}

public function updated($model): void
{
ValueCache::for($model)->updateRelated(false);
}
}
55 changes: 55 additions & 0 deletions src/Behaviours/ValueCache/ValueCache.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php

namespace Eloquence\Behaviours\ValueCache;

use Eloquence\Behaviours\Cacheable;
use Eloquence\Behaviours\CacheConfig;
use Illuminate\Database\Eloquent\Model;

class ValueCache
{
use Cacheable;

private function __construct(private Model $model)
{
}

protected function config($relationName, $sourceField): CacheConfig
{
$keys = array_keys($sourceField);

$aggregateField = $keys[0];
$sourceField = $sourceField[$aggregateField];

return new CacheConfig($relationName, $aggregateField, $sourceField);
}

public function rebuild()
{

}

public function updateRelated(bool $new): void
{
$this->apply(function(CacheConfig $config) use ($new) {
$foreignKey = $config->foreignKeyName($this->model);

// We only do work if the model previously existed and the source field has changed, or the model was newly created in the database.
if (!($new || $this->model->wasChanged($config->sourceField))) {
return;
}

$relatedModel = $config->emptyRelatedModel($this->model)->find($this->model->$foreignKey);

$relatedModel->{$config->aggregateField} = $this->model->{$config->sourceField};
$relatedModel->save();
});
}

private function configuration(): array
{
return $this->reflect(ValuedBy::class, function (array $config) {
return [$config['name'] => [$config['attribute']->as => $config['attribute']->from]];
});
}
}
13 changes: 13 additions & 0 deletions src/Behaviours/ValueCache/ValuedBy.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

namespace Eloquence\Behaviours\ValueCache;

use Attribute;

#[Attribute(Attribute::TARGET_METHOD)]
class ValuedBy
{
public function __construct(readonly string $from, readonly ?string $as)
{
}
}
2 changes: 2 additions & 0 deletions tests/Acceptance/AcceptanceTestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ private function migrate()
$table->integer('user_id')->nullable();
$table->string('slug')->nullable();
$table->integer('comment_count')->default(0);
$table->dateTime('publish_at')->nullable();
$table->timestamps();
});

Expand Down Expand Up @@ -85,6 +86,7 @@ private function migrate()
$table->increments('id');
$table->integer('post_count')->default(0);
$table->integer('total_comments')->default(0);
$table->dateTime('last_activity_at')->nullable();
$table->timestamps();
});
}
Expand Down
8 changes: 8 additions & 0 deletions tests/Acceptance/ModelTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php

namespace Tests\Acceptance;

class ModelTest
{

}
5 changes: 5 additions & 0 deletions tests/Acceptance/Models/Post.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
use Eloquence\Behaviours\HasSlugs;
use Eloquence\Behaviours\SumCache\HasSums;
use Eloquence\Behaviours\SumCache\SummedBy;
use Eloquence\Behaviours\ValueCache\HasValues;
use Eloquence\Behaviours\ValueCache\ValuedBy;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
Expand All @@ -19,10 +21,12 @@ class Post extends Model
use HasCounts;
use HasFactory;
use HasSums;
use HasValues;

protected $fillable = [
'user_id',
'category_id',
'publish_at',
];

#[CountedBy(as: 'post_count')]
Expand All @@ -38,6 +42,7 @@ public function slugStrategy()

#[CountedBy]
#[SummedBy(from: 'comment_count', as: 'total_comments')]
#[ValuedBy(from: 'publish_at', as: 'last_activity_at')]
public function category(): BelongsTo
{
return $this->belongsTo(Category::class);
Expand Down
20 changes: 20 additions & 0 deletions tests/Acceptance/ValueCacheTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

namespace Tests\Acceptance;

use Tests\Acceptance\Models\Category;
use Tests\Acceptance\Models\Post;

class ValueCacheTest extends AcceptanceTestCase
{
function test_values_from_related_models_are_cached()
{
$category = Category::factory()->create();

$this->assertNull($category->last_activity_at);

$post = Post::factory()->create(['category_id' => $category->id, 'publish_at' => now()->subDays(mt_rand(1, 10))]);

$this->assertEquals($category->fresh()->last_activity_at, $post->publish_at);
}
}

0 comments on commit f179a24

Please sign in to comment.