PHPackages                             tourze/wechat-official-account-menu-bundle - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. tourze/wechat-official-account-menu-bundle

ActiveSymfony-bundle

tourze/wechat-official-account-menu-bundle
==========================================

微信公众号-自定义菜单

0.0.1(11mo ago)00MITPHPPHP ^8.1CI failing

Since Jun 14Pushed 4mo ago1 watchersCompare

[ Source](https://github.com/tourze/wechat-official-account-menu-bundle)[ Packagist](https://packagist.org/packages/tourze/wechat-official-account-menu-bundle)[ RSS](/packages/tourze-wechat-official-account-menu-bundle/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (1)Dependencies (25)Versions (2)Used By (0)

WeChat Official Account Menu Bundle
===================================

[](#wechat-official-account-menu-bundle)

\[[![PHP Version](https://camo.githubusercontent.com/6518db1335bf20fdff07253dc6d6d0cec955b5fb6a8ef1382ac6d73687ecc07f/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f7068702d253345253344382e312d626c7565)](https://camo.githubusercontent.com/6518db1335bf20fdff07253dc6d6d0cec955b5fb6a8ef1382ac6d73687ecc07f/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f7068702d253345253344382e312d626c7565)\] () [![License](https://camo.githubusercontent.com/f8df3091bbe1149f398a5369b2c39e896766f9f6efba3477c63e9b4aa940ef14/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d677265656e)](LICENSE)[![Symfony](https://camo.githubusercontent.com/fc75a7c07101af05017d4efb0922fead1ed21166d4c8c68ab2b736a92f27fcd7/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f73796d666f6e792d253545362e342d627269676874677265656e)](https://symfony.com/)[![Build Status](https://camo.githubusercontent.com/07c5a0015c097e0dfbb44d4220df0eed6a623d83eceb02ac299fe96b8e4e1a73/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f746f75727a652f7068702d6d6f6e6f7265706f2f63692e796d6c3f6272616e63683d6d6173746572)](https://github.com/tourze/php-monorepo/actions)[![Code Coverage](https://camo.githubusercontent.com/9cb168340a6d5a1bdda8e16dafe8eed3d60f1441986fb63de17bff84ee6a18f0/68747470733a2f2f696d672e736869656c64732e696f2f636f6465636f762f632f6769746875622f746f75727a652f7068702d6d6f6e6f7265706f)](https://codecov.io/gh/tourze/php-monorepo)

[English](README.md) | [中文](README.zh-CN.md)

A comprehensive WeChat Official Account custom menu management bundle for Symfony, providing complete menu management functionality with version control and visual editing support.

Table of Contents
-----------------

[](#table-of-contents)

- [Features](#features)
- [Installation](#installation)
- [Requirements](#requirements)
- [Dependencies](#dependencies)
- [Usage](#usage)
- [Advanced Usage](#advanced-usage)
- [Data Models](#data-models)
- [Events](#events)
- [Configuration](#configuration)
- [Security](#security)
- [Limitations](#limitations)
- [Error Handling](#error-handling)
- [Roadmap](#roadmap)
- [License](#license)
- [References](#references)

Features
--------

[](#features)

- 📋 **Menu Management**: Create, edit, delete, sort, and copy menus
- 📦 **Version Control**: Menu versioning, publishing, rollback, and comparison
- ✅ **Menu Validation**: Automatic validation against WeChat restrictions
- 🔄 **WeChat API Integration**: Automatic menu synchronization to WeChat servers
- 🎯 **Personalized Menus**: Support for creating and managing personalized menus
- 🌲 **Tree Structure**: Support for up to two-level menu hierarchy
- 🚀 **Performance Optimization**: Enable/disable menus, batch operations

Installation
------------

[](#installation)

```
composer require tourze/wechat-official-account-menu-bundle
```

Requirements
------------

[](#requirements)

- PHP 8.1 or higher
- Symfony 6.4 or higher
- Doctrine ORM
- Valid WeChat Official Account

Dependencies
------------

[](#dependencies)

This bundle requires the following packages:

- `symfony/framework-bundle` - Core Symfony framework
- `doctrine/doctrine-bundle` - Database abstraction layer
- `tourze/wechat-official-account-bundle` - WeChat API integration
- `symfony/validator` - Data validation
- `symfony/serializer` - Object serialization

Usage
-----

[](#usage)

### 1. Menu Management

[](#1-menu-management)

#### Creating Menus

[](#creating-menus)

```
use WechatOfficialAccountMenuBundle\Service\MenuService;

// Create top-level menu
$menuData = [
    'name' => 'Products',
    'type' => MenuType::VIEW,
    'url' => 'https://example.com/products',
    'position' => 0,
    'enabled' => true,
];
$menuButton = $menuService->createMenuButton($account, $menuData);

// Create sub-menu
$subMenuData = [
    'name' => 'Product Details',
    'type' => MenuType::VIEW,
    'url' => 'https://example.com/product/detail',
    'parent' => $parentMenuButton,
];
$subMenuButton = $menuService->createMenuButton($account, $subMenuData);
```

#### Updating Menus

[](#updating-menus)

```
$menuService->updateMenuButton($menuButton, [
    'name' => 'New Products',
    'url' => 'https://example.com/new-products',
]);
```

#### Menu Sorting

[](#menu-sorting)

```
$positions = [
    'button_id_1' => 0,
    'button_id_2' => 1,
    'button_id_3' => 2,
];
$menuService->updateMenuPositions($positions);
```

### 2. Version Management

[](#2-version-management)

#### Creating Versions

[](#creating-versions)

```
use WechatOfficialAccountMenuBundle\Service\MenuVersionService;

// Create version from current menu
$version = $menuVersionService->createVersion(
    $account,
    '2024 Spring Festival Menu'
);

// Create from existing version
$newVersion = $menuVersionService->createVersion(
    $account,
    'Adjusted from Spring Festival version',
    $existingVersion
);
```

#### Publishing Versions

[](#publishing-versions)

```
try {
    $menuVersionService->publishVersion($version);
    echo "Menu published successfully!";
} catch (MenuVersionException $e) {
    echo "Publishing failed: " . $e->getMessage();
}
```

#### Version Rollback

[](#version-rollback)

```
$rollbackVersion = $menuVersionService->rollbackToVersion($oldVersion);
```

#### Version Comparison

[](#version-comparison)

```
$changes = $menuVersionService->compareVersions($version1, $version2);
// Returns: added, removed, modified
```

### 3. API Endpoints

[](#3-api-endpoints)

All endpoints return JSON format data.

#### Menu Version API

[](#menu-version-api)

- `GET /admin/menu/version/{id}/menus` - Get version menus
- `POST /admin/menu/version/{id}/menu` - Create menu in version
- `PUT /admin/menu/version/{id}/menu/{menuId}` - Update menu in version
- `DELETE /admin/menu/version/{id}/menu/{menuId}` - Delete menu from version
- `POST /admin/menu/version/{id}/positions` - Update menu positions
- `POST /admin/menu/version/{id}/from-current` - Create version from current menu

### 4. Menu Types

[](#4-menu-types)

Supported menu types (MenuType):

- `NONE` - No action (for parent menus)
- `VIEW` - Jump to URL
- `CLICK` - Click push event
- `MINI_PROGRAM` - Mini Program
- `SCAN_CODE_PUSH` - Scan code push event
- `SCAN_CODE_WAIT_MSG` - Scan code with prompt
- `PIC_SYS_PHOTO` - System photo
- `PIC_PHOTO_ALBUM` - Photo album
- `PIC_WEIXIN` - WeChat album
- `LOCATION_SELECT` - Send location

### 5. Visual Editor Integration

[](#5-visual-editor-integration)

This package provides complete data interface support for frontend visual editors, including:

- Tree menu structure data
- Drag-and-drop sorting support
- Real-time preview
- Version management interface
- Menu validation prompts

Advanced Usage
--------------

[](#advanced-usage)

### Personalized Menus

[](#personalized-menus)

Create conditional menus based on user attributes:

```
use WechatOfficialAccountMenuBundle\Service\WechatMenuApiService;

// Create personalized menu for specific user groups
$personalizedMenu = [
    'button' => $menuButtons,
    'matchrule' => [
        'tag_id' => '101',  // User tag ID
        'sex' => '1',       // Gender: 1=Male, 2=Female
        'country' => 'CN',  // Country
        'province' => 'Guangdong',  // Province
        'city' => 'Guangzhou',      // City
        'client_platform_type' => '1', // Platform: 1=iOS, 2=Android, 3=Others
        'language' => 'zh_CN'       // Language
    ]
];

$wechatMenuApiService->addConditionalMenu($account, $personalizedMenu);
```

### Batch Operations

[](#batch-operations)

Efficiently manage multiple menus:

```
// Batch create menus
$menuBatchData = [
    ['name' => 'Menu 1', 'type' => MenuType::VIEW, 'url' => 'https://example.com/1'],
    ['name' => 'Menu 2', 'type' => MenuType::VIEW, 'url' => 'https://example.com/2'],
    ['name' => 'Menu 3', 'type' => MenuType::CLICK, 'key' => 'MENU_3_KEY'],
];

foreach ($menuBatchData as $index => $data) {
    $data['position'] = $index;
    $menuService->createMenuButton($account, $data);
}

// Batch enable/disable menus
$menuService->batchUpdateStatus($menuIds, true); // Enable all
$menuService->batchUpdateStatus($menuIds, false); // Disable all
```

### Menu Analytics and Monitoring

[](#menu-analytics-and-monitoring)

Track menu performance:

```
// Get menu click statistics (requires custom implementation)
$stats = $menuService->getMenuClickStats($account, $startDate, $endDate);

// Monitor menu synchronization status
$syncStatus = $wechatMenuApiService->getCurrentMenuInfo($account);
if ($syncStatus['is_menu_open'] === 1) {
    echo "Menu is enabled on WeChat";
}
```

### Error Recovery

[](#error-recovery)

Handle failed operations gracefully:

```
use WechatOfficialAccountMenuBundle\Exception\WechatApiException;

try {
    $menuVersionService->publishVersion($version);
} catch (WechatApiException $e) {
    // Log the error
    $logger->error('Menu publish failed', [
        'error_code' => $e->getErrorCode(),
        'error_msg' => $e->getMessage(),
        'version_id' => $version->getId()
    ]);

    // Attempt recovery
    if ($e->getErrorCode() === 48001) { // API unauthorized
        // Refresh access token and retry
        $accessTokenService->refreshToken($account);
        $menuVersionService->publishVersion($version);
    }
}
```

Data Models
-----------

[](#data-models)

### MenuButton (Menu Button)

[](#menubutton-menu-button)

- Supports tree structure (up to two levels)
- Includes sorting and enable/disable status
- Automatic menu structure validation

### MenuVersion (Menu Version)

[](#menuversion-menu-version)

- Auto-generated version numbers
- Status: draft, published, archived
- Saves menu snapshots
- Records publishing history

### MenuButtonVersion (Versioned Menu Button)

[](#menubuttonversion-versioned-menu-button)

- Associated with specific versions
- Maintains original button ID for comparison

Events
------

[](#events)

- `MenuVersionCreatedEvent` - Triggered when version is created
- `MenuVersionPublishedEvent` - Triggered when version is published

Configuration
-------------

[](#configuration)

Configure in `config/packages/wechat_official_account_menu.yaml`:

```
# No special configuration needed currently, all services are auto-registered
```

Security
--------

[](#security)

### Access Control

[](#access-control)

- Always validate user permissions before menu operations
- Implement proper role-based access control for menu management
- Use CSRF protection for all menu modification forms

### Data Validation

[](#data-validation)

- All input data is validated using Symfony Validator
- Menu structures are validated against WeChat API requirements
- URL validation prevents malicious redirects

### WeChat API Security

[](#wechat-api-security)

- Store WeChat access tokens securely
- Implement rate limiting for API calls
- Use HTTPS for all WeChat API communications

### Recommended Practices

[](#recommended-practices)

```
// Always validate account ownership
if ($menu->getAccount()->getId() !== $currentUserAccountId) {
    throw new AccessDeniedException('Insufficient permissions');
}

// Validate URLs before setting
if (!filter_var($url, FILTER_VALIDATE_URL)) {
    throw new InvalidArgumentException('Invalid URL format');
}
```

Limitations
-----------

[](#limitations)

According to WeChat official documentation:

- Maximum 3 top-level menus
- Maximum 5 sub-menus per top-level menu
- Menu name maximum 60 characters
- Key value maximum 128 characters
- URL maximum 1024 characters

Error Handling
--------------

[](#error-handling)

```
use WechatOfficialAccountMenuBundle\Exception\MenuValidationException;
use WechatOfficialAccountMenuBundle\Exception\MenuVersionException;
use WechatOfficialAccountMenuBundle\Exception\WechatApiException;

try {
    // Menu operations
} catch (MenuValidationException $e) {
    // Menu validation failed
} catch (MenuVersionException $e) {
    // Version operation failed
} catch (WechatApiException $e) {
    // WeChat API call failed
    $errorCode = $e->getErrorCode();
}
```

Roadmap
-------

[](#roadmap)

- Support for media material menus
- Support for rich media message menus
- Batch import/export functionality
- Menu usage statistics
- More personalized menu conditions

Contributing
------------

[](#contributing)

We welcome contributions to this project! Here's how you can help:

### Reporting Issues

[](#reporting-issues)

- Use the [GitHub issue tracker](https://github.com/tourze/php-monorepo/issues) to report bugs
- Include as much detail as possible (PHP version, Symfony version, error messages)
- Provide a minimal code example that reproduces the issue

### Contributing Code

[](#contributing-code)

- Fork the repository and create a feature branch
- Follow the existing code style and conventions
- Write tests for new functionality
- Ensure all tests pass before submitting a PR
- Update documentation if needed

### Code Standards

[](#code-standards)

- Follow PSR-12 coding standards
- Use PHP 8.1+ features where appropriate
- Maintain backward compatibility when possible
- Add type declarations for all method parameters and return values

### Testing

[](#testing)

- All new features must include unit tests
- Integration tests are required for services and repositories
- Maintain test coverage above 80%

License
-------

[](#license)

This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.

References
----------

[](#references)

- \[WeChat Official Documentation - Custom Menu Creation\] ([https://developers.weixin.qq.com/doc/offiaccount/Custom\_Menus/Creating\_Custom-Defined\_Menu.html](https://developers.weixin.qq.com/doc/offiaccount/Custom_Menus/Creating_Custom-Defined_Menu.html))
- \[WeChat Official Documentation - Personalized Menu Interface\] ([https://developers.weixin.qq.com/doc/offiaccount/Custom\_Menus/Personalized\_menu\_interface.html](https://developers.weixin.qq.com/doc/offiaccount/Custom_Menus/Personalized_menu_interface.html))
- \[WeChat Official Documentation - Get Custom Menu Configuration\] ([https://developers.weixin.qq.com/doc/offiaccount/Custom\_Menus/Getting\_Custom\_Menu\_Configurations.html](https://developers.weixin.qq.com/doc/offiaccount/Custom_Menus/Getting_Custom_Menu_Configurations.html))

###  Health Score

28

—

LowBetter than 54% of packages

Maintenance64

Regular maintenance activity

Popularity0

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity35

Early-stage or recently created project

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

332d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/e354fdb316da535dfa8ba2e9193a473c403b6bc6fb9170778d1dc50e304c6e9d?d=identicon)[tourze](/maintainers/tourze)

---

Top Contributors

[![tourze](https://avatars.githubusercontent.com/u/13899502?v=4)](https://github.com/tourze "tourze (3 commits)")

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Type Coverage Yes

### Embed Badge

![Health badge](/badges/tourze-wechat-official-account-menu-bundle/health.svg)

```
[![Health](https://phpackages.com/badges/tourze-wechat-official-account-menu-bundle/health.svg)](https://phpackages.com/packages/tourze-wechat-official-account-menu-bundle)
```

###  Alternatives

[sylius/sylius

E-Commerce platform for PHP, based on Symfony framework.

8.4k5.6M651](/packages/sylius-sylius)[sulu/sulu

Core framework that implements the functionality of the Sulu content management system

1.3k1.3M152](/packages/sulu-sulu)[contao/core-bundle

Contao Open Source CMS

1231.6M2.4k](/packages/contao-core-bundle)[ec-cube/ec-cube

EC-CUBE EC open platform.

78527.0k1](/packages/ec-cube-ec-cube)[prestashop/prestashop

PrestaShop is an Open Source e-commerce platform, committed to providing the best shopping cart experience for both merchants and customers.

9.0k15.4k](/packages/prestashop-prestashop)[open-dxp/opendxp

Content &amp; Product Management Framework (CMS/PIM)

7310.3k29](/packages/open-dxp-opendxp)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
