🔹 Option 1: Invisible Submenu Page
You can register a hidden submenu page (so it doesn’t clutter the menu), and then link to it.
add_action(‘admin_menu’, ‘crudboard_menu’);
function crudboard_menu() {
add_options_page(
‘CRUD Board’,
‘CRUD Board’,
‘manage_options’,
‘crud’,
‘crudboard’
);
// Hidden submenu (not shown in sidebar)
add_submenu_page(
null,
‘Create Motor’,
‘Create Motor’,
‘manage_options’,
‘crud-create’,
‘crudboard_create’
);
}
function crudboard() {
?>
<div class=”wrap”>
<h2>
Motors
<a class=”add_new-h2″ href=”<?php echo admin_url(‘options-general.php?page=crud-create’); ?>”>Add New</a>
</h2>
<table class=”wp-list-table widefat fixed pages”>
<tr><td>Start page</td></tr>
</table>
</div>
<?php
}
function crudboard_create() {
include ‘create.php’;
}
Now you have /wp-admin/options-general.php?page=crud for the main listing.
And /wp-admin/options-general.php?page=crud-create for the add-new page.
WordPress knows about both, so no permissions error.
🔹 Option 2: URL Parameter (Simpler)
Instead of registering a second page, just check $_GET[‘create’] as you already did:
add_action(‘admin_menu’, ‘crudboard_menu’);
function crudboard_menu() {
add_options_page(
‘CRUD Board’,
‘CRUD Board’,
‘manage_options’,
‘crud’,
‘crudboard’
);
}
function crudboard() {
$add_new_url = admin_url(‘options-general.php?page=crud&create=true’);
?>
<div class=”wrap”>
<?php if ( !isset($_GET[‘create’]) ) { ?>
<h2>
Motors
<a class=”add_new-h2″ href=”<?php echo esc_url($add_new_url); ?>”>Add New</a>
</h2>
<table class=”wp-list-table widefat fixed pages”>
<tr><td>Start page</td></tr>
</table>
<?php } else {
include ‘create.php’;
} ?>
</div>
<?php
}
URL for listing: /wp-admin/options-general.php?page=crud
URL for adding: /wp-admin/options-general.php?page=crud&create=true