Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Meta Box Laravel Package

rilwis/meta-box

Meta Box is a powerful WordPress framework for creating custom fields, meta boxes, and settings pages without the hassle. Build custom post types, taxonomies, and user profiles with a clean API and 40+ field types, all developer-friendly and performance-optimized for production sites.

Deep Wiki
Context7

Getting Started

Meta Box is a WordPress plugin, not a plain Composer library, so treat it as a runtime dependency of the site rather than something you require into an application bootstrapper.

Install (pick one):

  • WP-CLI: wp plugin install meta-box --activate
  • Composer with composer/installers and an installer-path of wp-content/plugins/{$name}, then composer require rilwis/meta-box. You still have to activate it in WP; Composer only puts the files in place.
  • Bundled inside a theme/plugin (require_once __DIR__ . '/vendor/meta-box/meta-box.php';) if you cannot control the plugin stack — but you then own updates and conflict handling.

Where to look first:

  • meta-box/inc/fields/ — one class per field type; the fastest way to understand what a field actually stores.
  • meta-box/inc/meta-box.php — the field-group schema (id, title, post_types, context, priority, fields, validation, include/exclude).
  • docs.metabox.io — the field-type reference and the "Meta Box Builder" extension, which lets you click together a group and export it as PHP.

First use case — add a subtitle to posts and print it in the theme:

// functions.php or a small site plugin
add_filter( 'rwmb_meta_boxes', function ( $meta_boxes ) {
    $meta_boxes[] = [
        'id'         => 'post_extras',
        'title'      => __( 'Post Extras', 'mytheme' ),
        'post_types' => [ 'post' ],
        'context'    => 'normal',
        'priority'   => 'high',
        'fields'     => [
            [
                'id'   => 'subtitle',
                'name' => __( 'Subtitle', 'mytheme' ),
                'type' => 'text',
                'desc' => __( 'Shown under the post title.', 'mytheme' ),
            ],
        ],
    ];
    return $meta_boxes;
} );
// single.php
$subtitle = rwmb_meta( 'subtitle', [ 'post_id' => get_the_ID() ] );
if ( $subtitle ) {
    printf( '<h2 class="subtitle">%s</h2>', esc_html( $subtitle ) );
}

That is the whole loop: register a group, read a value, escape it.

Implementation Patterns

Keep field groups as data, not markup. Every group is an array passed through rwmb_meta_boxes. Put one file per group in a meta-boxes/ directory and require them from a bootstrap file; it keeps the config diffable and reviewable, and avoids a 600-line functions.php.

Three read helpers, three jobs:

  • rwmb_meta( $id, $args ) — get the raw/semantic value. $args accepts post_id (and size, limit for media fields).
  • rwmb_get_value( $id, $args ) — same, but a bit more explicit about the current object.
  • rwmb_the_value( $id, $args ) — echoes ready-made output (<img> for image fields, links for file fields). Use it for "just show it" cases, rwmb_meta() when you need your own markup.

Repeatable content is the highest-leverage feature. 'clone' => true turns any field into an array; add 'sort_clone' => true for drag-ordering and 'max_clone' to cap it:

[
    'id'         => 'facts',
    'name'       => 'Facts',
    'type'       => 'text',
    'clone'      => true,
    'sort_clone' => true,
]
foreach ( (array) rwmb_meta( 'facts' ) as $fact ) {
    echo '<li>' . esc_html( $fact ) . '</li>';
}

Media fields (image, image_advanced, file_advanced) return attachment data. For a grid of thumbnails:

$images = rwmb_meta( 'gallery', [ 'size' => 'medium' ] );
foreach ( $images as $image ) {
    printf( '<img src="%s" alt="%s">', esc_url( $image['url'] ), esc_attr( $image['alt'] ) );
}

Use rwmb_the_value( 'gallery', [ 'size' => 'medium' ] ) when you want the plugin's <img> markup and no per-image logic.

