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

Products Category Laravel Package

baks-dev/products-category

BaksDev Product Category — модуль категорий продукции для PHP 8.4+. Установка через Composer, установка ассетов и ресурсов, настройка директории для обложек категорий, миграции Doctrine, тесты PHPUnit (group: products-category).

View on GitHub
Deep Wiki
Context7

Implementation Patterns

1. Entity-Centric Development

Pattern: Leverage the ProductCategory entity as the primary abstraction.

  • CRUD Operations:
    // Create
    $category = new \BaksDev\ProductsCategoryBundle\Entity\ProductCategory();
    $category->setName('Electronics');
    $category->setSlug('electronics');
    $category->setDescription('All electronic devices');
    $entityManager->persist($category);
    $entityManager->flush();
    
    // Read (with hierarchy)
    $categories = $entityManager->getRepository(ProductCategory::class)
        ->findBy([], ['parent' => 'ASC']); // Assuming parent-child relationship
    
    // Update
    $category->setCoverImage('new_cover.jpg');
    $entityManager->flush();
    
    // Delete (soft/hard)
    $category->setIsDeleted(true); // If soft delete is implemented
    $entityManager->flush();
    
  • Validation: Use Symfony Validator constraints (e.g., @Assert\NotBlank on name).

2. Cover Image Handling

Pattern: Integrate with the product_category_cover upload directory.

  • Upload Logic:
    use Symfony\Component\HttpFoundation\File\UploadedFile;
    
    public function uploadCover(UploadedFile $file, ProductCategory $category)
    {
        $path = $file->getRealPath();
        $filename = uniqid() . '.' . $file->guessExtension();
        $destination = $this->getCoverPath($filename);
    
        $file->move($destination, $filename);
        $category->setCoverImage($filename);
        $entityManager->flush();
    
        return $destination;
    }
    
    private function getCoverPath(string $filename): string
    {
        return public_path('upload/product_category_cover/' . $filename);
    }
    
  • Storage Alternatives:
    • Replace local storage with AWS S3 or DigitalOcean Spaces by extending the CoverUploader service.
    • Bind a custom StorageInterface to override default behavior:
      $this->app->bind(\BaksDev\ProductsCategoryBundle\Service\StorageInterface::class, function () {
          return new \App\Service\S3CoverStorage();
      });
      

3. Hierarchical Data Traversal

Pattern: Recursively fetch categories with their children.

  • Repository Method:
    // In ProductCategoryRepository
    public function findWithChildren(ProductCategory $parent = null, int $depth = 0)
    {
        $query = $this->createQueryBuilder('c')
            ->where('c.parent = :parent')
            ->setParameter('parent', $parent);
    
        if ($depth > 0) {
            $children = $query->getQuery()->getResult();
            foreach ($children as $child) {
                $child->setChildren($this->findWithChildren($child, $depth - 1));
            }
            return $children;
        }
        return $query->getQuery()->getResult();
    }
    
  • Usage:
    $rootCategories = $repository->findWithChildren(null, 2); // 2 levels deep
    

4. Console Command Integration

Pattern: Extend or use built-in commands for bulk operations.

  • Custom Command Example:
    # Create a new command to bulk-import categories
    php bin/console app:import-categories path/to/csv.csv
    
    // In src/Command/ImportCategoriesCommand.php
    class ImportCategoriesCommand extends Command
    {
        protected function execute(InputInterface $input, OutputInterface $output)
        {
            $csvPath = $input->getArgument('path');
            $categories = $this->csvImporter->import($csvPath);
    
            foreach ($categories as $data) {
                $category = new ProductCategory();
                $category->setName($data['name']);
                $category->setSlug($data['slug']);
                $entityManager->persist($category);
            }
            $entityManager->flush();
            $output->writeln('Imported ' . count($categories) . ' categories.');
        }
    }
    

5. Event-Driven Extensions

