Personal Catalogue: PHP & MySQL — Chapter 7, Exercise 1 ==================================================== TASK Build index.php using the GROUP_CONCAT query from this chapter against your real database (with at least one tagged book, one untagged book, and one CD or DVD already in it from earlier chapters). Confirm the untagged items show a sensible fallback (e.g. "—") in the Tags column rather than a blank cell or a PHP warning. SOLUTION With index.php built using the full GROUP_CONCAT/LEFT JOIN query and the rendering loop from the chapter, and a database containing (from earlier chapters) at least: - "The Hobbit" (book, tagged Fantasy, Adventure) - "Fluent Python" (book, no tags attached) - "The Dark Side of the Moon" (CD, no tags — CDs never get tags) loading index.php shows a table where: - The Hobbit's Tags column reads "Adventure, Fantasy" (alphabetical, per the ORDER BY tags.name inside GROUP_CONCAT) - Fluent Python's Tags column reads "—" - The Dark Side of the Moon's Tags column reads "—" The fallback works because of this exact line in the rendering loop: For an item with zero tags, the LEFT JOIN produces no matching item_tags/tags rows, so GROUP_CONCAT() over zero rows returns SQL NULL for that item's own tag_names column — not an empty string. PDO returns that NULL as PHP null, and the ?? '—' null-coalescing operator catches exactly that case, substituting the fallback text before htmlspecialchars() ever runs (which would otherwise throw a deprecation warning if passed null directly in modern PHP). WHY THIS WORKS AS AN ANSWER ---------------------------- It uses a real mix of tagged and untagged items across two different item types (not just books) to confirm the fallback handles every case the query can actually produce, and correctly traces the fallback back to GROUP_CONCAT's own real NULL-on-zero-rows behavior rather than just observing that the dash appears.