PHP code example of proai / laravel-data-integrity

1. Go to this page and download the library: Download proai/laravel-data-integrity library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

proai / laravel-data-integrity example snippets


use ProAI\DataIntegrity\AuditCase;
use ProAI\DataIntegrity\Audit;
use App\Models\Order;

class OrderAudit extends AuditCase
{
    protected $model = Order::class;

    public function checkTotalMatchesLineItems(): Audit
    {
        return $this->audit('order total matches line items')
            ->validate(function ($order, $fail) {
                $expected = $order->lineItems()->sum('price');

                if ((int) $order->total !== (int) $expected) {
                    $fail(
                        "has total {$order->total}, expected {$expected}",
                        fn () => $order->update(['total' => $expected]),
                    );
                }
            });
    }
}

$fail(
    "has total {$order->total}, expected {$expected}",
    fn () => $order->update(['total' => $expected]),
);

public function checkCompletedOrderHasPayment(): Audit
{
    return $this->audit('completed order has a payment')
        ->query(fn ($query) => $query->where('status', 'completed'))
        ->chunkSize(200)
        ->validate(function ($order, $fail) {
            if (! $order->payment()->exists()) {
                $fail('is completed but has no payment record');
            }
        });
}

// Description will be "email is valid"
public function checkEmailIsValid(): Audit
{
    return $this->audit()
        ->validate(fn ($user, $fail) => /* ... */);
}

protected array $activeCounts = [];

public function checkActiveOrdersCount(): Audit
{
    return $this->audit('user has correct active orders count')
        ->before(function ($chunk) {
            $this->activeCounts = DB::table('orders')
                ->whereIn('user_id', $chunk->modelKeys())
                ->where('status', 'active')
                ->groupBy('user_id')
                ->pluck(DB::raw('count(*)'), 'user_id')
                ->all();
        })
        ->validate(function ($user, $fail) {
            $expected = $this->activeCounts[$user->id] ?? 0;

            if ($user->active_orders_count !== $expected) {
                $fail(
                    "has active_orders_count {$user->active_orders_count}, expected {$expected}",
                    fn () => $user->update(['active_orders_count' => $expected]),
                );
            }
        });
}

use Closure;
use Illuminate\Database\Eloquent\Model;
use ProAI\DataIntegrity\IntegrityCheck;

class BelongsToExists implements IntegrityCheck
{
    public function __construct(
        public readonly string $relation,
    ) {}

    public function description(): string
    {
        return "{$this->relation} exists";
    }

    public function validate(Model $model, Closure $fail): void
    {
        if (! $model->{$this->relation}()->exists()) {
            $foreignKey = $model->{$this->relation}()->getForeignKeyName();

            $fail("references missing {$this->relation} ({$foreignKey}: {$model->$foreignKey})");
        }
    }
}

class CommentAudit extends AuditCase
{
    protected $model = Comment::class;

    public function checkPostExists(): Audit
    {
        return $this->auditUsing(BelongsToExists::class, ['post']);
    }

    public function checkAuthorExists(): Audit
    {
        return $this->auditUsing(BelongsToExists::class, ['author']);
    }
}

class CachedCountIsCorrect implements IntegrityCheck
{
    public function __construct(
        public readonly string $relation,
        public readonly string $column,
    ) {}

    public function validate(Model $model, Closure $fail): void
    {
        $expected = $model->{$this->relation}()->count();

        if ($model->{$this->column} !== $expected) {
            $fail(
                "has {$this->column} {$model->{$this->column}}, expected {$expected}",
                fn () => $model->update([$this->column => $expected]),
            );
        }
    }
}

// In ThreadAudit
public function checkPostsCount(): Audit
{
    return $this->auditUsing(CachedCountIsCorrect::class, ['posts', 'posts_count']);
}

public function checkSubscribersCount(): Audit
{
    return $this->auditUsing(CachedCountIsCorrect::class, ['subscribers', 'subscribers_count']);
}

class CachedCountIsCorrect implements IntegrityCheck
{
    protected Collection $expectedCounts;

    public function __construct(
        public readonly string $relation,
        public readonly string $column,
    ) {}

    public function before(EloquentCollection $chunk): void
    {
        $example = $chunk->first()->{$this->relation}();
        $foreignKey = $example->getForeignKeyName();
        $table = $example->getRelated()->getTable();

        $this->expectedCounts = DB::table($table)
            ->whereIn($foreignKey, $chunk->modelKeys())
            ->groupBy($foreignKey)
            ->pluck(DB::raw('count(*)'), $foreignKey);
    }

    public function validate(Model $model, Closure $fail): void
    {
        $expected = $this->expectedCounts->get($model->getKey(), 0);

        if ($model->{$this->column} !== $expected) {
            $fail(
                "has {$this->column} {$model->{$this->column}}, expected {$expected}",
                fn () => $model->update([$this->column => $expected]),
            );
        }
    }
}

use ProAI\DataIntegrity\AuditManager;

AuditManager::register('posts-count', PostsCountIsCorrect::class);

public function checkPostsCount(): Audit
{
    return $this->auditUsing('posts-count');
}

use ProAI\DataIntegrity\AuditManager;

// Override the default chunk size (default: 1000)
AuditManager::defaultChunkSize(500);

// Override the audit discovery path (default: database/audits)
AuditManager::discoverIn(database_path('my-audits'));

public function validate(Model $model, Closure $fail): void;

$fail(string $reason, ?Closure $fix = null): void