Almost every major site I work on has at least one custom wp-cli command that I’ve built to manage or automate things. But I always run into the same problem, I don’t want my command to be a root command, I want it to live in a namespace of my own. But, I also don’t want to create a blank command that doesn’t do anything just for the sake of this namespace.
For instance, if I register a command using this:
WP_CLI::add_command('custom-command do-thing', DoThingCommand::class);
WordPress will show the below if I just type
cache Adds, removes, fetches, and flushes the WP Object Cache object. cap Adds, removes, and lists capabilities of a user role. cli Review current WP-CLI info, check for updates, or see defined aliases. comment Creates, updates, deletes, and moderates comments. config Generates and reads the wp-config.php file. core Downloads, installs, updates, and manages a WordPress installation. cron Tests, runs, and deletes WP-Cron events; manages WP-Cron schedules. custom-command db Performs basic database operations using credentials stored in wp-config.php. embed Inspects oEmbed providers, clears embed cache, and more. eval Executes arbitrary PHP code. eval-file Loads and executes a PHP file.
If you don’t notice or are unable to see the problem, each command listed has an “intro” description except for my command which instead just has a blank space.
Instead of grepping all of wp-cli’s code, I luckily had Yoast installed, too, so I grepped their code and saw a special class from core that you can extend call
CommandNamespace which has the following comment:
Adds a command namespace without actual functionality.
This is meant to provide the means to attach meta information to a namespace when there’s no actual command needed.
In case a real command gets registered for the same name, it replaces the command namespace.https://github.com/wp-cli/wp-cli/blob/bc37f66e25b9992813b0c50b933aefbf88718e6a/php/WP_CLI/Dispatcher/CommandNamespace.php#L8
So, just create a class that extends that (and probably make it final), register it like a normal command, and WordPress will do the rest for you.