Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Taxonomy Laravel Package

aliziodev/laravel-taxonomy

Flexible Laravel package for managing taxonomies, categories, tags, and hierarchical trees. Includes nested-set support for fast hierarchy queries, metadata, bulk operations, caching, and custom taxonomy types. Compatible with Laravel 11+.

View on GitHub
Deep Wiki
Context7

Analytics and Reporting

Scenario: Building comprehensive reports and analytics using taxonomy data.

1. Taxonomy usage analytics

class TaxonomyAnalyticsService
{
    public function getUsageStatistics(string $type, ?int $tenantId = null): array
    {
        $query = Taxonomy::where('type', $type);
        
        if ($tenantId) {
            $query->where('tenant_id', $tenantId);
        }

        return $query->withCount('models')
            ->orderBy('models_count', 'desc')
            ->get()
            ->map(function ($taxonomy) {
                return [
                    'id' => $taxonomy->id,
                    'name' => $taxonomy->name,
                    'usage_count' => $taxonomy->models_count,
                    'last_used' => $taxonomy->models()->latest('created_at')->first()?->created_at,
                    'meta' => $taxonomy->meta,
                ];
            })
            ->toArray();
    }

    public function getHierarchyDepthAnalysis(string $type): array
    {
        $taxonomies = Taxonomy::where('type', $type)
            ->orderBy('lft')
            ->get();

        $depthStats = $taxonomies->groupBy('depth')
            ->map(function ($group, $depth) {
                return [
                    'depth' => $depth,
                    'count' => $group->count(),
                    'taxonomies' => $group->pluck('name')->toArray(),
                ];
            })
            ->values();

        return [
            'max_depth' => $taxonomies->max('depth'),
            'avg_depth' => $taxonomies->avg('depth'),
            'depth_distribution' => $depthStats,
        ];
    }

    public function getPopularityTrends(string $type, int $days = 30): array
    {
        $startDate = now()->subDays($days);
        
        return DB::table('taxonomables')
            ->join('taxonomies', 'taxonomables.taxonomy_id', '=', 'taxonomies.id')
            ->where('taxonomies.type', $type)
            ->where('taxonomables.created_at', '>=', $startDate)
            ->select(
                'taxonomies.name',
                DB::raw('DATE(taxonomables.created_at) as date'),
                DB::raw('COUNT(*) as usage_count')
            )
            ->groupBy('taxonomies.name', 'date')
            ->orderBy('date')
            ->get()
            ->groupBy('name')
            ->map(function ($group) {
                return $group->pluck('usage_count', 'date')->toArray();
            })
            ->toArray();
    }
}

2. Advanced reporting dashboard

class ReportingController extends Controller
{
    protected $analyticsService;

    public function __construct(TaxonomyAnalyticsService $analyticsService)
    {
        $this->analyticsService = $analyticsService;
    }

    public function dashboard()
    {
        $reports = [
            'category_usage' => $this->analyticsService->getUsageStatistics('category'),
            'tag_trends' => $this->analyticsService->getPopularityTrends('tag', 30),
            'hierarchy_analysis' => $this->analyticsService->getHierarchyDepthAnalysis('category'),
            'performance_metrics' => $this->getPerformanceMetrics(),
        ];

        return view('reports.dashboard', compact('reports'));
    }

    public function exportReport(Request $request)
    {
        $type = $request->input('type', 'category');
        $format = $request->input('format', 'csv');
        $dateRange = $request->input('date_range', 30);

        $data = $this->analyticsService->getUsageStatistics($type);

        if ($format === 'csv') {
            return $this->exportToCsv($data, "taxonomy-{$type}-report.csv");
        }

        if ($format === 'json') {
            return response()->json($data);
        }

        return $this->exportToPdf($data, "taxonomy-{$type}-report.pdf");
    }

    private function getPerformanceMetrics(): array
    {
        return [
            'total_taxonomies' => Taxonomy::count(),
            'total_associations' => DB::table('taxonomables')->count(),
            'avg_associations_per_taxonomy' => DB::table('taxonomables')
                ->selectRaw('AVG(association_count) as avg')
                ->fromSub(function ($query) {
                    $query->from('taxonomables')
                        ->selectRaw('taxonomy_id, COUNT(*) as association_count')
                        ->groupBy('taxonomy_id');
                }, 'subquery')
                ->value('avg'),
            'most_used_type' => Taxonomy::selectRaw('type, COUNT(*) as count')
                ->groupBy('type')
                ->orderBy('count', 'desc')
                ->first()?->type,
        ];
    }

    private function exportToCsv(array $data, string $filename)
    {
        $headers = [
            'Content-Type' => 'text/csv',
            'Content-Disposition' => "attachment; filename={$filename}",
        ];

        $callback = function () use ($data) {
            $file = fopen('php://output', 'w');
            
            // Add CSV headers
            fputcsv($file, ['ID', 'Name', 'Usage Count', 'Last Used', 'Meta']);
            
            foreach ($data as $row) {
                fputcsv($file, [
                    $row['id'],
                    $row['name'],
                    $row['usage_count'],
                    $row['last_used'],
                    json_encode($row['meta']),
                ]);
            }
            
            fclose($file);
        };

        return response()->stream($callback, 200, $headers);
    }

    private function exportToPdf(array $data, string $filename)
    {
        $pdf = PDF::loadView('reports.pdf-template', compact('data'));
        return $pdf->download($filename);
    }
}

3. Real-time analytics with caching

class CachedAnalyticsService
{
    protected $cache;
    protected $analyticsService;

    public function __construct(Cache $cache, TaxonomyAnalyticsService $analyticsService)
    {
        $this->cache = $cache;
        $this->analyticsService = $analyticsService;
    }

    public function getCachedUsageStats(string $type, int $ttl = 3600): array
    {
        $cacheKey = "taxonomy_usage_stats_{$type}";
        
        return $this->cache->remember($cacheKey, $ttl, function () use ($type) {
            return $this->analyticsService->getUsageStatistics($type);
        });
    }

    public function getCachedTrends(string $type, int $days = 30, int $ttl = 1800): array
    {
        $cacheKey = "taxonomy_trends_{$type}_{$days}";
        
        return $this->cache->remember($cacheKey, $ttl, function () use ($type, $days) {
            return $this->analyticsService->getPopularityTrends($type, $days);
        });
    }

    public function invalidateCache(string $type = null): void
    {
        if ($type) {
            $this->cache->forget("taxonomy_usage_stats_{$type}");
            $this->cache->forget("taxonomy_trends_{$type}_30");
        } else {
            // Clear all taxonomy analytics cache
            $this->cache->flush();
        }
    }

    public function getRealtimeMetrics(): array
    {
        return [
            'active_users' => $this->getActiveUsersCount(),
            'recent_associations' => $this->getRecentAssociations(),
            'trending_taxonomies' => $this->getTrendingTaxonomies(),
            'system_health' => $this->getSystemHealth(),
        ];
    }

    private function getActiveUsersCount(): int
    {
        return DB::table('taxonomables')
            ->where('created_at', '>=', now()->subHour())
            ->distinct('created_by')
            ->count('created_by');
    }

    private function getRecentAssociations(): int
    {
        return DB::table('taxonomables')
            ->where('created_at', '>=', now()->subMinutes(5))
            ->count();
    }

    private function getTrendingTaxonomies(): array
    {
        return DB::table('taxonomables')
            ->join('taxonomies', 'taxonomables.taxonomy_id', '=', 'taxonomies.id')
            ->where('taxonomables.created_at', '>=', now()->subHour())
            ->select('taxonomies.name', DB::raw('COUNT(*) as count'))
            ->groupBy('taxonomies.id', 'taxonomies.name')
            ->orderBy('count', 'desc')
            ->limit(5)
            ->get()
            ->toArray();
    }

    private function getSystemHealth(): array
    {
        $totalTaxonomies = Taxonomy::count();
        $totalAssociations = DB::table('taxonomables')->count();
        $avgResponseTime = $this->calculateAverageResponseTime();
        
        return [
            'status' => $avgResponseTime < 100 ? 'healthy' : 'warning',
            'total_taxonomies' => $totalTaxonomies,
            'total_associations' => $totalAssociations,
            'avg_response_time' => $avgResponseTime,
            'cache_hit_rate' => $this->calculateCacheHitRate(),
        ];
    }

    private function calculateAverageResponseTime(): float
    {
        // Implementation would measure actual response times
        return rand(50, 150); // Placeholder
    }

