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.
%i identifier placeholder of $wpdb->prepare())Go to LUKDEV Custom Data Tables in the admin menu. You need the manage_options capability.
Hero title becomes hero_title. Keys must be unique within a structure.Deleting a structure also deletes all its rows.
Each type is listed with its settings, the value stored in the database and the value returned by the API.
text: no settings. Stored: string. API: string.textarea: no settings. Stored: string. API: string.wysiwyg: no settings. Stored: HTML (wp_kses_post). API: string.number: no settings. Stored: numeric string. API: string.email: no settings. Stored: string. API: string.url: no settings. Stored: string. API: string.boolean: no settings. Stored: "1" / "0". API: true / false.select: settings: options, default. Stored: option value. API: string.radio: settings: options, default. Stored: option value. API: string.checkbox: settings: options, defaults. Stored: list of option values. API: array of strings.image: no settings. Stored: attachment ID. API: image object or null.color_picker: settings: default, opacity, return format (string / array). Stored: #rrggbb or rgba(r,g,b,a). API: string, or { red, green, blue, alpha }.date_picker: settings: display format, return format, first day of week. Stored: Ymd. API: date in the return format.post_object: settings: post types, multiple. Stored: post ID or list of IDs. API: post object, null, or array of posts.relationship: settings: post types, filters (search / post type / taxonomy), max. Stored: list of post IDs. API: array of posts.link: no settings. Stored: { page, url, title, target }. API: { title, url, target } or null.repeater: settings: sub-fields. Stored: list of items. API: array of objects.Notes:
text.d/m/Y.textarea.Both endpoints are public (no authentication) and read-only.
GET /wp-json/ldcdt/v1/dataLists all structures.
[
{
"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.
{
"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_object, relationship): { id, type, slug, title, url, date }, where date is an ISO 8601 GMT date.{ title, url, target }, where target is "" or "_blank".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>
– To add a field type, register it in ldcdt_field_types(). Then handle its settings in ldcdt_sanitize_fields(), its value in ldcdt_sanitize_value() and ldcdt_format_value(), and its inputs in the admin partials and admin/js/admin.js.
– Everything uses the ldcdt prefix: functions (ldcdt_), constants (LDCDT_), tables, options, the REST namespace, CSS classes and JS. Sites upgraded from Custom Headless Data (old chd / chdata prefixes) have their tables and option renamed automatically. Admin form actions are ldcdt_save_structure, ldcdt_delete_structure, ldcdt_save_row, ldcdt_delete_row and ldcdt_move_row. The post search AJAX action is ldcdt_search_posts.