advanced yii project (multiple apps with different routes) uses same key that is hardcoded into yii\\web\\UrlManager
protected $cacheKey = __CLASS__;
this would case hash to always be a miss, each hit will do both get and set
if ($this->cache instanceof Cache) {
$cacheKey = $this->cacheKey;
$hash = md5(json_encode($this->rules));
if (($data = $this->cache->get($cacheKey)) !== false && isset($data[1]) && $data[1] === $hash) {
$this->rules = $data[0];
} else {
the solution is to suffix cacheKey with let's say basepath or app name ...etc.
Why would that be a miss?
because the hash of app1 (frontend) routing rules is different than the hash of app2 (backend) routing rules
this condition $data[1] === $hash will always be false because it would be set by the other app
Ah, right. Should be prefixed.
Do you want to implement a fix?
@samdark yes, I've opened a PR. that adds Yii::getAlias('@app')
Maybe better to add the ability to add parameters to the cacheKey, or declare it as public?
For example if site is multidomainable and rules can be different by domain
Maybe better to add the ability to add parameters to the cacheKey, or declare it as public?
I'm fine with calling it a cacheKeyPrefix and making it public (and always append @app to it).
Already have keyPrefix: https://github.com/yiisoft/yii2/blob/master/framework/caching/Cache.php#L60
not prefix per cache component! but prefix per UrlManagers
@kidol let's start with advanced yii templates, we have common, backend and frontend apps/subprojects, cache defined in common have a single keyPrefix. the key prefix in UrlManager is UrlManager (class name) to be added to the common key prefix of course, then we append to it the path to the subproject base path using @app because backend and frontend have different routes.
And what if Cache.keyPrefix supported @app alias and maybe even default to it? Would that work?
// hmm probably not because you call urlmanager of frontend in backend for example...?
I just think it's ugly to have 2 different places to define prefix.
And what if Cache.keyPrefix supported
@appalias and maybe even default to it? Would that work?
I like this idea.
it would work except for the case of generating links from backend to front end (having two components, because @app of the two is the same, in this case the user have to pass custom cache key)
@muayyad-alsadi Another solution might be to use different cache components for each UrlManager. Or for simplicity, you could simply set the $cache of the backend UrlManager to false.
@kidol that would work, but it's very unexpected.
Instead of using the alias I'd prefer to include Yii::$app->id into the key instead. This is much less overhead and id must be defined for every application.
Sounds much better.
@muayyad-alsadi
good point. Less execution the better.
@cebe I've looked on the apps I work on and they all seems to have really unique $app->id so do yii advanced project template
but I still believe using the @app directory is a fool proof way. I believe the cost of getAliase is just str_replace or something like that right?
but the question how are we going to specify $app->id ?
my major concern is the following case
both console and api need to generate links to frontend
we have a config/main.php in api app like this
'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'rules' => require 'api-urls.php',
],
'urlManagerWeb' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'rules' => require 'web-urls.php',
'cacheKey'=>'@webapp/UrlManager' // <--- this line
],
regarding the last config line, if it's cacheKey we can't say Yii::$otherApp->id.'/UrlManager'
and changing it to cacheKeyPrefix or cacheKeySuffix and adding Yii::$app->id by the code would add the wrong id.
@cebe would you please consider two apps with the need to generate urls from one to another, how are you going to solve this?
imo it's fine if two different apps have different cache by default (isn't that the point of the whole issue here?). If you want to share their cache you can still configure the cache key to be the same.
@cebe the issue here is that having the same cache key but different rules hashing (due to different rules 'rules' => require 'other-app-urls.php') cases a flood of unnessery get/set on memcached
we need two different cache keys for urlManager and urlManagerWeb both belonging to the same web api app (because it needs to generate links to web ui app). how are you going to pass it different key?
remember the settings is in main.php which is too early to call Yii::$otherApp->id (I even don't know if there is such thing)
'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'rules' => require 'api-urls.php',
],
'urlManagerWeb' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'rules' => require 'web-urls.php',
'cacheKey'=> Yii::$otherApp->id.'/urlManager' // look at this line <-------
],
If you use two different UrlManagers in the same Application instance you have to configure different cache keys yourself. Neither adding Yii::$app->id nor using @app alias solves this problem as they are the same for both components.
Looking at the implementation of UrlManager caching I wonder why $hash is not part of the cache key instead of storing it with the data. using $hash as the cache key would solve this issue as far as I see.
I accept adding $hash to the cache key, but in that case we need to add TTL that defaults to let's say 5 minutes and make it public so people can set it for let's say 1 day or 0 for no ttl (if that is possible).
for me I suggest one or more of the following
Probably fixed by #13426.
/cc @cebe @SilverFire
Yes, the PR will probably fix this issue.
Friends, could you check the problem after the merged PR? (in dev-master currently)
can we have a way to set ttl via component public property?
a public component property to set custom key prefix?
Hi @samdark , can we implement Yii::error to catch Memcached::getResultMessage when Memcached::getResultCode fail ?
http://php.net/manual/en/memcached.getresultcode.php
Sometimes memcache throw error, but Yii didn't gave us notice
like cache item exceeded/chunk fail, connection timeout, etc
@xicond that sounds like a separate issue. Please create one.
Probably fixed by #13426.
/cc @cebe @SilverFire
seems to be fixed.
Most helpful comment
Instead of using the alias I'd prefer to include
Yii::$app->idinto the key instead. This is much less overhead and id must be defined for every application.