Focus on Joomla's
Categories
by Peter Martin /
db8.nl
slides:
https://petermartin.nl
--- ### Focus on Categories in Joomla > The information architecture engine behind Joomla: from "what is a category" to ACL, routing, and developer hooks. ---
1. The Basics
---- ### 1.1 What is a Category? **Category** = container to
group and organise content
. - A smart folder for items. - Categories
help editors organise
content. - And
help visitors browse
related content. ---- ### 1.2 Categories are everywhere
Core Joomla components
- Articles (`com_content`) - Contacts (`com_contact`) - Newsfeeds (`com_newsfeeds`) - Banners (`com_banners`)
Third-party extensions
---- ### 1.3 Why use Categories? |
Purpose
| Example | |----------------------------------------|----| |
Organisation
| Group "News" articles separately from "Events" | |
Navigation
| Build menu items like "Category Blog" or "Category List" | |
Access Control
| Restrict a category to "Registered users" only | |
Styling
| Apply different layouts or templates per category | |
URL structure
| `/news/joomla-6-released` instead of `/article/42` | ---- ### 1.4 Where do I find Categories? In the Joomla 6 backend: ``` System → Manage → Categories (global view) Content → Articles → Categories (article categories) Components → Contacts → Categories (contact categories) Components → Banners → Categories (banner categories) ``` ---
2. Creating and Managing Categories
---- ### 2.1 Creating a Category `Content → Articles → Categories → New` Required: -
Title
— the human-readable name -
Alias
— used in the URL ---- ### 2.2 The Category Edit Screen — Tabs |
Tab
| What it controls | |------------------------------------|------------------| |
Category
| Title, parent, status, access, language, description | |
Options
| Layout overrides, alternative layout, image | |
Publishing
| Created/modified dates, author, meta info, version note | |
Permissions
| Per-group ACL (create, delete, edit, edit state, edit own) | ---- ### 2.3 Key Fields Explained
-
Parent
— No parent = root category, or other category for nesting. -
Status
— Published, Unpublished, Archived, Trashed. -
Access
— Public, Guest, Registered, Special, Super Users + custom. -
Language
— bind to a specific site language or leave as "All". -
Note
— internal-only label, not shown on the frontend. -
Version Note
— message stored in the version history.
---
3. Nested Categories
---- ### 3.1 The Tree Structure Joomla uses a
Nested Set Model
to store categories:
every category has
lft
and
rgt
values.
(makes deeply nested queries fast). ``` ROOT ├── News │ ├── National │ └── International ├── Events │ ├── Workshops │ └── Meetups └── About ``` ---- ### 3.2 How
lft
and
rgt
actually work Take this tree: ``` News ├── Company News └── Joomla News ├── Extensions └── Templates ``` Stored as: ``` News lft=1 rgt=10 Company News lft=2 rgt=3 Joomla News lft=4 rgt=9 Extensions lft=5 rgt=6 Templates lft=7 rgt=8 ``` **A parent always wraps its children.** ---- ### 3.3 Reading the tree A category is **inside** another when: ```sql child.lft > parent.lft AND child.rgt < parent.rgt ```
Extensions
(5, 6) is inside
Joomla News
(4, 9) because: ``` 5 > 4 6 < 9 ``` ---- ### 3.4 Why this matters To get
all child categories
of
Joomla News
, one query: ```sql SELECT * FROM #__categories WHERE lft > 4 AND rgt < 9 ORDER BY lft; ``` →
Extensions
,
Templates
**No recursion needed.** Fast reads on huge trees. ---- ### 3.5 When the tree breaks
lft
/
rgt
values must stay consistent.
Things that break them: - Categories edited directly in the database - Bad migrations - Custom extensions inserting categories incorrectly - Parent-child changes without updating nested set - Failed saves leaving gaps or duplicate values
Symptoms
:
wrong ordering, missing children, save errors. ---- ### 3.6 The Rebuild button The
Rebuild
toolbar button in the Categories fixes: ``` lft, rgt, level, path ```
Use when:
- Ordering looks wrong - Categories vanish from expected parents - After a migration - After raw SQL changes - Joomla reports tree errors Not a substitute for correct extension code!
Extensions should use Joomla's APIs, not raw SQL inserts.
---- ### 3.7 Practical rules - Child category does
not automatically inherit articles
from its parent. -
Permissions
are used
from parent
(unless overridden). - Moving a category moves all its children with it. - Keep depth shallow (2–3 levels).
Use Tags
for cross-cutting concerns. ---
4. Real-world examples
---- ### 4.1 News website ``` News ├── Politics ├── Sports ├── Tech └── Culture ``` ---- ### 4.2 University website ``` Departments ├── Engineering ├── Medicine └── Law ``` ---- ### 4.3 Webshop ``` Products ├── Laptops ├── Phones └── Accessories ``` ---
5. Categories on the Frontend
---- ### 5.1 Menu Item Types |
Menu Item Type
| What it shows | |----|----| |
Category Blog
| Articles from a category, in blog layout | |
Category List
| Articles from a category, as a sortable, paginated table | |
List All Categories
| Tree with all categories from a chosen root | |
Single Article
| One article (related, not strictly a category view) | ---- ### 5.2 Layout Options (Category Blog) - Leading articles: full width - Intro articles: columns (1–6) - Links: title only - Pagination, ordering, filters per category ---- ### 5.3 URL & Routing With **SEF URLs enabled**: ``` /news → category root /news/national → child category /news/national/election-2026 → article inside child ``` Joomla 6's router creates clean nested category paths if aliases are unique. ---
6. Access Control (ACL)
---- ### 6.1 Two distinct concepts |
Concept
| Question it answers | |----|----| |
Access (Viewing Access Level)
| Who
can see
this? | |
Permissions (Actions)
| Who
can do
what with this? | ---- ### 6.2 Access Levels Set on the
Category
tab.
The category + its articles are
only visible
to users in the matching
access level
.
Built-in levels
:
Public, Guest, Registered, Special, Super Users.
You can define your own. ---- ### 6.3 Permissions (per User Group) On the
Permissions
tab: |
Action
| Meaning | |----|----| |
Create
| Create new items in this category | |
Delete
| Delete items in this category | |
Edit
| Edit any item | |
Edit State
| Publish, unpublish, archive, trash | |
Edit Own
| Edit only items the user created | |
Edit Custom Field Value
| Change custom field values | ---- ### 6.4 The inheritance chain ``` Global Configuration └── Component (e.g. com_content) └── Category └── Article ``` Each level can be: - **Inherit** (default) - **Allowed** (grant) - **Denied** (hard block, can't be overridden) > **Deny at the highest level you can; allow at the lowest level you must.** ---- ### 6.5 Real-world ACL examples - Client portals - Staff-only documentation - Paid memberships - Department-only intranet sections ---
7. Advanced Features
---- ### 7.1
Custom Fields
per Category Content → Fields → Field Groups, then Fields - Assign fields to **specific categories** so editors only see relevant inputs. - Repeating data structures? Combine with **subform**. - Render with `{field N}` shortcodes or in template overrides. ---- ### 7.2
Layout Overrides
per Category In your template: ``` templates/your_template/html/com_content/category/ blog.php blog_item.php blog_links.php ``` For a single category, use an **Alternative Layout** on the Options tab, or name files with the category alias for finer control. ---- ### 7.3
Module Assignment
by Category Modules can be assigned to menu items
and therefore
shown per category through menu items linked to category views. ---- ### 7.4
Workflows
(com_content) Workflows can be **enabled per category**: articles move through stages (Draft → Review → Published) with transitions controlled by ACL. Content → Workflows, then bind a workflow to a category via the article options. ---- ### 7.5
Tags
vs Categories |
Use a Category when…
|
Use a Tag when…
| |----|----| | Item
belongs
to **one** place | Item relates to **many** topics | |
Hierarchy matters
| Flat, cross-cutting labels | | You need
ACL
or
workflow
| Discovery / filtering | |
Routing
should reflect it | URL not critical | > Categories define
what content is
.
> Tags describe
what content is about
. ---
8. Under the Hood (Developer View)
---- ### 8.1 One
database table
for all extensions Joomla stores every category in a single table: ``` jos_categories ├── com_content categories ├── com_contact categories ├── com_newsfeeds categories └── com_example categories ``` The `extension` column is the filter. ---- ### 8.2
com_categories
in any extension Any extension can use Joomla's category manager: ``` /administrator/index.php?option=com_categories&view=categories&extension=com_messages ``` The important part: ``` extension=com_messages ``` → "Show categories that belong to this extension." No need to build your own category manager! ---- ### 8.3 What you get for free Using
com_categories
gives you: - Nested category support - ACL integration - Published / unpublished states - Metadata fields - Language support - Ordering - Rebuild tooling ---- ### 8.4 Important table fields ``` id parent_id level path extension lft rgt alias published access language params (JSON blob with category-specific options) metadata, metadesc, metakey (SEO) ``` parent_id, level, lft, rgt, and path describe the tree. ---- ### 8.5 Categories API (PHP) ```php use Joomla\CMS\Categories\Categories; $categories = Categories::getInstance('Content'); $node = $categories->get('news'); // by alias or id $children = $node->getChildren(); $parent = $node->getParent(); $articles = $node->getNumItems(); ``` ---- ### 8.6 Making your component "Category-aware"
For a custom component: 1. Use
extension
=
com_yourcomponent
in
#__categories
. 2. Extend
Joomla\CMS\Categories\Categories
for your component. 3. Add a
rules
column to your items table for per-item ACL. 4. Register a router that handles category segments.
---- ### 8.7 Events to hook into |
Event
| When it fires | |----|----| |
onCategoryChangeState
| Publish / unpublish | |
onContentAfterSave
(context com_categories.category) | After save | |
onContentBeforeDelete
| Before deletion | ---
9. Common Pitfalls
---- ### 9.1 Too many top-level categories Bad: ``` News Blog Articles Updates Stories ``` Better: ``` Content ├── News ├── Blog └── Updates ``` ---- ### 9.2 Using categories like tags Categories should be: - Strategic - Stable - Structural Do NOT use "one-off" categories.
Use **Tags** instead. ---- ### 9.3 Bad planning Restructuring later causes: - Broken URLs - SEO regressions - Navigation confusion - Permission tangles >
Plan categories before building content
. ---- ### 9.4 Other gotchas -
Forgetting to rebuild
after manual database edits
→ broken lft/rgt. -
Mixing languages
a nl-NL category won't show en-GB items. -
Permission confusion
component-level "Denied" cannot be overridden. -
Deleting a parent
reassigns children to the grandparent, not deletes them. -
Alias collisions
under different parents are allowed but can confuse SEF if misconfigured. ---
10. Quick Reference Cheat Sheet
---- ## Quick Reference Cheat Sheet ```text CREATE Content → Articles → Categories → New NEST Set "Parent" field PUBLISH Status: Published + Access: Public RESTRICT Access: Registered (or custom level) HIERARCHY Use Rebuild if tree breaks WORKFLOW Bind on the Options tab FIELDS Assign Custom Fields to specific categories OVERRIDE templates/{tpl}/html/com_content/category/ ROUTING Enable SEF, use unique aliases ACL Component → Category → Article (inherited) REUSE index.php?option=com_categories&extension=com_X ``` ---
11. Live demo
---- ## 11. Live Demo 1. Create nested categories 2. Assign articles to a category 3. Build a Category Blog menu item 4. Open `com_categories` with `extension=com_messages` 5. Inspect `#__categories` in the database 6. Walk through `lft` / `rgt` on a real row 7. Run **Rebuild** after touching the DB 8. Restrict a category by Access Level 9. Show a SEF-friendly category URL 10. Add a Custom Field bound to one category ---
12. Summary
---- ## Summary > In Joomla, categories are not just containers for content.
-
Structure
: your information architecture -
Navigation
: the menus visitors use -
Permissions
: who sees and edits what -
SEO
: URL paths and topic clustering -
Scalability
: growth without rewrites -
Developer integration
: a shared API for every extension -
User experience
: for both editors and visitors
---
Questions?