Create a Pages category from code, move some records into it, and every one of those records becomes unreachable. The browser reports too many redirects; the server is issuing a 301 to the same URL over and over. The category itself is fine — it lists correctly, the AdminCP shows nothing unusual, and the records are present and approved.
The cause is one column that nothing asked you to fill in: category_full_path.
Why it loops rather than 404s
Pages builds a record's canonical URL from the category's stored full path, not by walking the parent chain at request time. With the column empty, the path segment is empty, and the URL comes out with a doubled separator:
/kb//how-to-do-the-thing-r7/
Pages then does what it always does with a non-canonical URL — redirects to the canonical one. Which it rebuilds from the same empty column. Which is the same URL it just rejected. The loop is not a bug in the redirect; the redirect is working perfectly and being handed a broken destination forever.
The fix
Write the column when you create the category. It is the parent's full path, plus a slash, plus this category's furl name — and for a top-level category it is simply the furl name:
$category->save();
\IPS\Db::i()->update( 'cms_database_categories', array(
'category_full_path' => $parent['category_full_path'] . '/' . $slug,
), array( 'category_id=?', $category->id ) );
It has to happen after save(), because until then there is no id to update. To repair categories that already exist, walk the parent chain once and write the assembled path to each row, then clear the caches:
\IPS\Data\Store::i()->clearAll();
\IPS\Data\Cache::i()->clearAll();
How to catch it
After creating any category in code, request an actual article URL and check the redirect count, not just the status code. A loop and a healthy page both look like success if you only ever follow redirects and read the final status:
curl -s -o /dev/null -L -w '%{http_code} hops=%{num_redirects}\n' <article-url>
A healthy record answers 200 hops=0. Anything reporting dozens of hops is this.
Related
The same shape of problem — a Pages category that saves cleanly and is then quietly broken — also applies to permissions: a category with no row in core_permission_index is invisible on the front end and raises nothing at all. See Creating a Pages database and categories in code.
Recommended Comments