🔧 Development
Stormlight Stormlight Apr 2, 2024

Laravel Integration

Hey @Toby, I'm currently working on a Laravel website from scratch and was wondering which scenario is better:

1) Start a new Laravel project and pull Waterhole as a package
2) Start a new Waterhole project and add main website features (routes, models, controllers etc) afterwards

Does one or the other have any advantages/disadvantages?

If we go with scenario 1, is it still possible to utilize the Waterhole css/components in my main Laravel app (I'm probably going to use blade/livewire)?
I think I may have answered my own question regarding Waterhole css/components (docs) by using the waterhole layout (see below).

<x-waterhole::layout title="Home">
    <section class="section">
        <div class="container">Content</div>
    </section>
</x-waterhole::layout>

Also, when can we expect compatibility with Laravel 11 and going forward how quickly can we expect Waterhole to have compatibility with future Laravel releases?

Apologies for asking so many questions, thanks in advance!

⁨8⁩ ⁨Comments⁩

Toby Toby Waterhole Founder Apr 3, 2024

Hey @Stormlight,

The Waterhole project skeleton is really just a slightly stripped-down version of the Laravel 10 skeleton (no Vite, no API routes, etc.) with some default configuration in place – use the Waterhole User model for auth, and add a service provider for Waterhole customizations.

Whether you start with the Laravel skeleton and pull in Waterhole, or start with the Waterhole skeleton and pull in things from the Laravel skeleton as needed, you'll end up at pretty much the same place. So do whatever you're most comfortable with 😊

As you've discovered, you can build new pages within the Waterhole layout using the <x-waterhole::layout> component, or if you just want the CSS (and not the layout) you can use <x-waterhole::html>. A list of all Waterhole components is available in the class reference.

See here for Laravel 11 discussion - we'll stay on top of future Laravel releases relatively quickly.

In reply to Toby Toby

Thanks for clarifying that @Toby! I had two more questions:

  1. How can we implement conditional rendering of components based on the route. In my case, I’m trying to remove the ‘search’ component from the Header on any routes that aren’t prefixed with “/forums” (my waterhole path is set to "forums").
// Inside the WaterholeServiceProvider extend function

if (!Route::is('forums.*')) {
    Extend\Header::remove('search');
}

I don’t think we can access routes in a ServiceProvider (nor is it good practice?) since that’s what’s bootstrapping the application, though I might be mistaken. In normal situations, we would have this conditional in our blade template files. However, I don’t think we have access to modify the Waterhole blade template files (unless I missed something in the Waterhole docs).

See my response in the post below for the solution.

  1. How should we go about adding relationships to the User model with my own generated models. In the docs, it’s mentioned to use Laravel’s resolveRelationUsing method. However, the Laravel docs mention that this is not recommended for normal application development. Is it then better to just create another User model and extend the Waterhole\Models\User class?
In reply to Stormlight Stormlight

I was able to figure out my question above regarding conditional rendering. If anyone else is interested, I just removed the 'search' component and added my own custom component (which has the logic for the conditional rendering) via the WaterHoleServiceProvider. Waterhole docs for reference.

// WaterholeServiceProvider

use App\View\Components\Navigation;

public function extend(): void
{
    Extend\Header::remove('search');
    Extend\Header::add(Navigation::class); // my own custom Blade component
}
// My custom blade view (navigation.blade.php)

<div>
    {{-- Other nav links if needed --}}
    @if (Route::is('waterhole.*'))
        <x-waterhole::HeaderSearch />
    @endif
</div>
Toby Toby Waterhole Founder Apr 11, 2024
In reply to Stormlight Stormlight

Yep, that's right about conditional rendering - there's a note on this in the Extenders doc. The way you've done it works well, or an alternative would be to replace the search component with a closure and conditionally return the search component:

use Waterhole\View\Components\HeaderSearch;

Extend\Header::replace('search', fn() => Route::is('waterhole.*') ? HeaderSearch::class : null);

Regarding adding relationships to Waterhole's User model, using resolveRelationUsing is fine when you're interacting with a package like Waterhole – the Laravel docs are talking about "normal application development" as in within your own app's codebase. Creating your own subclass of the Waterhole User model is also a nice idea, although I'm not 100% certain it will work in all cases as I believe some instances of the User model are hardcoded throughout Waterhole's codebase – I will definitely look at making this configurable in the future.

In reply to Toby Toby

Ahhh, I see, the alternative you've provided with the closure looks cleaner 👍️, thanks! I shouldn't have missed that in the docs 😅.

Okay, that makes sense, I'll use the resolveRelationUsing method for adding relationships. Is there any way we can add traits to the Waterhole\Models\User class in a similar way as adding relationships via the resolveRelationUsing method? I wanted to use this Laravel package, Overtrue\LaravelFavorite, but it requires the use of traits on the User model. I want to use this package to allow users to favourite my own models.

In reply to Toby Toby

Also, regarding conditional rendering, the use of a closure doesn't seem to work with the Extend remove method as it only accepts a string param. Is this method going to be updated in the future to allow for mixed content instead of only strings? I was trying to conditionally remove some of the buttons in the text editor but it seems they are hard coded, so using the replace method wasn't viable (source code).

Toby Toby Waterhole Founder Apr 30, 2024
In reply to Stormlight Stormlight

Is there any way we can add traits to the Waterhole\Models\User class in a similar way as adding relationships via the resolveRelationUsing method?

Unfortunately I don't think it's currently possible to add traits to the Waterhole User model. Again, I'll look into making the User model configurable so you can subclass it, but for now your options are to implement the desired relations manually using resolveRelationUsing, or use your own separate User model/table and then set up the Laravel authentication integration.

Also, regarding conditional rendering, the use of a closure doesn't seem to work with the Extend remove method as it only accepts a string param. Is this method going to be updated in the future to allow for mixed content instead of only strings?

Haven't tested, but try this:

$button = TextEditor::get('mention')['content'];
TextEditor::replace('mention', fn(string $id) => $condition ? $button($id) : null);
In reply to Toby Toby

Sounds good, for now I'll just create another user and implement traits on that model. I'll try out the code snippet you posted above as well, thanks!