Data lives in normal post meta. The field id is the meta key, so get_post_meta( $post_id, 'subtitle', true ), REST exposure, WP_Query meta queries, and migrations all work exactly as you expect. Cloneable/multiple fields store one serialized array under a single key. This is the main reason Meta Box is low-risk: there is no proprietary storage layer to escape from.

Conditional display uses include/exclude callbacks in the group config, e.g. only render a "book details" group when a book_type taxonomy term matches. For intra-form show/hide driven by another field's value, that is the separate Conditional Logic extension.

Frontend authoring is the MB Frontend Submission extension ([rwmb_frontend_form id="post_extras" post_fields="title,content"]), which handles nonce, validation, media uploads, and post creation. Do not hand-roll a frontend form around the field config unless you are prepared to enqueue the plugin's media/date/color scripts yourself.

Object types beyond posts — terms, users, comments, settings pages — are each a separate extension. Budget for them up front; the free core is post meta only.

Admin UX: the Builder extension is worth it just for generating and exporting config arrays. For list-table columns of your custom values, that is the MB Columns extension.

Gotchas and Tips

Pin the source, not this Packagist snapshot. The package metadata shows a last release of 2018-01-08, which is a stale 4.x artefact. Install from wordpress.org or the vendor's own distribution and stay current; 4.x on PHP 8 / recent WP is a compatibility question you should test rather than assume.

Free vs. paid is the real cost centre. Core is free; Settings Page, Views, Blocks, Relationships, Group, Conditional Logic, Frontend Submission, Columns, and Tooltip are commercial. A "simple custom fields" requirement can turn into a licence line item once the brief grows.

Empty values are '', not null. Always guard before echoing, and never assume a clone/multiple field returns an array — cast with (array) or check is_array().

Escape on output anyway. Meta Box sanitizes on save per field type, but rwmb_meta() returns stored data. esc_html, esc_url, wp_kses_post as appropriate; never trust it just because it came through a meta box.

Autosave ('autosave' => true) writes via AJAX. Any custom save_post logic that inspects $_POST will see nothing on autosave. Hook rwmb_before_save_post / rwmb_after_save_post (4.x) or read the meta after the box has saved, and always skip revisions.

Registration timing. rwmb_meta_boxes fires after plugins load. If the target post type is registered by another plugin at a later priority, the box silently does not appear. Same class of bug when the post_types slug is a typo — the box just never shows.

Removing a field does not remove its data. Orphaned meta rows accumulate. Clean up deliberately with a one-off migration when you delete fields.

Debugging checklist when rwmb_meta() returns nothing:

  1. Is the group actually registered on this screen? Dump the rwmb_meta_boxes array.
  2. Does the field id match exactly (case, underscores)?
  3. Are you passing the right post_id — inside a secondary loop, get_the_ID() is the wrong post?
  4. Did the value ever get saved? Check the wp_postmeta row directly; serialized arrays look like a:2:{...} and are expected for cloneable fields.
  5. On term/user screens, confirm the corresponding extension is active and the object ID is passed, not the post ID.

Performance. rwmb_meta() is a get_post_meta() call; in a loop over hundreds of posts, prefetch with update_meta_cache() or read the meta once. Serialized clone arrays cannot be efficiently meta_query-filtered by sub-value — if you need to query on it, model it as separate meta keys.

Extension points worth knowing: rwmb_meta_boxes for registration, rwmb_before_save_post / rwmb_after_save_post for save-time logic, and the custom field type filter for adding your own field class when none of the ~40 built-ins fit.

Keep field IDs namespaced (mytheme_subtitle, not subtitle). Field IDs are global meta keys; generic names collide with other plugins and with future core features.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
htinlynn/genius-helper
maco-studios/hephaestus
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk
martialbe/flysystem-oss
chondal/3312client
jeroen-g/flickr
opscale-co/nova-genbi
itsjustvita/laravel-retention
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator