The Dependency inversion principle: "Depend upon abstractions, not concretions."
One of the biggest advantages of such approach is reducing impact of external providers to the core of your application which helps especially medium and large sizes WordPress websites. Why it might be important? Getting know with this article might get you more context.
Once we disable ACF plugin, the page (depends on your conctrete implementation) will still work fine. If you decide to switch ACF to another plugin, you jest need to write a new implementation. You won't need to touch any other files in your application.
#1 Contract
The first thing that we need to do is create a contract (abstration) that ensures that the application implements correct settings module. The contracts are one of the most important parts of business rules.
namespace App\Contracts;
interface Settings
{
public function getField(string $name, int $id);
}
#2 Implementation
Implement controllers that will handle settings management in your application (concrete implementation).
namespace App\Integrations\WP;
use App\Contracts\Settings as ISettings;
class Settings implements ISettings
{
public function getField(string $name, int $id)
{
return get_post_meta($id, $name, true);
}
}
namespace App\Integrations\ACF;
use App\Contracts\Settings as ISettings;
class Settings implements ISettings
{
public function getField(string $name, int $id)
{
return get_field($name, $id);
}
}
If you have concerns that results for get_field
and get_post_meta
might return different results for the same field - you're right! ACF provides much more features as fields filtering what might cause different results, but it depends on you how it will behave. If you design data architecture focused on business rules, you'll be able to solve this problem.
#3 Initialize
Initialize the concrete implementations based on active plugins.
namespace App;
use App\Contracts\Settings;
class Facade
{
private Settings $settings;
public function __construct()
{
$plugins = apply_filters('active_plugins', get_option('active_plugins'));
if (in_array('advanced-custom-fields-pro/acf.php', $plugins)) {
$this->settings = new \App\Integrations\ACF\Settings();
} else {
$this->settings = new \App\Integrations\WP\Settings();
}
}
public function settings(): Settings
{
return $this->settings;
}
}
#4 Usage
Just use the settings facade.
printf(__('Post: %s', 'app'), app()->settings()->getField('title', 1));