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
- Installation
- Configuration
- Architecture
- Database Schema
- Multi-Tenant Model
- Consent Types & Values
- Usage Examples
- API Endpoint (ConsentApiControllerTrait)
- Running Migrations
- Running Tests
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\RecordsORM) 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 (
tenanttype 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
ConsentApiControllerTraitfor HTTP controllers - ✅
ConsentCheckerhelper 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 statemkt_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 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
与 marktic/cmp 相关的其它包
同方向 / 同关键字的高下载量 PHP Composer 包推荐,方便对比选型:
Add a configurable cookie consent banner to the website.
Laravel Plans is a package for SaaS apps that need management over plans, features, subscriptions, events for plans or limited, countable features.
Use Klaro! Consent Manager in Contao CMS
Asaas.com PHP API v3 Wrapper
Adaptaçao Asaas.com PHP API Wrapper para PHP 5.6
Laravel Tenant Multi-Self-Hosted-DB connections with Migration tools package for Laravel 5.1+
统计信息
- 总下载量: 30
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 0
- 点击次数: 31
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2026-03-15