### Quick Start: Create New Taxonomies Source: https://github.com/aliziodev/laravel-taxonomy/blob/master/README.md Provides a quick start example for creating new taxonomies using the `Taxonomy` facade, demonstrating how to create categories and tags, including nested categories with `parent_id`. ```php use Aliziodev\LaravelTaxonomy\Facades\Taxonomy; use Aliziodev\LaravelTaxonomy\Enums\TaxonomyType; // Create a category $electronics = Taxonomy::create([ 'name' => 'Electronics', 'type' => TaxonomyType::Category->value, 'description' => 'Electronic products and gadgets', ]); // Create a subcategory $smartphones = Taxonomy::create([ 'name' => 'Smartphones', 'type' => TaxonomyType::Category->value, 'parent_id' => $electronics->id, ]); // Create tags $featured = Taxonomy::create([ 'name' => 'Featured', 'type' => TaxonomyType::Tag->value, ]); ``` -------------------------------- ### Development Workflow: Install Composer Dependencies Source: https://github.com/aliziodev/laravel-taxonomy/blob/master/CONTRIBUTING.md Command to install project dependencies using Composer after cloning the repository. ```bash composer install ``` -------------------------------- ### Development Workflow: Fork and Clone Repository Source: https://github.com/aliziodev/laravel-taxonomy/blob/master/CONTRIBUTING.md Instructions for starting development by forking the repository and cloning it locally using Git commands. ```bash git clone https://github.com/your-username/laravel-taxonomy.git cd laravel-taxonomy ``` -------------------------------- ### Install Laravel Taxonomy via Composer Source: https://github.com/aliziodev/laravel-taxonomy/blob/master/README.md Installs the Laravel Taxonomy package into your project by adding it as a Composer dependency. This command fetches the package from Packagist and integrates it into your application. ```bash composer require aliziodev/laravel-taxonomy ``` -------------------------------- ### Laravel Controller Example for Taxonomy Usage Source: https://github.com/aliziodev/laravel-taxonomy/blob/master/README.md This comprehensive Laravel controller example illustrates the practical application of the Laravel Taxonomy package. It includes an `index` method for displaying paginated products filtered by category using query scopes, and a `store` method for creating new products and attaching categories and tags based on request input. ```php namespace App\Http\Controllers; use App\Models\Product; use Aliziodev\LaravelTaxonomy\Enums\TaxonomyType; use Aliziodev\LaravelTaxonomy\Facades\Taxonomy; use Illuminate\Http\Request; class ProductController extends Controller { public function index(Request $request) { // Get products filtered by category $categorySlug = $request->input('category'); $query = Product::query(); if ($categorySlug) { $category = Taxonomy::findBySlug($categorySlug, TaxonomyType::Category); if ($category) { $query->withAnyTaxonomies($category); } } $products = $query->paginate(12); $categories = Taxonomy::findByType(TaxonomyType::Category); return view('products.index', compact('products', 'categories')); } public function store(Request $request) { $validated = $request->validate([ 'name' => 'required|string|max:255', 'categories' => 'required|array', 'tags' => 'nullable|array', ]); $product = Product::create($validated); // Attach categories and tags $product->attachTaxonomies($validated['categories']); if (isset($validated['tags'])) { $product->attachTaxonomies($validated['tags']); } return redirect()->route('products.show', $product) ->with('success', 'Product created successfully.'); } } ``` -------------------------------- ### Conventional Commits: Example Messages Source: https://github.com/aliziodev/laravel-taxonomy/blob/master/CONTRIBUTING.md Illustrates various commit message examples, including new features, bug fixes, breaking changes, and commits with specific scopes, demonstrating the application of Conventional Commits. ```bash # New feature feat: add moveToParent method with optional rebuildNestedSet parameter # Bug fix fix: resolve nested set corruption on concurrent operations # Breaking change feat!: change taxonomy structure to support multi-tenancy BREAKING CHANGE: The taxonomy table now requires tenant_id column # With scope feat(manager): add bulk operations for taxonomy management fix(model): correct parent validation in moveToParent method docs(readme): update installation instructions ``` -------------------------------- ### Publish Laravel Taxonomy Configuration and Migrations Source: https://github.com/aliziodev/laravel-taxonomy/blob/master/README.md Publishes the essential configuration file and database migrations for the Laravel Taxonomy package using a single artisan command. This streamlines the setup process by automating the publishing steps. ```bash php artisan taxonomy:install ``` -------------------------------- ### Conventional Commit Message Format Examples Source: https://github.com/aliziodev/laravel-taxonomy/blob/master/README.md Examples of valid commit messages following the Conventional Commits specification, illustrating `feat`, `fix`, and breaking change (`feat!`) types for automated changelog generation. ```bash feat: add moveToParent method with performance optimization fix: resolve nested set corruption on concurrent operations feat!: change taxonomy structure for multi-tenancy support ``` -------------------------------- ### Quick Start: Associate Taxonomies with Eloquent Models Source: https://github.com/aliziodev/laravel-taxonomy/blob/master/README.md Shows how to attach created taxonomies to an Eloquent model (e.g., `Product`) using the `attachTaxonomies` method, supporting attachment by ID or by slug. ```php // Assuming you have a Product model with HasTaxonomy trait $product = Product::create([ 'name' => 'iPhone 15 Pro', 'price' => 999.99, ]); // Attach taxonomies $product->attachTaxonomies([$electronics->id, $smartphones->id, $featured->id]); // Or attach by slug $product->attachTaxonomies(['electronics', 'smartphones', 'featured']); ``` -------------------------------- ### Manually Publish Laravel Taxonomy Configuration and Migrations Source: https://github.com/aliziodev/laravel-taxonomy/blob/master/README.md Manually publishes the configuration file and database migrations for the Laravel Taxonomy package. This provides granular control over which assets are published, allowing for custom setup or troubleshooting. ```bash php artisan vendor:publish --provider="Aliziodev\\LaravelTaxonomy\\TaxonomyProvider" --tag="taxonomy-config" php artisan vendor:publish --provider="Aliziodev\\LaravelTaxonomy\\TaxonomyProvider" --tag="taxonomy-migrations" ``` -------------------------------- ### Quick Start: Query and Filter Models by Taxonomy Source: https://github.com/aliziodev/laravel-taxonomy/blob/master/README.md Demonstrates how to query and filter models based on their associated taxonomies using methods like `withTaxonomyType` and `withTaxonomySlug`. Also shows how to retrieve taxonomies by type or as a hierarchical tree. ```php // Find products in electronics category $products = Product::withTaxonomyType(TaxonomyType::Category) ->withTaxonomySlug('electronics') ->get(); // Get all taxonomies of a specific type $categories = Taxonomy::findByType(TaxonomyType::Category); // Get hierarchical tree $categoryTree = Taxonomy::tree(TaxonomyType::Category); ``` -------------------------------- ### Complete Development Workflow with Git and Conventional Commits Source: https://github.com/aliziodev/laravel-taxonomy/blob/master/CONTRIBUTING.md This comprehensive example demonstrates the standard development workflow, from creating a feature branch and making code changes to running tests, committing with a conventional message, and pushing to create a pull request. It emphasizes adherence to commit message best practices for automated changelog generation. ```bash # 1. Create feature branch git checkout -b feat/bulk-taxonomy-operations # 2. Make changes # ... edit files ... # 3. Add tests # ... create tests ... # 4. Run tests vendor/bin/pest vendor/bin/phpstan analyse vendor/bin/pint --test # 5. Commit with conventional format git add . git commit -m "feat: add bulk operations for taxonomy management Implement bulkCreate, bulkUpdate, and bulkDelete methods to improve performance for large-scale operations. Closes #45" # 6. Push and create PR git push origin feat/bulk-taxonomy-operations ``` -------------------------------- ### Set up Educational Taxonomies for Skills and Difficulty Source: https://github.com/aliziodev/laravel-taxonomy/blob/master/docs/en/learning-management-system.md This snippet demonstrates how to create and manage skill categories and difficulty levels using the Taxonomy model. It includes examples of nested skills and attaching custom metadata like icons, industry, prerequisites, and color codes. ```php // Create skill categories $programmingSkill = Taxonomy::create([ 'name' => 'Programming', 'type' => 'skill', 'meta' => [ 'icon' => 'code', 'industry' => 'Technology', 'demand_level' => 'high', ], ]); $webDevelopment = Taxonomy::create([ 'name' => 'Web Development', 'type' => 'skill', 'parent_id' => $programmingSkill->id, 'meta' => [ 'prerequisites' => ['HTML', 'CSS', 'JavaScript'], 'career_paths' => ['Frontend Developer', 'Full Stack Developer'], ], ]); // Create difficulty levels $difficulties = [ ['name' => 'Beginner', 'order' => 1, 'color' => '#28a745'], ['name' => 'Intermediate', 'order' => 2, 'color' => '#ffc107'], ['name' => 'Advanced', 'order' => 3, 'color' => '#dc3545'], ]; foreach ($difficulties as $difficulty) { Taxonomy::create([ 'name' => $difficulty['name'], 'type' => 'difficulty', 'sort_order' => $difficulty['order'], 'meta' => [ 'color' => $difficulty['color'], 'estimated_hours' => $difficulty['order'] * 20, ], ]); } ``` -------------------------------- ### Create Laravel Taxonomy Upgrade Migration File Source: https://github.com/aliziodev/laravel-taxonomy/blob/master/UPGRADE.md Provides the 'artisan' command to generate a new migration file for updating the taxonomy unique constraint. This is the first step in preparing the database schema changes. ```bash php artisan make:migration upgrade_taxonomies_unique_constraint_to_v2_3 ``` -------------------------------- ### Paginate Taxonomy Search and Find Results Source: https://github.com/aliziodev/laravel-taxonomy/blob/master/README.md This example demonstrates how the Laravel Taxonomy package supports pagination for search and find methods. It shows how to paginate general search results, taxonomies filtered by type, and taxonomies found by their parent, specifying items per page and the current page number. ```php // Paginate search results (5 items per page, page 1) $results = Taxonomy::search('electronic', null, 5, 1); // Paginate taxonomies by type $categories = Taxonomy::findByType(TaxonomyType::Category, 10, 1); // Paginate taxonomies by parent $children = Taxonomy::findByParent($parent->id, 10, 1); ``` -------------------------------- ### Set up Taxonomy Structure for E-commerce Categories, Brands, and Attributes (PHP) Source: https://github.com/aliziodev/laravel-taxonomy/blob/master/docs/en/ecommerce-product-catalog.md This PHP snippet demonstrates how to define and create various taxonomy types like categories, brands, and product attributes (e.g., colors) using the Laravel Taxonomy package. It shows the creation of parent-child relationships for categories and the use of 'meta' data for additional properties like icons, banners, or SEO information. This setup is crucial for organizing product data in an e-commerce platform. ```php use Aliziodev\LaravelTaxonomy\Facades\Taxonomy; use Aliziodev\LaravelTaxonomy\Enums\TaxonomyType; // Create main categories $electronics = Taxonomy::create([ 'name' => 'Electronics', 'type' => TaxonomyType::Category->value, 'meta' => [ 'icon' => 'laptop', 'banner_image' => 'electronics-banner.jpg', 'seo_title' => 'Electronics - Latest Gadgets & Devices', ], ]); $clothing = Taxonomy::create([ 'name' => 'Clothing', 'type' => TaxonomyType::Category->value, 'meta' => [ 'icon' => 'shirt', 'seasonal' => true, ], ]); // Create subcategories $smartphones = Taxonomy::create([ 'name' => 'Smartphones', 'type' => TaxonomyType::Category->value, 'parent_id' => $electronics->id, 'meta' => [ 'filters' => ['brand', 'price_range', 'storage', 'color'], 'popular' => true, ], ]); $laptops = Taxonomy::create([ 'name' => 'Laptops', 'type' => TaxonomyType::Category->value, 'parent_id' => $electronics->id, ]); // Create brands $apple = Taxonomy::create([ 'name' => 'Apple', 'type' => 'brand', 'meta' => [ 'logo' => 'apple-logo.png', 'premium' => true, 'warranty_years' => 1, ], ]); $samsung = Taxonomy::create([ 'name' => 'Samsung', 'type' => 'brand', 'meta' => [ 'logo' => 'samsung-logo.png', 'country' => 'South Korea', ], ]); // Create product attributes $colors = [ ['name' => 'Space Gray', 'hex' => '#8E8E93'], ['name' => 'Silver', 'hex' => '#C7C7CC'], ['name' => 'Gold', 'hex' => '#FFD700'], ]; foreach ($colors as $color) { Taxonomy::create([ 'name' => $color['name'], 'type' => TaxonomyType::Color->value, 'meta' => ['hex_code' => $color['hex']], ]); } ``` -------------------------------- ### Execute Laravel Database Migrations Source: https://github.com/aliziodev/laravel-taxonomy/blob/master/UPGRADE.md The standard 'artisan' command to run pending database migrations, applying the schema changes defined in the migration file. This step finalizes the database update for the new unique constraint. ```bash php artisan migrate ``` -------------------------------- ### Performing Bulk Taxonomy Operations in PHP Source: https://github.com/aliziodev/laravel-taxonomy/blob/master/README.md Provides examples of efficient bulk operations for managing taxonomy relationships on a model. This includes attaching multiple taxonomies without duplication, detaching specific or all taxonomies, syncing (replacing) taxonomies, and toggling their presence. ```php // Attach multiple taxonomies (won't duplicate existing) $product->attachTaxonomies([1, 2, 3, 'electronics', 'featured']); // Detach specific taxonomies $product->detachTaxonomies([1, 2]); // Detach all taxonomies $product->detachTaxonomies(); // Sync taxonomies (removes old, adds new) $product->syncTaxonomies([1, 2, 3]); // Toggle taxonomies (attach if not present, detach if present) $product->toggleTaxonomies([1, 2, 3]); // Work with different relationship names $product->attachTaxonomies($categoryIds, 'categories'); $product->attachTaxonomies($tagIds, 'tags'); ``` -------------------------------- ### Optimize Taxonomy Loading with Eager Loading in Laravel Source: https://github.com/aliziodev/laravel-taxonomy/blob/master/README.md Demonstrates how to use Laravel's eager loading feature (`with`) to efficiently load taxonomies associated with models, thereby reducing the number of database queries. Examples include selecting specific columns, filtering taxonomies by type, and preloading taxonomy counts for related models. ```php // Efficient loading of taxonomies with models $products = Product::with([ 'taxonomies' => function ($query) { $query->select('id', 'name', 'slug', 'type', 'meta') ->orderBy('type') ->orderBy('name'); } ])->get(); // Load specific taxonomy types only $products = Product::with([ 'taxonomies' => function ($query) { $query->whereIn('type', ['category', 'brand']); } ])->get(); // Preload taxonomy counts $categories = Taxonomy::where('type', 'category') ->withCount(['models as product_count' => function ($query) { $query->where('taxonomable_type', Product::class); }]) ->get(); ``` -------------------------------- ### Adjust Laravel Taxonomy Custom Queries for Type Constraint Source: https://github.com/aliziodev/laravel-taxonomy/blob/master/UPGRADE.md Demonstrates how to modify custom database queries that retrieve taxonomy entries. It highlights the need to include a 'type' constraint in queries, as the 'slug' is no longer globally unique. Examples show updates for direct model queries, facade usage, and leveraging the 'type' scope. ```php // Before: // Using model directly $taxonomy = Taxonomy::where('slug', 'technology')->first(); // Or using facade $taxonomy = \Aliziodev\LaravelTaxonomy\Facades\Taxonomy::findBySlug('technology'); // After: // Using model with type constraint $taxonomy = Taxonomy::where('slug', 'technology') ->where('type', TaxonomyType::Category) ->first(); // Using facade with type constraint $taxonomy = \Aliziodev\LaravelTaxonomy\Facades\Taxonomy::findBySlug('technology', TaxonomyType::Category); // Or using available scope $taxonomy = Taxonomy::type(TaxonomyType::Category) ->where('slug', 'technology') ->first(); ``` -------------------------------- ### Running Tests for Laravel Taxonomy Package Source: https://github.com/aliziodev/laravel-taxonomy/blob/master/README.md Instructions on how to execute the comprehensive test suite for the Laravel Taxonomy package using either the Composer `test` script or directly via `vendor/bin/pest`. ```bash composer test // or vendor/bin/pest ``` -------------------------------- ### Create Course and Attach Taxonomies Source: https://github.com/aliziodev/laravel-taxonomy/blob/master/docs/en/learning-management-system.md This snippet illustrates how to create a new course instance and associate it with existing taxonomies, such as 'Web Development' skill and 'Intermediate' difficulty, using the 'attachTaxonomies' method. ```php $course = Course::create([ 'title' => 'Complete Laravel Developer Course', 'description' => 'Master Laravel from basics to advanced concepts', 'duration_hours' => 40, 'price' => 99.99, ]); $course->attachTaxonomies([ $webDevelopment->id, Taxonomy::findBySlug('intermediate', 'difficulty')->id, ]); ``` -------------------------------- ### Checking for Taxonomy Existence and Finding by Slug Source: https://github.com/aliziodev/laravel-taxonomy/blob/master/README.md Provides an example of checking if a taxonomy exists by its slug using `Taxonomy::exists()` before attempting to retrieve it with `Taxonomy::findBySlug()` to prevent errors. ```php if (Taxonomy::exists('electronics')) { $taxonomy = Taxonomy::findBySlug('electronics'); } ``` -------------------------------- ### Implement Skill-Based Course Recommendations and Skill Path Browsing Source: https://github.com/aliziodev/laravel-taxonomy/blob/master/docs/en/learning-management-system.md This controller demonstrates two key functionalities: generating course recommendations for a user based on their completed courses and skills, and displaying a skill path by grouping courses related to a specific skill and its descendants by difficulty level. ```php class CourseController extends Controller { public function recommendations(User $user) { // Get user's completed courses and their skills $completedCourses = $user->enrollments() ->where('completed', true) ->with('course.taxonomies') ->get() ->pluck('course'); $userSkills = $completedCourses ->flatMap(function ($course) { return $course->taxonomiesOfType('skill'); }) ->unique('id'); // Find courses that build on user's existing skills $recommendedCourses = Course::query() ->whereNotIn('id', $completedCourses->pluck('id')) ->where(function ($query) use ($userSkills) { // Courses with related skills $query->withAnyTaxonomies($userSkills->pluck('id')) // Or courses with parent skills of user's skills ->orWhereHas('taxonomies', function ($q) use ($userSkills) { $parentSkillIds = $userSkills ->flatMap(fn($skill) => $skill->getAncestors()) ->pluck('id'); $q->whereIn('taxonomies.id', $parentSkillIds); }); }) ->with(['taxonomies']) ->limit(10) ->get(); return view('courses.recommendations', compact('recommendedCourses', 'userSkills')); } public function skillPath($skillSlug) { $skill = Taxonomy::findBySlug($skillSlug, 'skill'); if (!$skill) { abort(404); } // Get all courses for this skill and its descendants $skillIds = collect([$skill->id]) ->merge($skill->getDescendants()->pluck('id')); $courses = Course::withAnyTaxonomies($skillIds) ->with(['taxonomies' => function ($query) { $query->where('type', 'difficulty'); }]) ->get() ->groupBy(function ($course) { return $course->difficulty->name ?? 'Unknown'; }); return view('courses.skill-path', compact('skill', 'courses')); } } ``` -------------------------------- ### Service for Setting Up Tenant-Specific Default Taxonomies in Laravel Source: https://github.com/aliziodev/laravel-taxonomy/blob/master/docs/en/multi-tenant-business-application.md This PHP service class, `TenantTaxonomyService`, provides methods to initialize a tenant's default taxonomy structure. The `setupDefaultTaxonomies` method defines a hierarchical structure for departments, project types, and priorities, then iterates to create these taxonomies using the `createTaxonomyStructure` private method. This ensures each new tenant can be provisioned with a predefined, yet customizable, set of classifications. ```php class TenantTaxonomyService { public function setupDefaultTaxonomies(Tenant $tenant): void { $defaultStructure = [ 'departments' => [ 'Sales' => ['meta' => ['color' => '#007bff', 'manager_required' => true]], 'Marketing' => ['meta' => ['color' => '#28a745', 'budget_tracking' => true]], 'Engineering' => [ 'meta' => ['color' => '#6f42c1', 'technical' => true], 'children' => [ 'Frontend' => ['meta' => ['skills' => ['React', 'Vue', 'Angular']]], 'Backend' => ['meta' => ['skills' => ['Laravel', 'Node.js', 'Python']]], 'DevOps' => ['meta' => ['skills' => ['Docker', 'Kubernetes', 'AWS']]], ], ], ], 'project_types' => [ 'Internal' => ['meta' => ['billable' => false]], 'Client Work' => ['meta' => ['billable' => true, 'requires_contract' => true]], 'R&D' => ['meta' => ['billable' => false, 'innovation' => true]], ], 'priorities' => [ 'Low' => ['meta' => ['color' => '#6c757d', 'sla_days' => 30]], 'Medium' => ['meta' => ['color' => '#ffc107', 'sla_days' => 14]], 'High' => ['meta' => ['color' => '#fd7e14', 'sla_days' => 7]], 'Critical' => ['meta' => ['color' => '#dc3545', 'sla_days' => 1]], ], ]; foreach ($defaultStructure as $type => $items) { $this->createTaxonomyStructure($tenant, $type, $items); } } private function createTaxonomyStructure(Tenant $tenant, string $type, array $items, ?int $parentId = null): void { foreach ($items as $name => $config) { $taxonomy = TenantTaxonomy::create([ 'name' => $name, 'type' => $type, 'tenant_id' => $tenant->id, 'parent_id' => $parentId, 'meta' => $config['meta'] ?? [], ]); if (isset($config['children'])) { $this->createTaxonomyStructure($tenant, $type, $config['children'], $taxonomy->id); } } } } ``` -------------------------------- ### Testing: Run All PestPHP Tests Source: https://github.com/aliziodev/laravel-taxonomy/blob/master/CONTRIBUTING.md Command to execute all tests using PestPHP, the testing framework used in the project. ```bash vendor/bin/pest ``` -------------------------------- ### Run Laravel Taxonomy Database Migrations Source: https://github.com/aliziodev/laravel-taxonomy/blob/master/README.md Executes the database migrations provided by the Laravel Taxonomy package. This creates the necessary tables and schema in your database to support taxonomy management. ```bash php artisan migrate ``` -------------------------------- ### Example of Composite Unique Slug Constraint Source: https://github.com/aliziodev/laravel-taxonomy/blob/master/README.md Illustrates the new behavior (v2.3.0+) where slugs are unique per taxonomy type, not globally. This allows the same slug (e.g., 'featured') to exist for different taxonomy types (e.g., 'category' and 'tag'). ```php // This is now possible: Taxonomy::create(['name' => 'Featured', 'slug' => 'featured', 'type' => 'category']); Taxonomy::create(['name' => 'Featured', 'slug' => 'featured', 'type' => 'tag']); ``` -------------------------------- ### Rollback Laravel Taxonomy Database Migration Source: https://github.com/aliziodev/laravel-taxonomy/blob/master/UPGRADE.md Provides the 'artisan' command to revert the last batch of database migrations. This is useful for undoing the schema changes made during the upgrade process, but users are cautioned about potential data conflicts if duplicate slugs exist. ```bash php artisan migrate:rollback ``` -------------------------------- ### Basic Usage: Comprehensive Taxonomy Facade Operations Source: https://github.com/aliziodev/laravel-taxonomy/blob/master/README.md Illustrates various operations using the `Taxonomy` facade, including creating taxonomies with meta data, finding by slug, checking existence, searching, and retrieving hierarchical data in different formats (tree, flatTree, nestedTree). ```php use Aliziodev\LaravelTaxonomy\Facades\Taxonomy; use Aliziodev\LaravelTaxonomy\Enums\TaxonomyType; // Create taxonomies $category = Taxonomy::create([ 'name' => 'Books', 'type' => TaxonomyType::Category->value, 'description' => 'All kinds of books', 'meta' => [ 'icon' => 'book', 'color' => '#3498db', 'featured' => true, ], ]); // Find taxonomies $taxonomy = Taxonomy::findBySlug('books'); $exists = Taxonomy::exists('books'); $categories = Taxonomy::findByType(TaxonomyType::Category); // Search taxonomies $results = Taxonomy::search('science', TaxonomyType::Category); // Get hierarchical data $tree = Taxonomy::tree(TaxonomyType::Category); $flatTree = Taxonomy::flatTree(TaxonomyType::Category); $nestedTree = Taxonomy::getNestedTree(TaxonomyType::Category); ``` -------------------------------- ### Filter Models with Taxonomy Query Scopes Source: https://github.com/aliziodev/laravel-taxonomy/blob/master/README.md This section illustrates various query scopes provided by the Laravel Taxonomy package for filtering models. Examples include filtering by taxonomy type, specific taxonomies (any or all), taxonomy slug (with or without type), hierarchy, and depth level. ```php // Filter by taxonomy type $products = Product::withTaxonomyType(TaxonomyType::Category)->get(); // Filter by specific taxonomies $products = Product::withAnyTaxonomies([$category1, $category2])->get(); $products = Product::withAllTaxonomies([$tag1, $tag2])->get(); // Filter by taxonomy slug (any type) $products = Product::withTaxonomySlug('electronics')->get(); // Filter by taxonomy slug with specific type (recommended) $products = Product::withTaxonomySlug('electronics', TaxonomyType::Category)->get(); // Filter by hierarchy (includes descendants) $products = Product::withTaxonomyHierarchy($parentCategoryId)->get(); // Filter by depth level $products = Product::withTaxonomyAtDepth(2, TaxonomyType::Category)->get(); ``` -------------------------------- ### Querying Hierarchical Taxonomy Data in PHP Source: https://github.com/aliziodev/laravel-taxonomy/blob/master/README.md Demonstrates how to retrieve descendants, ancestors, and check hierarchical relationships using the nested set model in Laravel. It also shows methods to get a node's depth level and retrieve only root taxonomies or taxonomies at a specific depth. ```php // Get all descendants of a taxonomy (children, grandchildren, etc.) $descendants = $taxonomy->getDescendants(); // Get all ancestors of a taxonomy (parent, grandparent, etc.) $ancestors = $taxonomy->getAncestors(); // Check hierarchical relationships $isParent = $parent->isAncestorOf($child); $isChild = $child->isDescendantOf($parent); // Get the depth level $level = $taxonomy->getLevel(); // Get only root taxonomies $roots = Taxonomy::roots()->get(); // Get taxonomies at specific depth $level2 = Taxonomy::atDepth(2)->get(); ``` -------------------------------- ### Testing: Run PestPHP Tests with Coverage Report Source: https://github.com/aliziodev/laravel-taxonomy/blob/master/CONTRIBUTING.md Command to run tests and generate a code coverage report, helping identify untested areas. ```bash vendor/bin/pest --coverage ``` -------------------------------- ### Testing: Run Specific PestPHP Test File Source: https://github.com/aliziodev/laravel-taxonomy/blob/master/CONTRIBUTING.md Command to run tests from a particular file, useful for focused testing during development. ```bash vendor/bin/pest tests/Feature/TaxonomyFeatureTest.php ``` -------------------------------- ### Update Laravel Taxonomy Slug Validation Rules Source: https://github.com/aliziodev/laravel-taxonomy/blob/master/UPGRADE.md Illustrates the necessary changes to Laravel model validation rules for the 'slug' field. It shows how to transition from a simple global unique rule to a more complex rule using 'Rule::unique' with a 'where' clause, ensuring the 'slug' is unique only within its 'type'. ```php // Before (v2.x): 'slug' => 'required|string|unique:taxonomies,slug' // After (v2.3.0): 'slug' => [ 'required', 'string', Rule::unique('taxonomies')->where(function ($query) use ($type) { return $query->where('type', $type); }) ] ``` -------------------------------- ### Development Workflow: Push Changes and Create Pull Request Source: https://github.com/aliziodev/laravel-taxonomy/blob/master/CONTRIBUTING.md Git command to push the feature branch to the remote repository, preparing for a pull request. ```bash git push origin feat/your-feature-name ``` -------------------------------- ### Catching Laravel Taxonomy Package Exceptions Source: https://github.com/aliziodev/laravel-taxonomy/blob/master/README.md Shows how to implement comprehensive error handling for `MissingSlugException` and `DuplicateSlugException` when creating taxonomy entries, providing user-friendly feedback via back redirection with errors. ```php use Aliziodev\LaravelTaxonomy\Exceptions\MissingSlugException; use Aliziodev\LaravelTaxonomy\Exceptions\DuplicateSlugException; try { $taxonomy = Taxonomy::create([ 'name' => 'Test Category', 'type' => TaxonomyType::Category->value, ]); } catch (MissingSlugException $e) { // Handle missing slug error return back()->withErrors(['slug' => 'A slug is required.']); } catch (DuplicateSlugException $e) { // Handle duplicate slug error return back()->withErrors(['slug' => 'This slug already exists. Please choose another.']); } ``` -------------------------------- ### Optimize Taxonomy Loading with Eager Loading in Laravel Source: https://github.com/aliziodev/laravel-taxonomy/blob/master/README.id.md This snippet illustrates how to efficiently load taxonomies associated with models using Laravel's eager loading feature. It provides examples of selecting specific columns for performance, filtering eager-loaded taxonomies by type, and preloading taxonomy counts for related models. ```php // Loading taksonomi dengan model secara efisien $products = Product::with([ 'taxonomies' => function ($query) { $query->select('id', 'name', 'slug', 'type', 'meta') ->orderBy('type') ->orderBy('name'); } ])->get(); // Load hanya tipe taksonomi tertentu $products = Product::with([ 'taxonomies' => function ($query) { $query->whereIn('type', ['category', 'brand']); } ])->get(); // Preload jumlah taksonomi $categories = Taxonomy::where('type', 'category') ->withCount(['models as product_count' => function ($query) { $query->where('taxonomable_type', Product::class); }]) ->get(); ``` -------------------------------- ### Development Workflow: Create Feature Branch Source: https://github.com/aliziodev/laravel-taxonomy/blob/master/CONTRIBUTING.md Git command to create a new feature branch for development, following standard branching practices. ```bash git checkout -b feat/your-feature-name ``` -------------------------------- ### Verify Unique Constraint for Same Slug and Type (PHP) Source: https://github.com/aliziodev/laravel-taxonomy/blob/master/UPGRADE.md This PHP snippet illustrates an attempt to create a new taxonomy entry with a 'slug' ('technology') and 'type' (TaxonomyType::Category) that already exist in combination. This operation is expected to fail, confirming that the unique constraint on the 'slug' and 'type' pair within the same taxonomy type is correctly enforced by the system after the upgrade. ```php // This should fail Taxonomy::create([ 'name' => 'Tech', 'slug' => 'technology', // Same slug 'type' => TaxonomyType::Category // Same type ]); ``` -------------------------------- ### Create Taxonomies with Same Slug, Different Types (PHP) Source: https://github.com/aliziodev/laravel-taxonomy/blob/master/UPGRADE.md This PHP code demonstrates the creation of two taxonomy entries that share the same 'slug' ('technology') but are differentiated by their 'type' (TaxonomyType::Category and TaxonomyType::Tag). This scenario verifies that the system correctly allows multiple taxonomies with identical slugs as long as their types are distinct, as per the expected behavior after the upgrade. ```php Taxonomy::create([ 'name' => 'Technology', 'slug' => 'technology', 'type' => TaxonomyType::Category ]); Taxonomy::create([ 'name' => 'Technology', 'slug' => 'technology', 'type' => TaxonomyType::Tag ]); ``` -------------------------------- ### Set up Content Taxonomies in Laravel Source: https://github.com/aliziodev/laravel-taxonomy/blob/master/docs/en/content-management-system.md This snippet demonstrates how to create main content categories and tags using the `Taxonomy` model. It shows creating parent and child categories with custom metadata, and iterating to create multiple tags, including specific metadata for trending status and skill levels. ```php // Create main content categories $newsCategory = Taxonomy::create([ 'name' => 'News', 'type' => TaxonomyType::Category->value, 'meta' => [ 'template' => 'news-layout', 'show_date' => true, 'allow_comments' => true, ], ]); $techNews = Taxonomy::create([ 'name' => 'Technology', 'type' => TaxonomyType::Category->value, 'parent_id' => $newsCategory->id, 'meta' => [ 'featured_color' => '#007bff', 'rss_enabled' => true, ], ]); // Create content tags $tags = ['Laravel', 'PHP', 'JavaScript', 'AI', 'Machine Learning']; foreach ($tags as $tagName) { Taxonomy::create([ 'name' => $tagName, 'type' => TaxonomyType::Tag->value, 'meta' => [ 'trending' => in_array($tagName, ['AI', 'Machine Learning']), 'skill_level' => $tagName === 'Laravel' ? 'intermediate' : 'beginner', ], ]); } ``` -------------------------------- ### Optimize Laravel Taxonomy Queries and Batch Operations Source: https://github.com/aliziodev/laravel-taxonomy/blob/master/README.md This snippet demonstrates how to write efficient database queries using the Laravel Taxonomy package, specifically for retrieving products by category with eager loading of related taxonomies. It also illustrates a method for batch attaching taxonomies to multiple products, significantly improving performance for bulk operations. ```php // ✅ Good: Efficient querying with proper indexing class OptimizedTaxonomyQueries { public function getProductsByCategory(string $categorySlug): Collection { return Product::select(['id', 'name', 'price', 'slug']) ->withTaxonomy( Taxonomy::where('slug', $categorySlug) ->where('type', TaxonomyTypes::PRODUCT_CATEGORY) ->first() ) ->with(['taxonomies' => function ($query) { $query->select(['id', 'name', 'slug', 'type']) ->whereIn('type', [TaxonomyTypes::PRODUCT_TAG, 'brand']); }]) ->limit(20) ->get(); } // ✅ Good: Batch operations for better performance public function attachCategoriesInBatch(Collection $products, array $categoryIds): void { $products->chunk(100)->each(function ($chunk) use ($categoryIds) { foreach ($chunk as $product) { $product->attachTaxonomies($categoryIds); } }); } } ``` -------------------------------- ### Check for Laravel Taxonomy Slug Conflicts Before Migration Source: https://github.com/aliziodev/laravel-taxonomy/blob/master/UPGRADE.md Provides a PHP database query using Laravel's 'DB' facade to identify potential slug conflicts that might arise from the unique constraint change. It helps users pre-emptively find and resolve cases where the same slug is used across different taxonomy types before running the migration. ```php // Check for potential slug conflicts across different types $conflicts = DB::table('taxonomies') ->select('slug') ->groupBy('slug') ->havingRaw('COUNT(DISTINCT type) > 1') ->get(); if ($conflicts->isNotEmpty()) { // Handle conflicts manually or update slugs foreach ($conflicts as $conflict) { echo "Conflict found for slug: {$conflict->slug}\n"; } } ``` -------------------------------- ### Use Custom Taxonomy Types Directly in Code Source: https://github.com/aliziodev/laravel-taxonomy/blob/master/README.md Beyond configuration, custom taxonomy types can be used directly within your code. This includes creating new taxonomies with custom types, finding existing taxonomies by their custom type, checking if a model has taxonomies of a specific custom type, getting them, and filtering models based on custom taxonomy types. ```php use Aliziodev\LaravelTaxonomy\Facades\Taxonomy; // Create a taxonomy with a custom type $genre = Taxonomy::create([ 'name' => 'Science Fiction', 'type' => 'genre', // Custom type not defined in TaxonomyType enum 'description' => 'Science fiction genre', ]); // Find taxonomies by custom type $genres = Taxonomy::findByType('genre'); // Check if a model has taxonomies of a custom type $product->hasTaxonomyType('genre'); // Get taxonomies of a custom type $productGenres = $product->taxonomiesOfType('genre'); // Filter models by custom taxonomy type $products = Product::withTaxonomyType('genre')->get(); ``` -------------------------------- ### Laravel Taxonomy v2.3.0 Migration for Slug Unique Constraint Source: https://github.com/aliziodev/laravel-taxonomy/blob/master/UPGRADE.md Defines the database migration logic for 'aliziodev/laravel-taxonomy' to update the 'taxonomies' table. The 'up' method drops the old global 'slug' unique constraint and adds a new composite unique constraint on ['slug', 'type']. The 'down' method reverses these changes, restoring the previous global 'slug' uniqueness. ```php dropUnique(['slug']); // Add the new composite unique constraint $table->unique(['slug', 'type']); }); } public function down(): void { $tableNames = config('taxonomy.table_names'); $tableName = $tableNames['taxonomies'] ?? 'taxonomies'; Schema::table($tableName, function (Blueprint $table) { // Drop the composite unique constraint $table->dropUnique(['slug', 'type']); // Restore the old unique constraint on slug $table->unique(['slug']); }); } }; ``` -------------------------------- ### Develop Product Recommendation System in Laravel Source: https://github.com/aliziodev/laravel-taxonomy/blob/master/docs/en/ecommerce-product-catalog.md This PHP service provides methods for generating product recommendations. `getRelatedProducts` finds products with shared taxonomies, ordered by the number of common taxonomies. `getCrossSellProducts` identifies cheaper accessories within the same category, simulating cross-sell opportunities. It utilizes Laravel Taxonomy for efficient related product retrieval. ```php class ProductRecommendationService { public function getRelatedProducts(Product $product, int $limit = 6): Collection { $productTaxonomies = $product->taxonomies->pluck('id'); return Product::withAnyTaxonomies($productTaxonomies) ->where('id', '!=', $product->id) ->withCount(['taxonomies' => function ($query) use ($productTaxonomies) { $query->whereIn('taxonomy_id', $productTaxonomies); }]) ->orderByDesc('taxonomies_count') ->limit($limit) ->get(); } public function getCrossSellProducts(Product $product): Collection { // Get products frequently bought together $categoryIds = $product->taxonomies ->where('type', TaxonomyType::Category->value) ->pluck('id'); return Product::withAnyTaxonomies($categoryIds) ->where('id', '!=', $product->id) ->where('price', '<', $product->price * 0.5) // Cheaper accessories ->limit(4) ->get(); } } ``` -------------------------------- ### Implement Robust Validation and Error Handling for Taxonomy Creation Source: https://github.com/aliziodev/laravel-taxonomy/blob/master/README.md This example showcases a `TaxonomyService` class that incorporates comprehensive validation and error handling during the creation of new taxonomy entries. It utilizes Laravel's `Validator` for basic data integrity and includes custom logic to prevent circular references and enforce nesting depth limits, ensuring data consistency and preventing common issues. ```php class TaxonomyService { public function createWithValidation(array $data): Taxonomy { $validator = Validator::make($data, [ 'name' => 'required|string|max:255', 'type' => 'required|string|max:50', 'parent_id' => 'nullable|exists:taxonomies,id', 'meta' => 'nullable|array', ]); if ($validator->fails()) { throw new ValidationException($validator); } // Check for circular references if (isset($data['parent_id'])) { $this->validateNoCircularReference($data['parent_id'], $data); } return Taxonomy::create($validator->validated()); } private function validateNoCircularReference(int $parentId, array $data): void { $parent = Taxonomy::find($parentId); if (!$parent) { throw new InvalidArgumentException('Parent taxonomy not found'); } // Check if parent type matches (optional business rule) if ($parent->type !== $data['type']) { throw new InvalidArgumentException('Parent must be of the same type'); } // Prevent deep nesting (optional business rule) if ($parent->depth >= 5) { throw new InvalidArgumentException('Maximum nesting depth exceeded'); } } } ```