I am developing a site that allows to save a visitor's preferences, whether they're logged in or viewing the site as a guest.
To make things easier, I abstracted some logic around this under a helper class (a service). This class can be injected anywhere throughout my code, and will provide methods like $helper->getSettings(), so we can obtain the current visitor's settings without bothering about where they come from (User model, the cookie, the defaults…).
Here's a dummy example of how the class would look like:
class Helper
{
/** @var array $settings */
protected $settings;
public function __construct()
{
if (Auth::check()) {
$this->settings = Auth::user()->settings;
} else if (Cookie::has('settings')) { // Data from guest users is stored in a cookie
$this->settings = Cookie::get('settings');
} else {
$this->settings = [];
}
}
public function getSettings() {
return $this->settings;
}
// More methods that make use of $this->settings
}
Note: This class is bound to the Service Container as a singleton.
I am currently using this class in a controller's private method. As I cannot directly inject this dependency in the private method's signature, I have to inject it from within the controller's constructor, like this:
class MyController extends Controller
{
/** @var Helper $helper */
protected $helper;
public function __construct(Helper $helper)
{
$this->helper = $helper;
}
private function somePrivateMethod() {
// Using $this->helper
}
//
}
Now, the problem is the following:
I am injecting this class into the controller by using its constructor. As the controller's constructors are run before the middleware pipeline, there's no session and, hence, authentication yet, so my Helper class will not work as expected.
To solve this I have thought of some alternatives:
- Creating a
initialize() method in the Helper class that would check if the class has been initialized. This method would be called before any of the other methods in the helper. This option, however, feels very dirty and prone to error as I could forget to add this check.
- Using the
app() global helper, but I am not a fan of globals and would like to avoid them if possible.
As I'm not very happy about my options I come to you to enlighten me with your wisdom. What would you do?