marktic/cmp 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

marktic/cmp

Composer 安装命令:

composer require marktic/cmp

包简介

Server-side Consent Mode management system for SaaS applications. Records, audits and queries user consent for Google Consent Mode categories in multi-tenant environments.

README 文档

README

A modern, framework-agnostic PHP 8.3+ Composer package for server-side Consent Mode management in multi-tenant SaaS applications.

Designed to record, audit, and query user consent for Google Consent Mode categories (analytics, ads, etc.) with a clean feature-based architecture built on the bytic/orm, bytic/actions and bytic/migrations ecosystem.

Table of Contents

Features

  • ✅ PHP 8.3+ with strict types
  • ✅ PSR-4 autoloading, PSR-12 coding standard
  • ✅ Feature-based architecture (Base, Consents, ConsentLogs, Utility, database migrations)
  • ✅ Built on bytic/orm (Nip\Records ORM) for model persistence
  • bytic/actions as the base for all action classes
  • bytic/migrations (Phinx) for database schema migrations
  • ✅ Framework-agnostic core
  • ✅ Multi-tenant support (tenant type string + tenant_id)
  • ✅ Session-based and user-based consent tracking
  • ✅ Consent state table (mkt_cmp_consents)
  • ✅ Full audit log table (mkt_cmp_consent_logs)
  • ✅ All 7 Google Consent Mode v2 categories
  • ✅ Reusable ConsentApiControllerTrait for HTTP controllers
  • ConsentChecker helper for querying permissions
  • ✅ PHPUnit test suite

Installation

composer require marktic/cmp

Requirements

Dependency Version
PHP ^8.3
bytic/orm ^2.0
bytic/actions ^1.0
bytic/migrations ~0.13
bytic/package-base ^1.0

Configuration

Register the service provider in your application bootstrap:

use Marktic\Cmp\CmpServiceProvider;

// Laravel / similar
$app->register(CmpServiceProvider::class);

Enabling Migrations

By default, migrations are not run automatically. Enable them in your config/mkt_cmp.php:

return [
    'database' => [
        'migrations' => true,
        'connection' => env('DB_CONNECTION', 'default'),
    ],
    'tables' => [
        'consents' => 'mkt_cmp_consents',
        'consent_logs' => 'mkt_cmp_consent_logs',
    ],
];

Architecture

The package follows a feature-based structure consistent with other packages in the marktic organization. Models extend Nip\Records\Record (bytic/orm), actions extend Bytic\Actions\Action, and migrations are Phinx files.

src/
├── Base/                              # Shared cross-cutting types
│   ├── Tenant.php                     # Lightweight tenant DTO
│   └── Models/
│       ├── CmpRecord.php              # Base Record (extends Nip\Records\Record)
│       ├── CmpRecords.php             # Base RecordManager
│       ├── HasTenant/
│       │   ├── HasTenantRecord.php    # Adds $tenant + $tenant_id to records
│       │   └── HasTenantRepository.php # morphTo Tenant relation
│       └── Traits/
│           ├── BaseRepositoryTrait.php
│           └── HasDatabaseConnectionTrait.php
│
├── Consents/                          # Feature: mkt_cmp_consents table
│   ├── Enums/
│   │   ├── ConsentType.php
│   │   ├── ConsentStatus.php
│   │   └── ConsentSource.php
│   ├── Models/
│   │   ├── Consent.php                # ORM Record
│   │   ├── ConsentTrait.php           # Column getters
│   │   ├── Consents.php               # ORM RecordManager
│   │   └── ConsentsTrait.php          # Query methods
│   └── Actions/
│       ├── AbstractAction.php         # Extends Bytic\Actions\Action
│       ├── RecordConsent.php
│       ├── GetConsent.php
│       └── GetAllConsentsForSession.php
│
├── ConsentLogs/                       # Feature: mkt_cmp_consent_logs table
│   ├── Models/
│   │   ├── ConsentLog.php             # ORM Record
│   │   ├── ConsentLogTrait.php
│   │   ├── ConsentLogs.php            # ORM RecordManager
│   │   └── ConsentLogsTrait.php
│   └── Actions/
│       └── AbstractAction.php
│
├── CmpServiceProvider.php             # Registers migrations path
│
├── Utility/
│   ├── CmpModels.php                  # ModelFinder (resolves Consents / ConsentLogs)
│   ├── PackageConfig.php
│   └── ConsentChecker.php
│
└── Http/
    └── Trait/
        └── ConsentApiControllerTrait.php

