Skip to content
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

nocache tag and view::shared variables does not work "well" #10651

Open
dadaxr opened this issue Aug 17, 2024 · 0 comments
Open

nocache tag and view::shared variables does not work "well" #10651

dadaxr opened this issue Aug 17, 2024 · 0 comments
Labels

Comments

@dadaxr
Copy link

dadaxr commented Aug 17, 2024

Bug description

AFAIK there is no "statamic" way to share variable globally (across template and php code).

For instance if you want to set some globally available data from a middleware or a service provider ...

Using the "Cascade::set" helper does not work consistently because the cascade is reset before initializing the view.
So we can't use it "early" in the request life cycle...

I know 4 ways to share data globally :

this last helper is great because we can use it almost seamlessly in the templates because "shared" variables are accessible like other cascade variables from the context.

BUT ... when using "nocache" tag, it becomes tricky to use because the data available within the {{ nocache }} tag pair depends of the "select" tag paramater
.

Some examples, assuming we have a middleware (or a service provider), setting a shared variable "visitorCounter" which should be updated at each request (even with the "half" caching strategy set)...

1 : without "select" param (by default "all" variables come from the cached context, except some "top level var" which will be refreshed at each request

{{ nocache }}
 {{ visitorCounter }}
{{ /nocache }}

=> always use the first cached version (so visitorCounter would always be "1" ) so it's the same as no "nocache" tag

2 : with the "select" param defined

{{ nocache select="visitorCounter"}}
 {{ visitorCounter }} 
{{ /nocache }}

=> same result as above here : after a first "doc" read I thought the "select" param could be use to select some variable to be injected "fresh" in the nocache tag but it's the contrary ... it only permits to "pick" some previously cached var from the whole list of cached var... to prevent some overwhelming in hydratation.

3 : with "select" param "hacked"

{{ nocache select="aFakeVarName | orAnotherExistingVarName"}}
 {{ visitorCounter }} 
{{ /nocache }

=> here, the visitorCounter would correctly be incremented at each request ... only because we fill the select param explicitly with other var name ... so the visitorCounter var is not fetched from the cache context anymore ... We cannot use an empty select param (select="") neither an empty array ( :select="[]" ) because it triggers an error. But this technique is really not obvious... it's like saying all what you hate, so we can know what you love...

So here's my suggestions :

1 - we could simply add an "exclude" param to the nocache tag ... doing the opposite of the select, and update the doc to "clarify" the role of each
2 - or if there is not enough use case for this "exclude" param except the one I've just mentioned (view::share), maybe we can just force the the view::shared variables to be merged in the new cascade reinjected inside the nocache tag
( cf : the actual nocache doc paragraph All of the [top level variables](https://statamic.dev/variables) will be filtered out and replaced with fresh versions on subsequent requests. )

One way to do it actually is to use the bellow code within a service provider :

Cascade::hydrated(function (\Statamic\View\Cascade $cascade) {
      foreach(View::getShared() as $key => $value){
          $cascade->set($key, $value);    
      }
      $this->app[Statamic\StaticCaching\NoCache\Session::class]->setCascade($cascade->toArray());
  });

That way, the bellow code "just works"

{{ nocache }}
 {{ visitorCounter }}
{{ /nocache }}

But IMHO it could be done by default, and the laravel "view::share" and "view::shared" helper be documented somewhere (or be use internally by a new & documented Cascade::share helper method)

What do you think ?

How to reproduce

For the ease of reproduction, we could use a random integer var instead of an "visitorCounter"

enable "half" nocache strategy in the .env file :

STATAMIC_STATIC_CACHING_STRATEGY=half

in the boot method of a service provider add :

View::share( 'random_var', rand(0,100) );

and in a template, reuse the bellow blocs

{{ nocache }}
 {{ random_var }} {{# always cached #}}
{{ /nocache }}
{{ nocache select="random_var"}}
 {{ random_var }} {{# always cached #}}
{{ /nocache }}
{{ nocache select="aFakeVarName"}}
 {{ random_var }} {{# always updated #}}
{{ /nocache }

Logs

No response

Environment

Environment
Laravel Version: 10.48.13
PHP Version: 8.2.7
Composer Version: 2.6.2
Environment: local
Debug Mode: ENABLED
Maintenance Mode: OFF

Cache
Config: NOT CACHED
Events: NOT CACHED
Routes: NOT CACHED
Views: CACHED

Drivers
Broadcasting: log
Cache: file
Database: mysql
Logs: stack / single
Mail: smtp
Queue: sync
Session: file

Statamic
Addons: 4
Sites: 1
Stache Watcher: Disabled
Static Caching: half
Version: 5.20.0 PRO

Installation

Fresh statamic/statamic site via CLI

Additional details

No response

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants