Laravel custom field module - add custom display fields to models
qmrp/customfield is a Laravel package for laravel custom field module - add custom display fields to models.
It currently has 0 GitHub stars and 1 downloads on Packagist.
Install it with composer require qmrp/customfield.
Discover more Laravel packages by qmrp
or browse all Laravel packages to compare alternatives.
Last updated
为模型添加自定义显示字段的 Laravel 扩展包。
composer require qmrp/customfield
php artisan vendor:publish --provider="Qmrp\CustomField\CustomFieldServiceProvider"
php artisan migrate
use Qmrp\CustomField\Traits\HasCustomFields;
class Product extends Model
{
use HasCustomFields;
}
use Qmrp\CustomField\Facades\CustomField;
CustomField::saveModuleFields('product', [
[
'key' => 'total_price',
'name' => '总价',
'type' => 'computed',
'config' => [
'callback' => function ($model) {
return $model->price * $model->quantity;
}
],
'sort_order' => 1,
'is_active' => true
],
[
'key' => 'category_name',
'name' => '分类名称',
'type' => 'relation',
'config' => [
'relation' => 'category',
'display_field' => 'name'
],
'sort_order' => 2,
'is_active' => true
],
[
'key' => 'formatted_price',
'name' => '格式化价格',
'type' => 'formatted',
'config' => [
'source_field' => 'price',
'format' => 'currency',
'decimals' => 2
],
'sort_order' => 3,
'is_active' => true
]
]);
$products = Product::withCustomFields()->get();
foreach ($products as $product) {
echo $product->getCustomField('total_price');
echo $product->getCustomField('category_name');
echo $product->getCustomField('formatted_price');
}
直接显示模型中的字段值。
[
'key' => 'status_text',
'name' => '状态文本',
'type' => 'basic',
'config' => [
'source_field' => 'status',
'default' => '未知'
]
]
通过回调函数计算字段值。
[
'key' => 'total_amount',
'name' => '总金额',
'type' => 'computed',
'config' => [
'callback' => function ($model) {
return $model->subtotal + $model->tax - $model->discount;
},
'default' => 0
]
]
显示关联模型的字段值。
[
'key' => 'user_name',
'name' => '用户名',
'type' => 'relation',
'config' => [
'relation' => 'user',
'display_field' => 'name',
'multiple' => false,
'separator' => ', '
]
]
对字段值进行格式化。
[
'key' => 'created_date',
'name' => '创建日期',
'type' => 'formatted',
'config' => [
'source_field' => 'created_at',
'format' => 'date',
'date_format' => 'Y-m-d'
]
]
支持的格式类型:
date: 日期格式化datetime: 日期时间格式化currency: 货币格式化number: 数字格式化percentage: 百分比格式化phone: 电话号码格式化uppercase: 转大写lowercase: 转小写ucfirst: 首字母大写truncate: 文本截断根据条件返回不同的值。
[
'key' => 'order_status',
'name' => '订单状态',
'type' => 'conditional',
'config' => [
'default' => '未知',
'conditions' => [
[
'field' => 'status',
'operator' => '==',
'expected' => 'pending',
'value' => function ($model) {
return '待处理';
}
],
[
'field' => 'status',
'operator' => '==',
'expected' => 'completed',
'value' => function ($model) {
return '已完成';
}
]
]
]
]
支持的条件操作符:
==, ===: 等于!=, !==: 不等于>, <, >=, <=: 比较运算符in, not_in: 包含/不包含contains: 包含字符串starts_with, ends_with: 开头/结尾null, not_null: 为空/不为空empty, not_empty: 为空/不为空callback: 自定义回调<x-customfield::table
:module="'product'"
:data="$products"
:user-id="auth()->id()"
/>
<x-customfield::value
:model="$product"
field-key="total_price"
module="product"
/>
<x-customfield::form
module="product"
:model="$product"
:user-id="auth()->id()"
/>
GET /api/customfield/fields?module=product&user_id=1
POST /api/customfield/fields
Content-Type: application/json
{
"module": "product",
"fields": [
{
"key": "total_price",
"name": "总价",
"type": "computed",
"config": {
"callback": "..."
}
}
]
}
PUT /api/customfield/fields/{module}/{key}
Content-Type: application/json
{
"name": "总价(更新)",
"is_active": true
}
DELETE /api/customfield/fields/{module}/{key}
# 获取用户设置
GET /api/customfield/user-settings?module=product&user_id=1
# 保存用户设置
POST /api/customfield/user-settings
Content-Type: application/json
{
"module": "product",
"user_id": 1,
"settings": [
{
"custom_module_field_id": 1,
"sort_order": 1,
"is_show": true,
"is_fixed": false
}
]
}
# 获取模板列表
GET /api/customfield/templates?module=product&user_id=1
# 创建模板
POST /api/customfield/templates
Content-Type: application/json
{
"name": "产品默认模板",
"module": "product",
"fields": [...],
"is_public": true,
"created_by": 1
}
# 应用模板
POST /api/customfield/templates/apply
Content-Type: application/json
{
"module": "product",
"template_id": 1
}
# 复制模板
POST /api/customfield/templates/duplicate
Content-Type: application/json
{
"template_id": 1,
"new_name": "产品模板副本",
"created_by": 1
}
# 删除模板
DELETE /api/customfield/templates/{templateId}
# 导出字段配置
POST /api/customfield/export
Content-Type: application/json
{
"module": "product"
}
# 导入字段配置
POST /api/customfield/import
Content-Type: application/json
{
"data": {
"module": "product",
"fields": [...]
}
}
use Qmrp\CustomField\Services\CustomFieldPermissionService;
$permissionService = app(CustomFieldPermissionService::class);
// 授予用户查看权限
$permissionService->grantPermission($fieldId, 'view', $userId);
// 授予角色编辑权限
$permissionService->grantPermission($fieldId, 'edit', null, $roleId);
// 撤销权限
$permissionService->revokePermission($fieldId, 'view', $userId);
// 检查权限
$hasPermission = $permissionService->checkPermission($fieldId, 'view', $userId);
$accessibleFields = $permissionService->getAccessibleFields('product', $userId, 'view');
php artisan customfield:install
php artisan customfield:export product --output=product_fields.json
php artisan customfield:import product_fields.json
use Qmrp\CustomField\Contracts\FieldTypeInterface;
use Qmrp\CustomField\Types\AbstractFieldType;
class CustomFieldType extends AbstractFieldType implements FieldTypeInterface
{
public function __construct()
{
parent::__construct('custom', '自定义类型');
}
public function getValue($model, array $config)
{
// 自定义逻辑
return $model->{$config['field']} ?? $config['default'];
}
public function validate(array $config): bool
{
return isset($config['field']);
}
}
// 注册自定义类型
use Qmrp\CustomField\Types\FieldTypeRegistry;
FieldTypeRegistry::register('custom', new CustomFieldType());
use Qmrp\CustomField\Facades\CustomField;
// 创建模板
$template = CustomField::createTemplate(
'产品标准模板',
'product',
[
[
'key' => 'total_price',
'name' => '总价',
'type' => 'computed',
'config' => [...]
]
],
true,
1
);
// 应用模板
CustomField::applyTemplate('product', $template->id);
// 复制模板
$newTemplate = CustomField::duplicateTemplate($template->id, '产品模板副本', 2);
use Qmrp\CustomField\Config\FieldConfigManager;
$configManager = app(FieldConfigManager::class);
// 设置缓存时间(秒)
$configManager->setCacheTtl(7200);
在 config/customfield.php 中配置:
return [
'cache' => [
'enabled' => true,
'ttl' => 3600,
],
'permissions' => [
'enabled' => true,
'default_permissions' => [
'view' => true,
'edit' => true,
'delete' => false,
],
],
'middleware' => [
'auth' => 'auth:sanctum',
'permission' => \Qmrp\CustomField\Http\Middleware\CustomFieldPermission::class,
],
'routes' => [
'prefix' => 'api/customfield',
'middleware' => 'api',
],
];
存储自定义字段定义
存储用户的字段显示设置
存储字段模板
存储字段权限配置
A: 只需在模型中使用 HasCustomFields Trait,然后创建字段配置即可。
A: 不会,字段值在访问时才计算,并且支持缓存。建议对频繁访问的字段使用缓存。
A: 可以,使用 ModelWithCustomFieldsResource 或在查询时使用 withCustomFields()。
A: 使用 CustomFieldPermissionService 设置字段级别的权限,并在中间件中验证。
MIT License