    private function calculateCacheHitRate(): float
    {
        // Implementation would calculate actual cache hit rate
        return rand(80, 95); // Placeholder
    }
}

4. Custom report builder

class ReportBuilder
{
    protected $query;
    protected $filters = [];
    protected $groupBy = [];
    protected $orderBy = [];

    public function __construct()
    {
        $this->query = DB::table('taxonomies')
            ->leftJoin('taxonomables', 'taxonomies.id', '=', 'taxonomables.taxonomy_id');
    }

    public function filterByType(string $type): self
    {
        $this->filters[] = ['taxonomies.type', '=', $type];
        return $this;
    }

    public function filterByDateRange(Carbon $startDate, Carbon $endDate): self
    {
        $this->filters[] = ['taxonomables.created_at', '>=', $startDate];
        $this->filters[] = ['taxonomables.created_at', '<=', $endDate];
        return $this;
    }

    public function filterByUsageCount(int $minCount, ?int $maxCount = null): self
    {
        $this->query->havingRaw('COUNT(taxonomables.id) >= ?', [$minCount]);
        
        if ($maxCount) {
            $this->query->havingRaw('COUNT(taxonomables.id) <= ?', [$maxCount]);
        }
        
        return $this;
    }

    public function groupByType(): self
    {
        $this->groupBy[] = 'taxonomies.type';
        return $this;
    }

    public function groupByDate(string $format = 'Y-m-d'): self
    {
        $this->groupBy[] = DB::raw("DATE_FORMAT(taxonomables.created_at, '{$format}') as date_group");
        return $this;
    }

    public function orderByUsage(string $direction = 'desc'): self
    {
        $this->orderBy[] = ['usage_count', $direction];
        return $this;
    }

    public function orderByName(string $direction = 'asc'): self
    {
        $this->orderBy[] = ['taxonomies.name', $direction];
        return $this;
    }

    public function build(): Collection
    {
        // Apply filters
        foreach ($this->filters as $filter) {
            $this->query->where(...$filter);
        }

        // Apply grouping
        if (!empty($this->groupBy)) {
            $this->query->groupBy($this->groupBy);
        } else {
            $this->query->groupBy('taxonomies.id');
        }

        // Select fields
        $this->query->select([
            'taxonomies.id',
            'taxonomies.name',
            'taxonomies.type',
            'taxonomies.meta',
            DB::raw('COUNT(taxonomables.id) as usage_count'),
            DB::raw('MAX(taxonomables.created_at) as last_used'),
        ]);

        // Apply ordering
        foreach ($this->orderBy as $order) {
            $this->query->orderBy(...$order);
        }

        return $this->query->get();
    }

    public function toChart(string $chartType = 'bar'): array
    {
        $data = $this->build();
        
        return [
            'type' => $chartType,
            'labels' => $data->pluck('name')->toArray(),
            'datasets' => [[
                'label' => 'Usage Count',
                'data' => $data->pluck('usage_count')->toArray(),
                'backgroundColor' => $this->generateColors($data->count()),
            ]],
        ];
    }

    private function generateColors(int $count): array
    {
        $colors = [
            '#FF6384', '#36A2EB', '#FFCE56', '#4BC0C0',
            '#9966FF', '#FF9F40', '#FF6384', '#C9CBCF'
        ];
        
        return array_slice(array_merge($colors, $colors), 0, $count);
    }
}

5. Automated reporting system

class AutomatedReportingService
{
    public function scheduleReports(): void
    {
        // Daily usage report
        Schedule::call(function () {
            $this->generateDailyUsageReport();
        })->daily();

        // Weekly trend analysis
        Schedule::call(function () {
            $this->generateWeeklyTrendReport();
        })->weekly();

        // Monthly comprehensive report
        Schedule::call(function () {
            $this->generateMonthlyReport();
        })->monthly();
    }

    public function generateDailyUsageReport(): void
    {
        $report = (new ReportBuilder())
            ->filterByDateRange(now()->subDay(), now())
            ->groupByType()
            ->orderByUsage()
            ->build();

        $this->sendReportEmail('Daily Taxonomy Usage Report', $report, 'daily-usage');
    }

    public function generateWeeklyTrendReport(): void
    {
        $analyticsService = app(TaxonomyAnalyticsService::class);
        
        $trends = $analyticsService->getPopularityTrends('category', 7);
        $usage = $analyticsService->getUsageStatistics('tag');
        
        $this->sendReportEmail('Weekly Taxonomy Trends', [
            'trends' => $trends,
            'usage' => $usage,
        ], 'weekly-trends');
    }

    public function generateMonthlyReport(): void
    {
        $analyticsService = app(TaxonomyAnalyticsService::class);
        
        $report = [
            'summary' => $this->getMonthlyMetrics(),
            'category_analysis' => $analyticsService->getHierarchyDepthAnalysis('category'),
            'usage_trends' => $analyticsService->getPopularityTrends('category', 30),
            'performance_metrics' => $this->getPerformanceMetrics(),
        ];
        
        $this->sendReportEmail('Monthly Taxonomy Report', $report, 'monthly-comprehensive');
    }

    private function sendReportEmail(string $subject, array $data, string $template): void
    {
        $recipients = config('taxonomy.reporting.email_recipients', []);
        
        foreach ($recipients as $recipient) {
            Mail::to($recipient)->send(new TaxonomyReportMail($subject, $data, $template));
        }
    }

    private function getMonthlyMetrics(): array
    {
        $startOfMonth = now()->startOfMonth();
        
        return [
            'new_taxonomies' => Taxonomy::where('created_at', '>=', $startOfMonth)->count(),
            'new_associations' => DB::table('taxonomables')
                ->where('created_at', '>=', $startOfMonth)
                ->count(),
            'most_active_type' => $this->getMostActiveType($startOfMonth),
            'growth_rate' => $this->calculateGrowthRate($startOfMonth),
        ];
    }

    private function getMostActiveType(Carbon $startDate): ?string
    {
        return DB::table('taxonomables')
            ->join('taxonomies', 'taxonomables.taxonomy_id', '=', 'taxonomies.id')
            ->where('taxonomables.created_at', '>=', $startDate)
            ->select('taxonomies.type', DB::raw('COUNT(*) as count'))
            ->groupBy('taxonomies.type')
            ->orderBy('count', 'desc')
            ->first()?->type;
    }

    private function calculateGrowthRate(Carbon $startDate): float
    {
        $currentMonth = DB::table('taxonomables')
            ->where('created_at', '>=', $startDate)
            ->count();
            
        $previousMonth = DB::table('taxonomables')
            ->where('created_at', '>=', $startDate->copy()->subMonth())
            ->where('created_at', '<', $startDate)
            ->count();
            
        return $previousMonth > 0 ? (($currentMonth - $previousMonth) / $previousMonth) * 100 : 0;
    }

    private function getPerformanceMetrics(): array
    {
        return [
            'avg_query_time' => $this->measureAverageQueryTime(),
            'cache_efficiency' => $this->calculateCacheEfficiency(),
            'database_size' => $this->getDatabaseSize(),
            'optimization_suggestions' => $this->getOptimizationSuggestions(),
        ];
    }

    private function measureAverageQueryTime(): float
    {
        // Implementation would measure actual query performance
        return 45.2; // Placeholder (milliseconds)
    }

    private function calculateCacheEfficiency(): float
    {
        // Implementation would calculate cache hit/miss ratio
        return 87.5; // Placeholder (percentage)
    }

    private function getDatabaseSize(): array
    {
        return [
            'taxonomies_table_size' => '2.5 MB',
            'taxonomables_table_size' => '15.8 MB',
            'total_size' => '18.3 MB',
        ];
    }

    private function getOptimizationSuggestions(): array
    {
        return [
            'Consider adding indexes on frequently queried meta fields',
            'Archive old taxonomy associations to improve performance',
            'Implement more aggressive caching for read-heavy operations',
        ];
    }
}

This analytics and reporting example demonstrates how Laravel Taxonomy can power sophisticated business intelligence systems with real-time metrics, automated reporting, and comprehensive data analysis capabilities.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
nasirkhan/laravel-sharekit
directorytree/privacy-filter-classifier
directorytree/privacy-filter
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
develia/geo-bundle
dreamzy/livewire-charts
touchestate-sdk/php-sdk
22h/doctrine-garbage-collection-bundle
agtp/agtp-php
agtp/mod-php
splash/sonata-admin
splash/metadata
splash/openapi
splash/scopes
splash/toolkit
testo/output-teamcity
testo/bridge-symfony