growtech/acf-core-php
Composer 安装命令:
composer require growtech/acf-core-php
包简介
Advanced Custom Fields for Core PHP — dynamic custom field management for non-WordPress PHP applications.
README 文档
README
A lightweight, dependency-free custom field engine for vanilla PHP applications — the flexibility of WordPress ACF, without WordPress.
Requirements
- PHP 7.4+ (tested on 8.3)
- MySQL or MariaDB
pdo_mysqlextension
Installation
Option A — no Composer:
require_once '/path/to/acf-core-php/autoload.php';
Option B — with Composer, add to your composer.json:
"repositories": [{ "type": "path", "url": "path/to/acf-core-php" }], "require": { "yourvendor/acf-core-php": "*" }
Then load the schema once:
mysql -u youruser -p your_database < database/schema.sql
This creates three tables: acf_field_groups, acf_fields, acf_field_values.
Quick Start
use ACF\ACF; use ACF\Exceptions\ValidationException; // 1. Bootstrap (once per request) ACF::configure([ 'host' => 'localhost', 'dbname' => 'my_app', 'username' => 'db_user', 'password' => 'db_password', ], [ 'base_path' => __DIR__ . '/public/uploads/acf', // where files are written 'base_url' => '/uploads/acf', // public URL prefix ]); // 2. One-time setup (run from a migration/seed script) $groupId = ACF::createFieldGroup(['title' => 'Product Details', 'entity_type' => 'product']); ACF::addField($groupId, ['label' => 'Price', 'name' => 'price', 'type' => 'number', 'required' => true]); // 3. Render a form echo ACF::renderForm('product', $productId, ['wrap_form' => true, 'form_attrs' => ['action' => '/save']]); // 4. Save submitted data try { ACF::save('product', $productId, $_POST, $_FILES); } catch (ValidationException $e) { $errors = $e->getErrors(); // ['field_name' => ['message', ...]] } // 5. Read values back $values = ACF::getValues('product', $productId); // raw values $display = ACF::getValues('product', $productId, true); // template-ready (formatted dates, <img> tags, etc.)
See examples/full_integration_example.php for a complete worked example (bootstrap, setup, form, save handler, display template).
Supported Field Types
| Type | type string |
Notes |
|---|---|---|
| Text | text |
validation_rules: min_length, max_length, pattern |
| Textarea | textarea |
options.rows, validation_rules: min_length, max_length |
| Number | number |
validation_rules: min, max, step |
email |
Validated with FILTER_VALIDATE_EMAIL |
|
| URL | url |
Validated with FILTER_VALIDATE_URL |
| Select | select |
options.choices (assoc array), options.multiple (bool) |
| Checkbox group | checkbox |
options.choices; always stores/returns an array |
| Radio | radio |
options.choices |
| File upload | file |
options.accept (e.g. .pdf,.docx), options.subdir, options.max_size (bytes) |
| Image upload | image |
Same options as file; validates actual image content, not just extension |
| Date | date |
Stored as Y-m-d; validation_rules.min_date/max_date; options.display_format (PHP date format) |
| Rich text | richtext |
Plain <textarea class="acf-richtext"> — attach your own WYSIWYG JS (TinyMCE/Quill/etc). HTML is sanitized against an allow-list on save. |
Adding a Custom Field Type
use ACF\FieldTypes\AbstractFieldType; class ColorField extends AbstractFieldType { public function render(array $field, $value = null): string { /* ... */ } public function validate(array $field, $value): array { /* ... */ } public function sanitize(array $field, $value) { /* ... */ } public function display(array $field, $value) { /* ... */ } } ACF::registerFieldType('color', ColorField::class);
See examples/CustomColorField.php for a full working example.
Core API Reference
Setup
ACF::configure(array $dbConfig, ?array $uploadConfig = null)ACF::registerFieldType(string $type, string $className)
Field groups & fields
ACF::createFieldGroup(array $data): intACF::addField(int $groupId, array $data): intACF::getFields(string $entityType, ?string $groupSlug = null): arrayACF::updateFieldGroup() / deleteFieldGroup() / updateField() / deleteField()
Forms
ACF::renderForm(string $entityType, ?int $entityId, array $options = []): stringoptions:group_slug,errors,wrap_form,form_attrs
Validation & saving
ACF::validate(string $entityType, array $postData, array $files = []): array— error array, empty if validACF::save(string $entityType, int $entityId, array $postData, array $files = []): bool— throwsValidationExceptionon invalid data
Reading values
ACF::getValue(string $entityType, int $entityId, string $fieldName, bool $forDisplay = false)ACF::getValues(string $entityType, int $entityId, bool $forDisplay = false): arrayACF::deleteEntityValues(string $entityType, int $entityId): bool
Notes on File Uploads
- Stored values are relative paths (e.g.
products/cover-64f2a1.png), built fromUploadConfig'sbase_path/base_url. - Re-saving a form without selecting a new file preserves the existing stored file — it won't be wiped.
display()output forfile/imagefields returns ready-to-print<a>/<img>tags.
Styling
assets/acf.css has minimal default styles using plain class names (.acf-field, .acf-errors, etc.) — safe to override or ignore entirely if you're bringing your own design system.
Project Structure
acf-core-php/
├── autoload.php # zero-dependency PSR-4-style autoloader
├── composer.json # optional, if you prefer Composer's autoloader
├── database/schema.sql # 3-table schema: field_groups, fields, field_values
├── src/
│ ├── ACF.php # main facade — the class you'll actually call
│ ├── Core/ # Database, FieldGroup, Field, FieldValue, UploadConfig
│ ├── FieldTypes/ # one class per field type + the factory/registry
│ ├── Validation/Validator.php
│ ├── Render/FormRenderer.php
│ └── Exceptions/
├── examples/
│ ├── full_integration_example.php
│ └── CustomColorField.php # custom field type example
└── assets/acf.css
统计信息
- 总下载量: 0
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 0
- 点击次数: 3
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2026-06-19