LUKDEV Custom Data Tables Wordpress Plugin - Rating, Reviews, Demo & Download
Plugin Description
A WordPress plugin for defining custom data structures (sets of fields) and managing rows of data for them in the admin. The data is exposed through a public, read-only REST API, so a headless front end can use it.
Think of it as a small, standalone alternative to ACF options pages and repeaters. Each structure is a list of rows, stored in its own database tables instead of post meta.
Author: LUKDEV. Text domain: lukdev-custom-data-tables.
Requirements
- WordPress 6.2+ (queries use the
%iidentifier placeholder of$wpdb->prepare()) - PHP 7.4+
Usage
Go to LUKDEV Custom Data Tables in the admin menu. You need the manage_options capability.
- Create a structure. Give it a name and, optionally, a slug (the name is used when the slug is empty). Then add fields. A field’s key is generated from its label, for example
Hero titlebecomeshero_title. Keys must be unique within a structure. - Add rows. After you save the structure, the rows editor opens. Rows are saved one at a time, can be moved up or down, and can be deleted.
- Fetch the data from the REST API (see below).
Deleting a structure also deletes all its rows.
Field types
Type
Settings
Stored value
API value
text
none
string
string
textarea
none
string
string
wysiwyg
none
HTML (wp_kses_post)
string
number
none
numeric string
string
email
none
string
string
url
none
string
string
boolean
none
"1" / "0"
true / false
select
options, default
option value
string
radio
options, default
option value
string
checkbox
options, defaults
list of option values
array of strings
image
none
attachment ID
image object or null
color_picker
default, opacity, return format (string / array)
#rrggbb or rgba(r,g,b,a)
string, or { red, green, blue, alpha }
date_picker
display format, return format, first day of week
Ymd
date in the return format
post_object
post types, multiple
post ID or list of IDs
post object, null, or array of posts
relationship
post types, filters (search / post type / taxonomy), max
list of post IDs
array of posts
link
none
{ page, url, title, target }
{ title, url, target } or null
repeater
sub-fields
list of items
array of objects
Notes:
- Options: an option without a value uses its label as the value, and the other way round.
- Repeaters can’t be nested. A repeater added as a sub-field is saved as
text. - Post object and relationship fields accept any public post type (except attachments) when no post types are selected. The API returns published posts only. Drafts and private posts picked in the admin are left out.
- Link fields point to either a page or a custom URL. The page wins if both are set. The page’s title is used when the link text is empty.
- Date picker fields use PHP date formats. The default for both display and return is
d/m/Y. - Changing a field’s type or settings keeps saved data where possible. For example, a single post object becomes a list when multiple is turned on, and a select value becomes a one-item checkbox list. Fields saved before field types existed are treated as
textarea.
REST API
Both endpoints are public (no authentication) and read-only.
GET /wp-json/ldcdt/v1/data
Lists all structures.
`json
[
{
“name”: “Team”,
“slug”: “team”,
“fields”: [
{ “key”: “name”, “label”: “Name”, “type”: “text” },
{ “key”: “photo”, “label”: “Photo”, “type”: “image” }
],
“url”: “https://example.com/wp-json/ldcdt/v1/data/team”
}
]
`
GET /wp-json/ldcdt/v1/data/{slug}
Returns one structure with its rows, in the order set in the admin. Each item has an id plus one property per field key. Returns 404 (ldcdt_not_found) for an unknown slug.
`json
{
“name”: “Team”,
“slug”: “team”,
“fields”: [ … ],
“items”: [
{
“id”: 1,
“name”: “Jane Doe”,
“photo”: {
“id”: 42,
“url”: “https://example.com/app/uploads/jane.jpg”,
“alt”: “”,
“width”: 1200,
“height”: 800,
“sizes”: {
“thumbnail”: { “url”: “…”, “width”: 150, “height”: 150 }
}
}
}
]
}
`
Shapes of the other object values:
- Post (
post_object,relationship):{ id, type, slug, title, url, date }, wheredateis an ISO 8601 GMT date. - Link:
{ title, url, target }, wheretargetis""or"_blank".
Project structure
`
lukdev-custom-data-tables.php Plugin header, constants, bootstrap
includes/
install.php Table names, creation and upgrades
fields.php Field types, sanitization and API formatting
data.php Reading structures and rows
rest-api.php REST routes (ldcdt/v1)
admin/
admin.php Menu, assets, page router, notices
handlers.php admin-post.php form handlers, post search AJAX
partials/ List, structure builder and rows editor screens
css/, js/ Admin assets
vendor/select2/ Select2 4.1.0 (MIT)
<h3>Extending</h3>ldcdt_field_types()
- To add a field type, register it in. Then handle its settings inldcdt_sanitize_fields(), its value inldcdt_sanitize_value()andldcdt_format_value(), and its inputs in the admin partials andadmin/js/admin.js.ldcdt
- Everything uses theprefix: functions (ldcdt_), constants (LDCDT_), tables, options, the REST namespace, CSS classes and JS. Sites upgraded from Custom Headless Data (oldchd/chdataprefixes) have their tables and option renamed automatically. Admin form actions areldcdt_save_structure,ldcdt_delete_structure,ldcdt_save_row,ldcdt_delete_rowandldcdt_move_row. The post search AJAX action isldcdt_search_posts`.