database/
└── migrations/
    ├── 20260311000001_cmp_consents.php
    └── 20260311000002_cmp_consent_logs.php

Database Schema

Overview

Table Purpose
mkt_cmp_consents Current consent state per session/type
mkt_cmp_consent_logs Immutable audit log of all consent changes

mkt_cmp_consents

Stores the current consent state. One row per tenant + session + consent type.

Column Type Description
id BIGINT auto-increment Primary key
tenant VARCHAR(100) Morphic type, e.g. organization, project
tenant_id BIGINT UNSIGNED Numeric tenant identifier
session_id VARCHAR(255) Browser/cookie session identifier
user_id VARCHAR(255) nullable Authenticated user identifier
consent_type VARCHAR(100) One of the 7 consent type values
consent_value VARCHAR(10) granted or denied
created_at TIMESTAMP Record creation time
updated_at TIMESTAMP Last update time

Unique constraint: (tenant, tenant_id, session_id, consent_type)

mkt_cmp_consent_logs

Stores every consent change for auditing. Rows are append-only.

Column Type Description
id BIGINT auto-increment Primary key
consent_id BIGINT nullable Reference to mkt_cmp_consents.id
tenant VARCHAR(100) Morphic tenant type
tenant_id BIGINT UNSIGNED Tenant ID
session_id VARCHAR(255) Session identifier
user_id VARCHAR(255) nullable User identifier
payload TEXT JSON with consent_type, previous_status, new_status
source VARCHAR(20) api, frontend, import, or admin
ip_address VARCHAR(45) nullable Client IP
user_agent TEXT nullable Browser user-agent
created_at TIMESTAMP Log entry creation time

Multi-Tenant Model

The package is designed for multi-tenant SaaS applications. Every consent record and log entry is scoped to a tenant using a morphic pair:

  • tenant (string) — the morphic type name of the owning entity (e.g. organization, project)
  • tenant_id (int) — the numeric ID of the owning entity
// Records scoped to organization/10
$consents->findAllBySession('organization', 10, $sessionId);

// Records scoped to project/44
$consents->findAllBySession('project', 44, $sessionId);

The Base\Tenant value object is also available as a lightweight DTO to group these two values when passing them through application layers:

use Marktic\Cmp\Base\Tenant;

$tenant = new Tenant('organization', 10);
$consents->findAllBySession($tenant->type, $tenant->id, $sessionId);

Consent Types & Values

Types (ConsentType enum)

Value Enum Case
ad_storage ConsentType::AD_STORAGE
analytics_storage ConsentType::ANALYTICS_STORAGE
ad_user_data ConsentType::AD_USER_DATA
ad_personalization ConsentType::AD_PERSONALIZATION
functionality_storage ConsentType::FUNCTIONALITY_STORAGE
security_storage ConsentType::SECURITY_STORAGE
personalization_storage ConsentType::PERSONALIZATION_STORAGE

Status (ConsentStatus enum)

Value Enum Case
granted ConsentStatus::GRANTED
denied ConsentStatus::DENIED

Source (ConsentSource enum)

Value When to use
api Consent received via REST API
frontend Consent received directly from frontend
import Bulk data import
admin Set by an admin user

Usage Examples

Setup

Resolve the managers through CmpModels or via dependency injection:

use Marktic\Cmp\Consents\Actions\RecordConsent;
use Marktic\Cmp\Utility\CmpModels;

$consents    = CmpModels::consents();
$consentLogs = CmpModels::consentLogs();
$record      = new RecordConsent();

Recording Consent

use Marktic\Cmp\Consents\Enums\ConsentSource;

$record->handle(
    tenant:    'organization',
    tenantId:  10,
    sessionId: 'sess_abc123',
    userId:    'user_42',          // null for anonymous
    consents: [
        'ad_storage'              => 'granted',
        'analytics_storage'       => 'granted',
        'ad_user_data'            => 'denied',
        'ad_personalization'      => 'denied',
        'functionality_storage'   => 'granted',
        'security_storage'        => 'granted',
        'personalization_storage' => 'denied',
    ],
    source:    ConsentSource::FRONTEND,
    ipAddress: '192.0.2.1',
    userAgent: 'Mozilla/5.0 ...',
);

When called again with the same session, only changed values are updated and logged. Unchanged values are silently ignored.

Querying Consent

use Marktic\Cmp\Consents\Actions\GetConsent;
use Marktic\Cmp\Consents\Actions\GetAllConsentsForSession;
use Marktic\Cmp\Consents\Enums\ConsentType;

// Get a single consent
$getConsent = new GetConsent();
$consent = $getConsent->handle('organization', 10, 'sess_abc123', ConsentType::ANALYTICS_STORAGE);

if ($consent !== null && $consent->isGranted()) {
    // analytics is allowed
}

// Get all consents for a session
$getAll = new GetAllConsentsForSession();
$consents = $getAll->handle('organization', 10, 'sess_abc123');

Using ConsentChecker

ConsentChecker provides a more expressive API for checking permissions in application code.

use Marktic\Cmp\Consents\Enums\ConsentType;
use Marktic\Cmp\Utility\CmpModels;
use Marktic\Cmp\Utility\ConsentChecker;

$checker = new ConsentChecker(CmpModels::consents(), 'organization', 10, 'sess_abc123');

// Enum-based check
$checker->isGranted(ConsentType::ANALYTICS_STORAGE); // true / false
$checker->isDenied(ConsentType::AD_STORAGE);         // true / false

// String-based check
$checker->hasConsent('analytics_storage');            // true / false

// Get all recorded consents as a map
$all = $checker->getAll();
// ['analytics_storage' => 'granted', 'ad_storage' => 'denied', ...]

API Endpoint (ConsentApiControllerTrait)

The ConsentApiControllerTrait provides a ready-to-use handleConsentUpdate() method. Mix it into your framework controller and implement the abstract bridge methods.

Endpoint specification

POST /consent
Content-Type: application/json
X-Tenant-Type: organization
X-Tenant-Id:   10

{
  "consent": {
    "ad_storage":              "granted",
    "analytics_storage":       "granted",
    "ad_user_data":            "denied",
    "ad_personalization":      "denied",
    "functionality_storage":   "granted",
    "security_storage":        "granted",
    "personalization_storage": "denied"
  }
}

Framework integration example (pseudo-framework)

use Marktic\Cmp\Consents\Actions\RecordConsent;
use Marktic\Cmp\Http\Trait\ConsentApiControllerTrait;

class ConsentController
{
    use ConsentApiControllerTrait;

    public function __construct(
        private readonly RecordConsent $recordConsent,
        private readonly Request $request,
    ) {}

    public function update(): JsonResponse
    {
        $result = $this->handleConsentUpdate($this->recordConsent);
        $statusCode = $result['status'] === 'ok' ? 200 : 422;
        return new JsonResponse($result, $statusCode);
    }

    protected function resolveTenantType(): ?string
    {
        return $this->request->header('X-Tenant-Type');
    }

    protected function resolveTenantId(): ?int
    {
        $raw = $this->request->header('X-Tenant-Id');
        return $raw !== null ? (int) $raw : null;
    }

    protected function resolveSessionId(): ?string
    {
        return $this->request->cookie('session_id')
            ?? $this->request->header('X-Session-Id');
    }

    protected function resolveUserId(): ?string { return auth()->id(); }

    protected function resolveIpAddress(): ?string { return $this->request->ip(); }

    protected function resolveUserAgent(): ?string { return $this->request->userAgent(); }

    protected function resolveConsents(): array { return $this->request->input('consent', []); }
}

Running Migrations

Migrations are standard Phinx files located in database/migrations/. When using a framework that integrates with CmpServiceProvider, migrations run automatically if enabled in config.

To run manually via Phinx CLI:

vendor/bin/phinx migrate --configuration=phinx.php

The two tables created are:

  • mkt_cmp_consents — current consent state
  • mkt_cmp_consent_logs — audit log

Running Tests

composer install
vendor/bin/phpunit

License

MIT License. See LICENSE for details.

marktic/cmp 适用场景与选型建议

marktic/cmp 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 30 次下载、GitHub Stars 达 0, 最近一次更新时间为 2026 年 03 月 15 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「saas」 「multi-tenant」 「consent」 「gdpr」 「consent-mode」 「google-consent-mode」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

我们在过去多个企业项目中使用过 marktic/cmp 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 marktic/cmp 我们能提供哪些服务?
定制开发 / 二次开发

基于 marktic/cmp 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 30
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 31
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2026-03-15