tourze/product-keyword-bundle

商品关键词管理系统,提供关键词分类和商品关联功能

Installs: 0

Dependents: 0

Suggesters: 0

Security: 0

Stars: 0

Watchers: 0

Forks: 0

Open Issues: 0

Type:symfony-bundle

pkg:composer/tourze/product-keyword-bundle


README

English | 中文

Latest Version Total Downloads PHP Version License Build Status Code Coverage

A Symfony Bundle for managing product keywords, supporting product search and keyword categorization.

Table of Contents

Core Features

  • Keyword Management: Create, edit, and delete product keywords
  • Keyword Categorization: Support for keyword category management
  • Weight System: Support for weight settings for both keywords and product-keyword associations
  • Keyword Search: Find related products based on keywords, sorted by weight
  • EasyAdmin Integration: Complete backend management interface
  • Recommendation System: Support for keyword recommendation marking

Installation

composer require tourze/product-keyword-bundle

Configuration

Register the Bundle in config/bundles.php:

<?php

return [
    // ...
    ProductKeywordBundle\ProductKeywordBundle::class => ['all' => true],
];

Core Entities

Keyword

- id: Unique ID generated by Snowflake algorithm
- keyword: Keyword text (max 100 characters, unique)
- category: Keyword category (optional)
- weight: Weight value (default 1.0)
- thumb: Thumbnail (optional)
- description: Description (optional)
- valid: Is valid (default false)
- recommend: Is recommended (default false)

KeywordCategory

- id: Unique ID generated by Snowflake algorithm
- name: Category name
- description: Category description

ProductKeyword

- id: Unique ID generated by Snowflake algorithm
- keyword: Associated keyword
- spuId: SPU ID
- weight: Association weight (default 1.0)
- source: Source of the keyword (default 'manual')

Usage

1. Keyword Search Service

use ProductKeywordBundle\Service\KeywordSearchService;

public function __construct(
    private KeywordSearchService $keywordSearchService
) {}

// Find products by single keyword
$products = $this->keywordSearchService->findProductsByKeyword('phone');

// Find products by multiple keywords
$products = $this->keywordSearchService->findProductsByKeywords(['phone', 'apple']);

// Return format:
// [
//     ['productId' => 123, 'weight' => 2.5],
//     ['productId' => 456, 'weight' => 1.8],
// ]

2. Repository Services

use ProductKeywordBundle\Repository\KeywordRepository;
use ProductKeywordBundle\Repository\KeywordCategoryRepository;
use ProductKeywordBundle\Repository\ProductKeywordRepository;

// Find valid keyword
$keyword = $keywordRepository->findByKeyword('phone');

// Find multiple valid keywords by names
$keywords = $keywordRepository->findValidKeywordsByNames(['phone', 'apple']);

// Find recommended keywords
$recommendKeywords = $keywordRepository->findRecommendedKeywords();

3. EasyAdmin Backend Management

The Bundle automatically provides the following management interfaces:

  • ProductKeywordKeywordCrudController: Keyword management
  • ProductKeywordKeywordCategoryCrudController: Keyword category management
  • ProductKeywordProductKeywordCrudController: Product-keyword association management

Advanced Usage

Custom Keyword Filtering

use ProductKeywordBundle\Repository\KeywordRepository;

public function getFilteredKeywords(
    KeywordRepository $keywordRepository,
    ?string $category = null,
    ?float $minWeight = null
): array {
    $qb = $keywordRepository->createQueryBuilder('k')
        ->where('k.valid = :valid')
        ->setParameter('valid', true);
    
    if ($category !== null) {
        $qb->andWhere('k.category = :category')
           ->setParameter('category', $category);
    }
    
    if ($minWeight !== null) {
        $qb->andWhere('k.weight >= :minWeight')
           ->setParameter('minWeight', $minWeight);
    }
    
    return $qb->getQuery()->getResult();
}

Batch Product-Keyword Association

use ProductKeywordBundle\Entity\ProductKeyword;
use ProductKeywordBundle\Repository\KeywordRepository;
use Doctrine\ORM\EntityManagerInterface;

public function batchAssociateKeywords(
    EntityManagerInterface $em,
    KeywordRepository $keywordRepository,
    string $spuId,
    array $keywordNames,
    string $source = 'auto'
): void {
    $keywords = $keywordRepository->findValidKeywordsByNames($keywordNames);
    
    foreach ($keywords as $keyword) {
        $productKeyword = new ProductKeyword();
        $productKeyword->setSpuId($spuId)
                      ->setKeyword($keyword)
                      ->setSource($source)
                      ->setWeight($keyword->getWeight());
        
        $em->persist($productKeyword);
    }
    
    $em->flush();
}

Custom Search with Filters

use ProductKeywordBundle\Service\KeywordSearchService;

public function searchWithFilters(
    KeywordSearchService $searchService,
    array $keywords,
    ?string $source = null,
    ?float $minWeight = null
): array {
    $results = $searchService->findProductsByKeywords($keywords);
    
    if ($source !== null || $minWeight !== null) {
        return array_filter($results, function($result) use ($source, $minWeight) {
            if ($source !== null && $result['source'] !== $source) {
                return false;
            }
            if ($minWeight !== null && $result['weight'] < $minWeight) {
                return false;
            }
            return true;
        });
    }
    
    return $results;
}

Database Schema

-- Keywords table
CREATE TABLE product_keyword (
    id BIGINT PRIMARY KEY COMMENT 'Snowflake ID',
    keyword VARCHAR(100) UNIQUE NOT NULL COMMENT 'Keyword',
    category_id BIGINT NULL COMMENT 'Category ID',
    weight FLOAT DEFAULT 1.0 COMMENT 'Weight value',
    thumb VARCHAR(255) NULL COMMENT 'Thumbnail',
    description TEXT NULL COMMENT 'Description',
    valid BOOLEAN DEFAULT 0 COMMENT 'Valid',
    recommend BOOLEAN DEFAULT 0 COMMENT 'Recommend',
    created_at DATETIME COMMENT 'Created at',
    updated_at DATETIME COMMENT 'Updated at',
    created_by VARCHAR(255) COMMENT 'Created by',
    updated_by VARCHAR(255) COMMENT 'Updated by'
);

-- Keyword categories table
CREATE TABLE product_keyword_category (
    id BIGINT PRIMARY KEY COMMENT 'Snowflake ID',
    name VARCHAR(100) NOT NULL COMMENT 'Category name',
    description TEXT NULL COMMENT 'Category description',
    created_at DATETIME COMMENT 'Created at',
    updated_at DATETIME COMMENT 'Updated at'
);

-- Product-keyword associations table
CREATE TABLE product_keyword_relation (
    id BIGINT PRIMARY KEY COMMENT 'Snowflake ID',
    keyword_id BIGINT NOT NULL COMMENT 'Keyword ID',
    spu_id VARCHAR(255) NOT NULL COMMENT 'SPU ID',
    weight FLOAT DEFAULT 1.0 COMMENT 'Association weight',
    source VARCHAR(20) DEFAULT 'manual' COMMENT 'Source',
    created_at DATETIME COMMENT 'Created at',
    updated_at DATETIME COMMENT 'Updated at',
    created_by VARCHAR(255) COMMENT 'Created by',
    updated_by VARCHAR(255) COMMENT 'Updated by'
);

Weight Calculation

Final weight calculation formula for search:

Final Weight = Keyword Weight × Product-Keyword Association Weight

Technical Features

  • Snowflake Algorithm ID: Uses Snowflake algorithm for distributed unique IDs
  • Timestamp Tracking: Automatically records creation and update times
  • User Tracking: Automatically records creator and updater
  • Index Optimization: Key fields have database indexes added
  • Data Validation: Uses Symfony Validator for data validation
  • Array Conversion: Supports API, Admin, Plain multiple array output formats

Requirements

  • PHP 8.1+
  • Symfony 6.4+
  • Doctrine ORM 3.0+
  • EasyAdmin Bundle 4+

Extension Suggestions

  1. Cache Optimization: Integrate Redis to cache popular keyword query results
  2. Search Engine: Combine with Elasticsearch for more powerful full-text search
  3. Statistics Analysis: Add keyword search statistics functionality
  4. Auto-complete: Implement search auto-complete based on keyword data
  5. Synonym Support: Extend synonym matching functionality

Contributing

Please see our contribution guidelines for details on how to contribute to this project.

License

The MIT License (MIT). Please see License File for more information.