I have a custom class which I use for several cases extending it, for example

class A {
    public function show_things() {
        print_r( apply_filter( 'yet_another_filter', array( 'coffee', 'tea' ) ) );
    }
}

class B extends A {
    public function __construct() {
        parent::__construct();
        add_filter( 'yet_another_filter', array( $this, 'other_things' ) );
    }

    public function other_things( $things ) {
        return array( 'crisps', 'beer' );
    }
}

class C extends A {
    public function __construct() {
        parent::__construct();
        // no filter added here
    }
}

Now, I create instances of Class B and C:

$b = new B;
$c = new C;

When displaying the things of $b, with

$b->show_things(); // gives crisps, beer

When displaying the things of instance $c where I did not add any filter, I get the same, since the filter added by instance $b is ‘global’:

$c->show_things(); // gives crisps, beer, which is logical

But I would like to get the coffee and tea, since I did not add the filter inside class C. Do I have to add the instance itself when adding the filter and then checking for $this? Or is there another (better) approach?

1 Answer
1

The problem is that filters in WordPress are global; if you add a filter somewhere it persists everywhere, unless you remove it.

Also consider that you should prefer composition over inheritance, and if your current application structure is already built upon inheritance, and you can’t or don’t want to change it, you should avoid at least using filters for things that aren’t global.

By separating the logic that returns data from the logic that filters it, everything becomes much easier:

class A {

    function get_things() {
        return array( 'coffee', 'tea' );
    }

    function show_things() {
        return apply_filter( 'yet_another_filter', $this->get_things() );
    }

}

class B extends A {

    function get_things() {
        return array( 'crisps', 'beer' );
    }

}

class C extends A {

}

As you can guess:

$a = new A;
$b = new B;
$c = new C;

$a->show_things(); // array( 'coffee', 'tea'  )
$b->show_things(); // array( 'crisps', 'beer'  )
$c->show_things(); // array( 'coffee', 'tea'  )

All the results pass through "yet_another_filter" filter, allowing external code to overwrite results in all cases, which is what a filter is intended for.

Leave a Reply

Your email address will not be published. Required fields are marked *