Yii2: Failed to instantiate component or class "cache".

Created on 25 Mar 2020  路  23Comments  路  Source: yiisoft/yii2

What steps will reproduce the problem?

Since version 2.0.33 the urlManager will throw an exception if cache component is not properly configured.

Failed to instantiate component or class "cache".

Now the out of the box setup process is disturbed i would say. Assuming the following config:

return [
'id' => 'luya-test-case',
'basePath' => dirname(__DIR__),
'components' => [
    'urlManager' => [
        'rules' => [
        // my rules goes here
        ]
    ],
    'db' => [
        'class' => 'yii\db\Connection',
        'dsn' => 'sqlite::memory:',
    ],
];

Before version 2.0.33 it was possible to run this code above, but since version 2.0.33 if have to either setup cache component (for example using DummyCache) or set urlManager::$cache to null.

  • In order to be strict in terms of configuration would either recommend to set urlManager::$cache to null by default (which requires people to take action to enable caching, which seems to be unpractical as well). (https://github.com/yiisoft/yii2/blob/master/framework/web/UrlManager.php#L135)
  • Or define DummyCache in coreComponents (https://github.com/yiisoft/yii2/blob/master/framework/base/Application.php#L624)
  • Or just revert that commit: https://github.com/yiisoft/yii2/pull/17890

Additional info

| Q | A
| ---------------- | ---
| Yii version | 2.0.33
| PHP version | all
| Operating system | all

under discussion

All 23 comments

@rob006 any idea on how it could be made better in terms of ease of configuration?

IMO current behavior of UrlManager is optimal. In most cases you want cache in UrlManager, and hiding misconfiguration is undesirable. We could move cache initialization below if (empty($this->rules)) condition, so it will not throw exception with default configuration (you don't need it anyway, if there are no rules).

i really don't understand what should be the benefit for developers in the current behavior, you are assuming that if someone is using urlManager he requires to configure cache component or otherwise configure the urlManager "properly".

In order to be consistent, it should be the opposite way at least (which i don't like either) => configure urlManager to use cache, then also define the cache.

But when dummy cache is a a core component, everyone would be happy too?

But when dummy cache is a a core component, everyone would be happy too?

No, this is even worse. You're still silently ignoring situation where cache is not working, bun not only in UrlManager - you're ignoring invalid cache configuration in entire application.

i really don't understand what should be the benefit for developers in the current behavior, you are assuming that if someone is using urlManager he requires to configure cache component or otherwise configure the urlManager "properly".

Actually I'm proposing solution where you can use UrlManager without any configuration, but if you're configuring it (by adding rules), you need to do it properly (adjust cache configuration if you don't use it). If you're already adding rules configuration, one additional line should not be a big deal (and in most cases it will not be needed anyway).

If you're already adding rules configuration, one additional line should not be a big deal

But not if you have already running thousands of applications out there and releasing such a changement as (defacto) patch release.

We (luya.io) inject urlRules while bootstrapping, so the urlManager is not needed in the configuration file, but we also don't force people to configure cache (sure its recommend) - now all those applications are broken.

https://www.yiiframework.com/doc/guide/2.0/en/runtime-routing#adding-rules this will not work anymore unless urlManager is configured in the config, which makes no sense to me.

https://www.yiiframework.com/doc/guide/2.0/en/runtime-routing#adding-rules this will not work anymore unless urlManager is configured in the config, which makes no sense to me.

Actually it should work if we implement https://github.com/yiisoft/yii2/issues/17933#issuecomment-603870256 - cache will not be initialized in this scenario and rules added by addRules() will not use cache. Which may be a problem if someone wants to use cache for dynamically added rules... :/

It does not seem that https://github.com/yiisoft/yii2/issues/17933#issuecomment-603870256 helps in any way.

@rob006 I don't see how dummy cache is equal to wrong configuration. To me it's not. It will works as it was by default while reacting to invalid cache configuration.

@rob006 I don't see how dummy cache is equal to wrong configuration. To me it's not.

It is cache that does not work, without any indication that it is not working - this is just terrible default. Imagine that you use Yii::$app->cache somewhere - right now you get exception that cache is not configured. With dummy cache it will just move on without any indication that cache does not work at all and Yii::$app->cache does nothing.

Yes but that's how it worked before. Default was "no cache".

Yes but that's how it worked before.

It worked that way in UrlManager. After #17940 it will work that way globally - even explicit calls to cache component will silently ignore the fact, that cache does not work.

If we want default cache settings, it should be something that works (FileCache?).
If only UrlManager is the problem, I would catch this exception and convert it to warning.

To bring in a new idea: What if we implement a new cache type like InMemoryCache (or the like)? It would work similar to a DummyCache i.e. it's not a "real" cache - but it would at least store all cached values internally e.g. in an array. So get() and set() would work properly but cached values are lost after each request (or after command line script ends).

This could then be the new default cache component.

It worked that way in UrlManager. After #17940 it will work that way globally - even explicit calls to cache component will silently ignore the fact, that cache does not work.

If it's not configured - yes. In majority of Yii components there are checks for cache === null so if it's not configured, everything silently works without cache.

If we want default cache settings, it should be something that works (FileCache?).

It is default in application templates.

If only UrlManager is the problem, I would catch this exception and convert it to warning.

You mean logging a warning?

@mikehaertl using yii\caching\ArrayCache (https://www.yiiframework.com/doc/api/2.0/yii-caching-arraycache) instead of dummy cache is what you mean i guess?

Yeah, right, nevermind then. Also not really fix for this issue. I did not read everything before responding.

Actually I'd vote to set UrlManager::$cache to null by default and add an upgrade note to 2.0.34.

I would prefer to reset https://github.com/yiisoft/yii2/pull/17890, so everything was like it always has been for all the applications out there.

@mikehaertl It already exists: https://www.yiiframework.com/doc/api/2.0/yii-caching-arraycache
And this is cache that in most cases is equivalent to no cache, but also brings memory issues for processes with many writes.

If it's not configured - yes. In majority of Yii components there are checks for cache === null so if it's not configured, everything silently works without cache.

In most cases you have separate flag (like enableSchemaCache). It is counter-intuitive that enabling DB schema cache does not work, because default cache does not work.

It is default in application templates.

Then why do we care about this issue? :D Environments without cache is an edge case.

You mean logging a warning?

Yes.

Then why do we care about this issue? :D Environments without cache is an edge case.

Unit Tests for example. Anyhow i would not make assumption based on your personal opinion, even you might be right.

@rob006 What's your argument against UrlManager::$cache = null by default? IMO the situation now can't be solved without BC break anyway.

What's your argument against UrlManager::$cache = null by default?

Because it will introduce performance regression, which is the worse regression possible, since it will be hard to notice. It is also not pragmatic - in most cases you have cache configured and you want to use it in UrlManager. Optimizing default configuration for an edge case does not seems to like Yii-way.

IMO the situation now can't be solved without BC break anyway.

Converting exception to Yii::warning() should be BC and still give you a clue that your configuration is not optimal.

Logging a warning sounds like a compromise but it would spam logs a lot in @nadar case.

I agree that a warning would be fine. If the log is spammed, you can still set UrlManager::$cache to null in your config. (Could even be mentioned in the warning)

The root problem is that there should never have been a hardcoded component id (cache) that is not a core component. And we can't just add new core components now.

I've adjusted pull request.

Was this page helpful?
0 / 5 - 0 ratings