While developing my website I frequently got warnings. The one below
Warning: Attempt to read property “slug” on null in taxonomy.php on line
means WordPress tried to access the property slug of an object that doesn’t exist (is null) and, as mentioned elsewhere, this usually happens when a menu, a snippet or other piece of code references a category that no longer exist.
Here are a few safe SQL queries you can use to detect and optionally clean orphaned taxonomy entries that can cause the warning. Finally, I will give an example on how to create a stored procedure in mysql that will be much more confortable to use in code.
Detect orphaned taxonomy entries
Find taxonomy records without matching terms
SELECT tt.term_taxonomy_id, tt.term_id, tt.taxonomy FROM wp_term_taxonomy AS tt LEFT JOIN wp_terms AS t ON tt.term_id = t.term_id WHERE t.term_id IS NULL;
This query lists all rows from wp_ala_term_taxonomy that point to a term_id missing from wp_ala_terms. These are broken taxonomy links and often cause slug on null warnings when WordPress tries to load them. This is the result:
Find relationships pointing to missing taxonomy IDs
SELECT tr.object_id, tr.term_taxonomy_id FROM wp_term_relationships AS tr LEFT JOIN wp_term_taxonomy AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.term_taxonomy_id IS NULL;
This query finds post–term relationships that reference missing taxonomy entries — another possible cause of the warning. In my case, I have none:
Create and use a stored procedure
Here’s how you can wrap that query into a MySQL stored procedure named SP_show_orphaned_categories. This will return all categories (by ID, name, slug) from your WordPress database that currently have no posts assigned:
DELIMITER $$
CREATE DEFINER=`root`@`localhost` PROCEDURE `SP_show_orphaned_categories`()
BEGIN
SELECT
t.term_id AS category_id,
t.name AS category_name,
t.slug AS category_slug,
COUNT(tr.object_id) AS post_count
FROM wp_ala_terms AS t
INNER JOIN wp_term_taxonomy AS tt ON t.term_id = tt.term_id
LEFT JOIN wp_term_relationships AS tr ON tt.term_taxonomy_id = tr.term_taxonomy_id
WHERE tt.taxonomy = 'category'
GROUP BY t.term_id, t.name, t.slug
HAVING COUNT(tr.object_id) = 0;
END$$
DELIMTER ;
After creating it, you can call the procedure with:
CALL SP_show_orphaned_categories();
I like using stored procedures especially with PHP applications because the PHP code is cleaner and simpler:
$result = mysqli_query($connection, "CALL SP_show_orphaned_categories");
This Works both in MySQL and MariaDB (used by WordPress) and no input parameters needed since it simply lists all orphaned categories. If you ever need to update it, drop it first:
DROP PROCEDURE IF EXISTS SP_show_orphaned_categories;
DELIMITER
You noticed I used the DELIMITER command in the above stored procedure. Well, in MySQL, the DELIMITER command is not part of SQL itself — it’s an instruction to the MySQL client (like the command-line tool, phpMyAdmin, or MySQL Workbench). It tells the client what sequence of characters marks the end of a command you’re sending to the server. By default, MySQL uses a semicolon (;) as the command delimiter. But when you create a stored procedure, you usually need semicolons inside the procedure (to end each SQL statement):
CREATE PROCEDURE myproc()
BEGIN
SELECT * FROM wp_posts;
SELECT * FROM wp_users;
END;
If the MySQL client still thinks ; means “end of command,” it will stop after the first ; and try to execute an incomplete command — causing a syntax error. The solution is to temporarily change the delimiter to something else (commonly $$ or //):
DELIMITER $$
CREATE PROCEDURE myproc()
BEGIN
SELECT * FROM wp_posts;
SELECT * FROM wp_users;
END$$
DELIMITER ;
Here’s what happens:
DELIMITER $$tells the MySQL client: “From now on, a command ends when you see$$, not;.”- Then, the client sends the entire procedure (including internal ;s) as one block, up to the final
$$. DELIMITER ;resets it back to normal afterward.
Take care, in MySQL Workbench, editor complains about this. Just ignore it. It works:
In a future post I will provide some queries to clean the database.
Have a great day !
73


