I have a fairly large site with the main content on most pages driven by a Matrix field. That Matrix field has 15 or so different Blocks - we are now doing a tidy up on the site and going to try and reduce the number of blocks available - is there any way to tell if a block isn't being used?
1 Answer
Nothing native, but it can be done with an SQL query – something like this should work (note that all the queries assume that your dbPrefix
setting is set to 'craft_'
):
SELECT bt.id, bt.handle, f.handle as field
FROM craft_matrixblocktypes bt
INNER JOIN craft_fields f ON bt.fieldId = f.id
LEFT JOIN craft_matrixblocks b ON bt.id = b.typeId
WHERE b.id IS NULL
The above query would output a table with the id
and handle
for all block types that aren't used, in addition to the handle for the Matrix field they belong to, i.e.
id | handle | field
------------------------------------------
13 | someMatrixBlock | someMatrixField
4 | anotherMatrixBlock | someMatrixField
To actually execute the SQL query, you can use a free tool like Sequel Pro or phpMyAdmin – or write a custom plugin that uses the QueryBuilder.
Edit
Upon request in the comments below, here's a query that will list all block types that are in use (i.e. there are blocks for each particular block type). The number of blocks for each type is listed in a count
column:
SELECT COUNT(bt.id) as count, bt.id, bt.handle, f.handle as field
FROM craft_matrixblocktypes bt
INNER JOIN craft_fields f ON bt.fieldId = f.id
LEFT JOIN craft_matrixblocks b ON bt.id = b.typeId
WHERE b.id IS NOT NULL
GROUP BY bt.id
...and here's a query that will output a table with all blocks, sorted by block type, with the ID and URI for the entry which "owns" each particular block. The following query should work for Craft 2:
SELECT b.id as blockId, bt.handle as blockType, bt.id as blockTypeId, e.id as entryId, i18n.uri as entryUri, f.handle as field
FROM craft_matrixblocks b
INNER JOIN craft_entries e on e.id = b.ownerId
INNER JOIN craft_fields f on f.id = b.fieldId
INNER JOIN craft_matrixblocktypes bt on bt.id = b.typeId
LEFT JOIN craft_elements_i18n i18n on i18n.elementId = e.id
ORDER BY bt.id
For Craft 3 (and 4), you'll need to replace the craft_elements_i18n
table with craft_elements_sites
:
SELECT b.id as blockId, bt.handle as blockType, bt.id as blockTypeId, e.id as entryId, sites.uri as entryUri, f.handle as field
FROM craft_matrixblocks b
INNER JOIN craft_entries e on e.id = b.ownerId
INNER JOIN craft_fields f on f.id = b.fieldId
INNER JOIN craft_matrixblocktypes bt on bt.id = b.typeId
LEFT JOIN craft_elements_sites sites on sites.elementId = e.id
ORDER BY bt.id
If you want to exclude drafts, revisions and soft-deleted entries, include this in the query:
INNER JOIN craft_elements els on els.id = b.ownerId
WHERE els.dateDeleted IS NULL AND els.draftId IS NULL AND els.revisionId IS NULL AND els.archived = 0
Edit: For Craft 4, you'll want to replace all instances of b.ownerId
with b.primaryOwnerId
.
If you want to limit that last query to only list the blocks for a particular block type, you can replace the ORDER BY
statement with this:
WHERE bt.id = 2
Where 2
is the ID for the block type you want to list.
-
Excellent - really useful - in a similar manner then is it possible to find the number of times a block from a particular field does appear and say what page it is on– mmc501Commented Dec 22, 2016 at 10:35
-
The number of times a block type have been used (i.e. the number of blocks with that particular block type) should be easy enough, but if you want to output the ID/handle/URL for any elements with relevant blocks you're going to have to pull multiple rows for each block type (one per element), so I don't see those two operations being very useful together. Commented Dec 22, 2016 at 10:56
-
Thanks - the number of times of block type would be used would be very useful as we could see then what blocks we could do away with. If there is a few then some way to find easily what entries the block is used in - even if it needed to be a separate query as there are a large number of entries on the site so could be hard to find manually– mmc501Commented Dec 22, 2016 at 10:58
-
1
-
1@mmc501The queries you provided are SUPER helpful. Just wanted to say thank you! You helped me considerably with this answer.– dpayneCommented Jun 7, 2017 at 15:17