Waterhole is highly extensible, making it possible to add new features tailored
to your community.
Waterhole is a Laravel package, meaning right off the bat you can add your own
routes, views, middleware, container bindings, database migrations, console
commands, and more, in the
standard Laravel way.
But there are also plenty of opportunities to extend Waterhole itself. This
section of the documentation covers those.
In Laravel, all of the application bootstrapping – the registration of bindings,
event listeners, middleware, routes – takes place in
service providers. This is also the
place where you can put code to extend Waterhole.
If you're building customizations specific to your community, then you can add
code to your project's service providers, found in app/Providers.
If, on the other hand, you want to reuse, distribute, or sell your features, you
can make an extension. The premise is the same though – the
starting point is your extension's service providers.
The main mechanism by which you'll hook into Waterhole is with extenders.
These are classes resolved from the container that expose lists and registries
you can modify. You can see all of the extenders that are available under the
Waterhole\Extend namespace.
As a quick example, open up app/Providers/WaterholeServiceProvider.php and add
the following code to register:
use Illuminate\View\Component;
use Waterhole\Extend;
public function register(): void
{
$this->extend(function (Extend\Ui\Layout $layout) {
$layout->before->add(
new class extends Component {
public function render()
{
return 'Hello, world!';
}
},
);
});
}
Now reload your forum to see your first customization!
What did we just do? We used the Layout extender's before list to inject a
custom component into the Waterhole layout. There are dozens more extenders like
this covering all parts of Waterhole's views and functionality, ready for you to
hook into.
Warning: To avoid strange behavior when using
Laravel Octane, extenders should
always be registered in a service provider's register method, and should
never be guarded by a request-specific condition. For example, don't do
this:
$this->extend(function (Extend\Ui\Layout $layout) {
if (Auth::check()) {
$layout->header->add('foo');
}
});
Instead, pass a closure to the extender and put the condition inside: