WordPress uses calls filters and actions internally. They are called hooks and they make WordPress super flexible because it doesn't have to be a piece software that tries to do or be everything. It only needs to offer the foundation and the rest can be done via plugins.

 

WordPress Hooks

Filters => modify a piece of content and return it

Actions => are events that happen at a given time. An action can output something or nothing at all.

 

Naming convention

Here's how I name my filters and actions.

I start with my company name and then add the plugin name.

If it's going to be an extension/addon of an existing plugin I add that name as well e.g. "_woocommerce_ext_"

Depending on the hook it will also have _filter_ or _action_ after the name and last comes the action/filter name.

Result:

action: orbisius_woocommerce_ext_quick_order_action_before_order_container

filter: orbisius_woocommerce_ext_quick_order_filter_header_cols

Yes, they are long but so are descriptive. You won't accidentally use filter where an action is supposed to be used or vice versa.

How I use them

When triggering actions I pass an array which I call context ($ctx)  that contains relevant info. In the beginning it's either empty or has just one element.

When triggering filters I pass the data that needs to be modified and then as a second parameter an array which I call again context ($ctx)  that contains relevant info.

 

Examples
This is how your code should trigger the action.

	
	// action triggering
	$ctx = array(
		'product_id' => 123,
	);

	do_action( 'orbisius_woocommerce_ext_quick_order_action_before_order_container', $ctx );

This is how an addon can use your custom action.

	add_action( 'orbisius_woocommerce_ext_quick_order_action_before_order_container', 'company_custom_action_handler' );

	function company_custom_action_handler( $ctx ) {
		// Do something awesome!
		echo 42;
	}

Actions can output something. If you need the capture the content from an action, you can use php's output buffering functions.
I've seen this approach in Pippin's plugins and is a very cool idea.

	$ctx = array(
		'css_class' => 'my_app_wrapper',
		'product_id' => 123,
	);

	ob_start();
	do_action( 'orbisius_woocommerce_ext_quick_order_action_before_order_container', $ctx );
	$action_buff = ob_get_clean();

Filters
There's a little extra effort to add 2 additional parameters to that add_filter call.
We need to explicitly specify the priority of the filter and the number of arguments it accepts.
We specify 10, 2; 10 - priority, 2 - 2 arguments. The first value is the data that's being modified and 2nd one is the context parameter.

For actions we didn't have to do that because by default the priority is 10 and the number of arguments is 1.
This is how your code should trigger the filter.

	// Your plugin/theme triggers the filter.
	$columns = [
		'id' => 'ID',
		'product_name' => 'Product Name',
	];

	$ctx = array(
		'user_id' => 777,
		'product_id' => 123,
	);

	$columns = apply_filters( 'orbisius_woocommerce_ext_quick_order_filter_header_cols', $columns, $ctx );

Usage (addons can hook into this filter)

	
	add_filter( 'orbisius_woocommerce_ext_quick_order_filter_header_cols', 'company_custom_modify_cols', 10, 2 );	

	function company_custom_modify_cols( $columns, $ctx ) {
		// Modify the data like a Pro!
		return $columns;
	}	

Why bother passing that additional info?
Well, when we pass an array we make the code future proof.
When your plugin/theme starts to get more popular you will definitely need to pass more information to modify the content using one way or another.
For example if you have a gallery plugin the images could be rendered in a list or grid view.

What are your best practices? Feel free to share them in the comments below.