There's no single answer here, like anything software related it's all a question of what works best for you, your team, and your users, but here's a few general rules of thumb.
CMS Widgets are for content management. You create a widget when you want to create a simple user interface where store owners can create typed content, which can then be inserted into a page. Not a good choice to distributing an extension that needs to modify a page, or for creating an on/off feature. The ideal use case is a Magento solution provider creates specific widgets and a widget workflow, and a store owners content people update the widgets and add them to pages while managing a site's content.
The local.xml
file is for layout updates that are local to this specific store/theme, and require little programatic logic. Your specific mention of adding a local.xml
to app/design/frontend/base/default/layout
would be a particularly poor choice for an extension you're distributing, as a user would lose this as soon as they added their own local.xml
file to a theme. The ideal use case for local.xml
is a developer working for a store owner (i.e. has a long term relationship with this particular Magento installation) who needs to build new pages or non-management content/interactive modules. Third party extensions shouldn't add anything to local.xml
.
The official blessed way to distribute an extension that modifies an existing page would be to
- Create a module
- Use that module to add a new layout xml update file (see files like
catalog.xml
in core modules)
- Use this layout update XML file to make your changes
This gives you the same functionally as local.xml
, but keeps your code separate from a local user's system code. If you can add your block and implement your feature using only the features of the layout update xml files (block
, reference
, action
, ifconfig
, etc ..) this is a good choice.
Finally, there's using a core_block_abstract_to_html_after
observer. This will let you add a block using pure PHP. Some PHP developers (myself included) prefer using this method as it's more programmatically transparent than using layout update xml files. The downside of using this method is if you attempt to grab a reference to a block
$block = Mage::getSingleton('core/layout')->getBlock('some_block');
$block->setSomeMethod('foo');
and some_block
doesn't exist, you'll get you a fatal PHP error for calling a method on a non-object. That means your observers end up having a lot of code like this
$block = Mage::getSingleton('core/layout')->getBlock('some_block');
if($block)
{
$block->setSomeMethod('foo');
}
One of the benefits of using layout xml update files is these sorts of error silently fail on a production store (although it's that same silent failure that's maddening when developing a feature)
Hope that helps, and good luck! When in doubt, use the technique that lets your get your job done — you can always re-factor later.