How to show not cached fe_user data in TYPO3? According to Prevent to Cache Login Information.
The ViewHelper sets $GLOBALS['TSFE']->no_cache = 1 if the user logged in. Is there a better way? Because not the whole page should not be cached, only some parts of it.
Unfortunately this is not possible.
The best way is, you render the not cached fe_user data with a AJAX called eID or TypeNum and the whole page is completly cached.
like this one:
http://www.typo3-tutorials.org/cms/typo3-und-ajax-wie-geht-das.html
your example code disabled cache for the complete page. but you only need to disable cache for the part where you display the user specific data. As you can except any part from caching you need to select whether to cache only
one content element (especially for plugins this is standard behaviour: just declare your plugin as uncachable in your ext_localconf.php)
one column (make sure you use a COA_INT (or other uncached object) in your typoscript)
one viewhelper (make your viewhelper uncachable [1] or use the v:render.uncache() VH from EXT:vhs)
[1]
as a viewhelper is derived from AbstractConditionViewHelper, which uses the Compilable Interface, which caches the result, the compile() method from AbstractConditionViewHelper must be rewritten and return the constant
\TYPO3\CMS\Fluid\Core\Compiler\TemplateCompiler::SHOULD_GENERATE_VIEWHELPER_INVOCATION
like this:
public function compile(
$argumentsVariableName,
$renderChildrenClosureVariableName,
&$initializationPhpCode,
\TYPO3\CMS\Fluid\Core\Parser\SyntaxTree\AbstractNode $syntaxTreeNode,
\TYPO3\CMS\Fluid\Core\Compiler\TemplateCompiler $templateCompiler
) {
parent::compile(
$argumentsVariableName,
$renderChildrenClosureVariableName,
$initializationPhpCode,
$syntaxTreeNode,
$templateCompiler
);
return \TYPO3\CMS\Fluid\Core\Compiler\TemplateCompiler::SHOULD_GENERATE_VIEWHELPER_INVOCATION;
}
Related
I am a newcomer in Drupal, and I want to make a custom module in Drupal8.
I have developed the module, but there are some problems to solve.
The module displays GET parameter value when a page containing the module is shown to users.
For example, I connect with http://localhost/drupal/?keyword=banana and the module displays "banana".
But after the above, when I connect with http://localhost/drupal/?keyword=apple again, then the module displays "banana" too.
In other words, the module works well when the page containing the module is shown firstly and works wrong when I connect secondly, thirdly and so on.
I have tested some and build() method in the module is called only once.
So, I think that the module is rendered only once when I connect to the page and can't be rendered after the first.
Also, I think that it can be the problem related to cache, but I set admin/configuration/performance/cache to "no-cache".
I am not sure that it is possible to display "apple" after "banana" is displayed by the module.
Please help me and let me know more details...
Thanks.
There are a couple of possible solutions depending on your constraints: disable the cache for this particular page, or use routing wildcards.
You can disable the cache on a particular page by using the page cache kill switch service, which you trigger like this in your controller:
\Drupal::service('page_cache_kill_switch')->trigger();
This will disable the cache just for this particular request, so you won't get the effect of seeing stale content.
A better solution, if possible, is to use routing parameters instead of your GET parameters. This will allow your separate URLs (for example page/banana, page/apple etc.) to be cached and still show the contents you'd like them to. For example, in your module.routing.yml file:
mymodule.route:
path: '/path/{parameter}'
defaults:
_controller: '\Drupal\mymodule\Controller\MyModuleController::page'
_title: 'My Module Page'
requirements:
_permission: 'access content'
The {parameter} parameter can then be accessed in your controller like so:
public function page($parameter) {
return ['#markup' => $parameter];
}
More information: https://www.drupal.org/node/2186285
I am looking for opinions and alternate ideas, as what I am doing is working, but wanted to ask if it was optimal
I have a site that when the index handler is called, it populates the request collection with specific queries from database tables so that I can build drop downs for the user to select.
i am querying two models and putting their results in their respective variables, then loop thru them in the view to create the drop down
index Handler
function index(event, rc, prc){
event.paramValue("debug",0);
rc.stages = getmodel("tms_proposal_stage").select();
rc.plannedGiftTypes = getmodel("tms_funding_type").select();
event.setLayout('layout.bootstrap');
}
index view
<div class="form-group">
<label for="proposal_stage" class="control-label">Proposal Stage Code</label>
<select id="proposal_stage" name="proposal_stage" class="form-control">
<cfloop query="rc.stages">
<option value="#stage_code#">#short_desc#</option>
</cfloop>
</select>
</div>
I understand that two queries isnt that costly, but if I needed to run 100 of these that would have scalability issues. These query result sets do not change much, so I was thinking, shouldnt these be cached or stored and accessed a different way?
I thought about html5 local storage, which I have used but not in this regard.
I also considered making a new handler function that makes all of these database calls and is cached, then referenced by other functions
anyways, all thoughts are appreciated
You have several options available to you. Since you're using ColdBox, you have CacheBox readily available to you.
https://github.com/ColdBox/cbox-refcards/raw/master/CacheBox/CacheBox-Refcard.pdf
A very simple way to do inline caching of the data would be to inject a CacheBox provider at the top of your component:
component {
property name="cache" inject="cachebox:default";
}
Then use the cache API in your event to store and retrieve data. My favorite method is getOrSet() because it wraps it up in a single call.
rc.stages = cache.getOrSet(
objectKey="stages",
produce=function(){
return getmodel("tms_proposal_stage").select();
}
);
The closure is only executed if the key is not already in the cache.
http://wiki.coldbox.org/wiki/WhatsNew:CacheBox-1.6.cfm#Get_Or_Set_Baby
Another approach is to cache the full HTML. To do this, create a viewlet that only outputs the HTML for your form control. Create an event that returns the output of just that view like so:
function stagesFormInput(event, rc, prc) cache=true {
var stagesData = getmodel("tms_proposal_stage").select();
return renderView(view="viewlets/stages", args={ stagesData : stagesData } );
}
Note, I'm passing stageData directly into the view so it doesn't pollute the rc or prc. This data will be available in your viewlet as "args.stagesData".
Also note the "cache=true" in the method declaration. That's the magic that will tell ColdBox to cache this event (inside CacheBox's "template" provider"). You can specify a timeout, but this will use the default. Now, enabled eventCaching in your /config/ColdBox.cfc file.
coldbox={
eventCaching = true
}
http://wiki.coldbox.org/wiki/ConfigurationCFC.cfm#Application_Aspects
And finally, in your main view or layout, just run your new viewlet everywhere you want the cached HTML to be output.
#runEvent("viewlets.stagesFormInput")#
This is a little bit more setup, but is more powerful since it caches the full HTML snippet which is really ideal. I also have an entire sample app that demos this inside a working app. You can check it out here:
https://github.com/bdw429s/ColdBox-Viewlet-Sample
I have a module which allows the user to choose a category, which is then used for filtering the component's output. So when the user first clicks on the menu item, the view shows items from all categories, then as they click on the module, a param such as &catid=69 etc. is added to the url and used to filter the items displayed.
A system plugin complements the behaviour by registering the extra catid param i.e.
$registeredurlparams->catid = 'INT';
$app->set('registeredurlparams', $registeredurlparams);
The module uses the category id to create the cache id, and shows the top-level categories + the subcategories of the category that was chosen.
This works fine with both conservative cache enabled in the system configuration and the System Cache plugin enabled.
My concern is that I cannot get it to work with progressive cache: even though the component output is cached correctly, the module doesn't get updated (so I never see the subcategories).
Eventually I plan to make the extension available on the JED, and I'd like to be compatible with all possible cache configurations. Is there any possibility to force the progressive cache to add the parameters I want to the cache id?
Workarounds such as sending the full category tree and doing it with ajax will not be accepted.
One thing you could look at is ContentModelArticle in the back end. You will notice that cleanCache()
forcibly clears the content modules that could be impacted by a save or create.
protected function cleanCache($group = null, $client_id = 0)
{
parent::cleanCache('com_content');
parent::cleanCache('mod_articles_archive');
parent::cleanCache('mod_articles_categories');
parent::cleanCache('mod_articles_category');
parent::cleanCache('mod_articles_latest');
parent::cleanCache('mod_articles_news');
parent::cleanCache('mod_articles_popular');
}
I've always thought this was a sledge hammer/kludge since it doesn't let the webmaster control whether or not to do this, but you could do something along the lines of making a custom cleanCache() for your model.
I have an application where each user can choose a custom layout. The layouts can be different and it's not just css styles but html as well.
I know that mvc would cache the layout, but having so many layouts I doubt it would fit in cache. So what would it be better to save templates in DB or on the disk?
FYI: DB that I'm using is MongoDB.
I would save the layouts on disk because at the moment I don't see any advantage in a database (unless you do). But one thing that is worth mentioning is that you can create a class derived from OutputCacheAttribute and have your saved result depend on the layout you're using.
Does the layout depend on user? You could use the VaryByCustom property to have it vary by user.
EDIT
Are your users allowed to change layouts dinamically? If yes, you should also have a guid associated to your users change it each time the layouts change so you return on your VaryByCustom method:
return string.Format("User-{0}-{1}", user.Id, user.LayoutUpdateGuid);
See the meaning of this? This way, when a user changes the layouts, they will see their pages updated immediately.
How to apply the VaryByCustom attribute in your situation
In your action method, you may use:
[OutputCache(Duration = 3600, VaryByCustom = "UserLayouts")]
public ActionResult Details(string param)
{
// Returning the view
}
Then, in your VaryByCustom method in your Global.asax.cs file:
protected override string VaryByCustom(string custom)
{
switch (custom)
{
case "UserLayouts":
//// Here you fetch your user details so you can return a unique
//// string for each user and "publishing cycle"
//// Also, I strongly suggest you cache this user object and expire it
//// whenever the user is changed (e.g. when the LayoutUpdateGuid is
//// changed) so you achieve maximum speed and not defeat the purpose
//// of using output cache.
return string.Format("User-{0}-{1}", user.Id, user.LayoutUpdateGuid);
break;
}
}
The missing piece
The missing piece here is that you need to store a value that I called LayoutUpdateGuid (I'm sure you'll find a better name) and change that value whenever a user changes his layouts => this will lead to a different string being returned by the VaryByCustom(string) method in the Global.asasx.cs which in turn will force your action method to run again and return the result with the updated layout.
Makes sense to you?
Note: I can't test the specific code I wrote here, but I am sure (apart from typos) it is correct.
I wish to remove the following setting:
<cms>enterprise_pagecache/processor_default</cms>
... from the config.xml of the core / Enterprise / PageCache / config.xml file so that the home page will not be cached, (because we have a complicated custom store switch in place).
Since this value is not stored in core_config_data I am unsure of the best way to override the out of the box value. The comments above the line in the core file do hint that it is not actually bad practice to edit this file, however, can I open this to the community to see what they think?
PS = This is a multi website setup with a custom store switcher.
Hole punching is what it sounds like you may need.
Add a etc/cache.xml file with a <config> root to your module. (see Enterprise/PageCache/etc/cache.xml). Choose a unique [placeholder] name.
The placeholders/[placeholder]/block node value must match the class-id of your custom dynamic block, e.g. mymodule/custom
The placeholders/[placeholder]/container node value is the class to generate the content dynamically and handle block level caching
The placeholders/[placeholder]/placeholder node value is a unique string to mark the dynamic parts in the cached page
placeholders/[placeholder]/cache_lifetime is ignored, specify a block cache lifetime in the container’s _saveCache() method if needed
Implement the container class and extends Enterprise_PageCache_Model_Container_Abstract. Use _renderBlock() to return the dynamic content.
Implement the _getCacheId() method in the container to enable the block level caching. Use cookie values instead of model ids (lower cost).
One last note: You DON’T have the full Magento App at your disposal when _renderBlock() is called. Be as conservative as possible.
SOURCE: http://tweetorials.tumblr.com/post/10160075026/ee-full-page-cache-hole-punching