Pattern: Subscribe to package events for custom logic.

  • Example Events (if implemented):
    • CategoryCreatedEvent
    • CoverUploadedEvent
    • CategoryDeletedEvent
  • Listener Example:
    // In src/EventListener/CategoryCreatedListener.php
    class CategoryCreatedListener
    {
        public function onCategoryCreated(CategoryCreatedEvent $event)
        {
            $category = $event->getCategory();
            // Send notification, log analytics, etc.
            Log::info("New category created: {$category->getName()}");
        }
    }
    
  • Register in services.yaml:
    services:
        App\EventListener\CategoryCreatedListener:
            tags:
                - { name: kernel.event_listener, event: category.created, method: onCategoryCreated }
    

6. API Integration (Optional)

Pattern: Expose categories via Laravel API resources.

  • Resource:
    namespace App\Http\Resources;
    
    use BaksDev\ProductsCategoryBundle\Entity\ProductCategory;
    use Illuminate\Http\Resources\Json\JsonResource;
    
    class ProductCategoryResource extends JsonResource
    {
        public function toArray($request)
        {
            return [
                'id' => $this->id,
                'name' => $this->name,
                'slug' => $this->slug,
                'cover_url' => $this->getCoverUrl(),
                'children' => ProductCategoryResource::collection($this->children),
            ];
        }
    
        private function getCoverUrl()
        {
            return asset("upload/product_category_cover/{$this->coverImage}");
        }
    }
    
  • Controller:
    use App\Http\Resources\ProductCategoryResource;
    
    public function index()
    {
        $categories = $this->categoryRepository->findWithChildren(null, 2);
        return ProductCategoryResource::collection($categories);
    }
    

7. Testing Strategies

Pattern: Write tests for core functionality using the products-category test group.

  • Unit Test Example:
    public function testCategoryCreation()
    {
        $category = new ProductCategory();
        $category->setName('Test');
        $category->setSlug('test');
    
        $entityManager = $this->getEntityManager();
        $entityManager->persist($category);
        $entityManager->flush();
    
        $this->assertDatabaseHas('product_categories', [
            'name' => 'Test',
            'slug' => 'test',
        ]);
    }
    
  • Run Tests:
    php bin/phpunit --group=products-category
    

8. Frontend Integration (Blade)

Pattern: Render categories in Blade templates.

  • Template Example:
    @foreach($categories as $category)
        <div class="category">
            <h3>{{ $category->name }}</h3>
            @if($category->coverImage)
                <img src="{{ asset("upload/product_category_cover/{$category->coverImage}") }}" alt="{{ $category->name }}">
            @endif
            @if(count($category->children) > 0)
                <ul>
                    @include('partials.category-list', ['categories' => $category->children])
                </ul>
            @endif
        </div>
    @endforeach
    

9. Migration Customization

Pattern: Extend or override migrations if needed.

  • Example: Add a custom column to the product_categories table.
    // In src/Migrations/VersionYYYYMMDDHHMMSS.php
    public function up()
    {
        $this->addSql("ALTER TABLE product_categories ADD meta_data JSON NULL");
    }
    
  • Run Custom Migration:
    php bin/console doctrine:migrations:execute 'ALTER TABLE product_categories ADD meta_data JSON NULL'
    

10. Service Provider Extensions

Pattern: Bind custom services to override or extend package behavior.

  • Example: Replace the default cover uploader.
    // In AppServiceProvider
    public function register()
    {
        $this->app->bind(
            \BaksDev\ProductsCategoryBundle\Service\CoverUploaderInterface::class,
            \App\Service\CustomCoverUploader::class
        );
    }
    

Gotchas and Tips

Pitfalls

  1. Migration Conflicts

    • Issue: Running doctrine:migrations:migrate may fail if the package’s tables already exist.
    • Fix: Check for existing tables before migrating or manually merge schemas:
      php bin/console doctrine:schema:update --dump-sql
      
    • Tip: Use --complete flag to force updates:
      php bin/console doctrine:migrations:migrate --complete
      
  2. File Permissions

    • Issue: Uploads to public/upload/product_category_cover may fail with Permission denied.
    • Fix: Ensure the directory has 773 permissions and the web server user (e.g., `www
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