-
Notifications
You must be signed in to change notification settings - Fork 55
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
"Smart" route URLs caching #119
base: 2.x
Are you sure you want to change the base?
Conversation
PR Summary
|
@Voltra Thanks for your work on this firstly! I've added your code to my project and noticed I was getting the following error: Then I noticed the method call inside HandlesPageUrls.php
The call is to $this->getAllUrlCacheKeysArgs(), but that method doesn't exist in the trait. After changing this call to $this->getAllCacheKeyArgs(), this problem was fixed for me.
I will start testing the code inside my project, so if you'd like additional feedback I could provide that. |
See #1 |
Whoops, that's what I get for using github codespaces instead of my usual setup, will correct the typo |
public function getUrl(array $args = []): string { | ||
$cacheKey = $this->getUrlCacheKey($args); | ||
|
||
//TODO: Clear and re-compute cached routes when the routing prefix changes |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For this maybe we can introduce an artisan command? then in the docs mention that if routing prefix changes, run the command to clear and re-compute all routes?
src/Observers/PageRoutesObserver.php
Outdated
*/ | ||
public function deleted(Page $page): void | ||
{ | ||
//TODO: implement this |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How should deleted case be handled?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For now it seems unclear. There's no way to have a "re-attach to root" strategy, since there's no concept of root. If we still have the page's relationship data, we could use a linked-list inspired deletion procedure (attaching the parent of the children of this page to be this page's parent)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See the deleting
method for that implementation
This comment was marked as resolved.
This comment was marked as resolved.
I've tried to keep the exact same interface, but just change the implementation itself. The only breaking change is in the manager, which now has a parameter to its constructor. A temporary solution would be to make it nullable (defaulting to null would keep the same arity) and using |
If you could work out locale support from #75 (comment), I'd be happy to make a 3.x release |
I think it's gonna be difficult and/or tricky to make it 1st-party. I think it should be a project-dependent configuration of the For instance: namespace App\Models\Overrides;
use Filament\Facades\Filament;
use Filament\SpatieLaravelTranslatablePlugin;
use Spatie\Sitemap\Contracts\Sitemapable;
use Spatie\Sitemap\Tags\Url;
use Spatie\Translatable\HasTranslations;
class Page extends \Z3d0X\FilamentFabricator\Models\Page implements Sitemapable {
use HasTranslations;
public array $translatable = [
'title',
'slug',
'blocks',
];
protected $table = 'pages';
/**
* {@inheritDoc}
*/
public function getDefaultUrlCacheArgs(): array
{
return [
'locale' => 'fr',
];
}
/**
* {@inheritDoc}
*/
public function getUrlCacheKey(array $args = []): string
{
$keyArgs = collect($this->getDefaultUrlArgs())->merge($args)->all();
$locale = $keyArgs['locale'];
$id = $this->id;
return "page-url--{$locale}--{$id}";
}
/**
* {@inheritDoc}
*/
public function getAllUrlCacheKeysArgs(): array
{
/**
* @var SpatieLaravelTranslatablePlugin $translatable
*/
$translatable = Filament::getPlugin((new SpatieLaravelTranslatablePlugin())->getId());
return array_map(fn (string $locale) => [
'locale' => $locale,
], $translatable?->getDefaultLocales() ?: ['fr', 'en']);
}
public function toSitemapTag(): Url|string|array
{
$entry = Url::create(url($this->getUrl([
'locale' => $this->getLocale(),
])));
$argsSets = $this->getAllUrlCacheKeysArgs();
array_walk($argsSets, function (array $args) use ($entry) {
$url = $this->getUrl($args);
$entry->addAlternate(url($url), $args['locale']);
});
$entry->setLastModificationDate($this->updated_at)
->setChangeFrequency(Url::CHANGE_FREQUENCY_DAILY);
return $entry;
}
} In my case, the locale detection/switching is made via URLs using a custom middleware: namespace App\Http\Middleware;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\App;
use Symfony\Component\HttpFoundation\Response;
class LocaleDetector
{
/**
* Handle an incoming request.
*
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
*/
public function handle(Request $request, \Closure $next): Response
{
$path = $request->decodedPath();
if ($this->matchesLocale($path, 'en')) {
App::setLocale('en');
} else {
App::setLocale(App::getFallbackLocale());
}
return $next($request);
}
protected function matchesLocale(string $uri, string $locale): bool
{
return $uri === $locale
|| str_starts_with($uri, "{$locale}/")
|| str_starts_with($uri, "/{$locale}/");
}
} Not all cases will work the same way. You might want to have the locale in the session, or the user's settings. You might need more arguments to generate a route, etc... That's why these customization/extension points exist in the first place:
|
Agreed. I think a pinned post on discussions on how this plugin can be extended to support translations should suffice. @Voltra if there isn't anything else to be added I'm merging this. I have reviewed the code once again, you are right, there doesn't seem to be any breaking changes |
…re/SMART_ROUTE_CACHING
Deleted as in using the delete action from the PageResource's table. Looks like it's just a standard filament DeleteAction that deletes the record using the model. So in that case, it should work since you're observing deletion of page models? |
It should, but if there's any sort of on-delete-cascade logic that might be what causes them to be deleted |
I have some relations set up in my db but I don't think I have any on delete cascades. I'll check and make a copy db without the relations for testing if it's the case though. EDIT ( 2-2 2024) Also, I'm writing tests for my project, and was wondering how to best go about writing a smoke test for all Fabricator pages? This is really the first time I'm writing tests so bear with me on that, lol. Learning as I go currently. I've installed Laravel Pest and I noticed that the FilamentFabricator package has a TestCase included. Is this extendable and would it be preferred to use inside tests that involve Fabricator pages? |
…re/SMART_ROUTE_CACHING
I can't merge until #119 (comment) is fixed |
Short answer nope. This unrelated to this PR, make a post in the Discussions, if you want a more detailed answer |
I'll do some testing in the next few days. |
Was the project setup with Pest or just regular PHPUnit ? I feel like writing unit tests for this part will definitely help (especially with detecting regressions in the future) |
@Voltra setup is for pest, you can see the sample test in the test folder. I could write basic tests for existing features, then you can add any additional tests for this PR |
Would it be OK if I configured the tests to use the |
There were a few bugs that the unit tests help catch |
Things should be A-OK @Z3d0X I've also added a config option that hooks into existing laravel artisan commands to clear and refresh the caches at the same time as the others. |
Just got done fixing a corner-case in updates where changing the parent page would not properly change the URLs. Now all cases should be handled properly and thoroughly tested. |
Should be good to merge |
any update on this? |
Initial draft of the new route caching system as described in #116
A few quirks need to be ironed out (mainly completely removing any and all traces of the previous route caching system).
The
args
are mainly here to enable project-dependent customization for generating multiple "independent" URLs per page (e.g. translatable pages)