mirror of
https://github.com/yiisoft/yii2.git
synced 2025-08-26 14:26:54 +08:00
Fixes #14449: Fix PHP 7.2 compatibility bugs and add explicit closure support in yii\base\Application
This commit is contained in:

committed by
Alexander Makarov

parent
b0162d3a48
commit
03d53b785d
@ -58,12 +58,22 @@ If it is not accessed at all during a request, it will not be instantiated. Some
|
||||
to instantiate an application component for every request, even if it is not explicitly accessed.
|
||||
To do so, you may list its ID in the [[yii\base\Application::bootstrap|bootstrap]] property of the application.
|
||||
|
||||
You can also use Closures to bootstrap customized components. Returning a instantiated component is not
|
||||
required. A Closure can also be used simply for running code after [[yii\base\Application]] instantiation.
|
||||
|
||||
For example, the following application configuration makes sure the `log` component is always loaded:
|
||||
|
||||
```php
|
||||
[
|
||||
'bootstrap' => [
|
||||
'log',
|
||||
function($app){
|
||||
return new ComponentX();
|
||||
},
|
||||
function($app){
|
||||
// some code
|
||||
return;
|
||||
}
|
||||
],
|
||||
'components' => [
|
||||
'log' => [
|
||||
|
@ -3,7 +3,7 @@ Yii Framework 2 Change Log
|
||||
|
||||
2.0.13 under development
|
||||
------------------------
|
||||
|
||||
- Bug #14449: Fix PHP 7.2 compatibility bugs and add explicit closure support in `yii\base\Application` (dynasource)
|
||||
- Bug #7890: Allow `migrate/mark` to mark history at the point of the base migration (cebe)
|
||||
- Bug #14206: `MySqlMutex`, `PgsqlMutex` and `OracleMutex` now use `useMaster()` to ensure lock is aquired on the same DB server (cebe, ryusoft)
|
||||
- Chg #14321: `yii\widgets\MaskedInput` is now registering its JavaScript `clientOptions` initialization code in head section (DaveFerger)
|
||||
|
@ -168,6 +168,7 @@ abstract class Application extends Module
|
||||
* - a module ID as specified via [[modules]].
|
||||
* - a class name.
|
||||
* - a configuration array.
|
||||
* - a Closure
|
||||
*
|
||||
* During the bootstrapping process, each component will be instantiated. If the component class
|
||||
* implements [[BootstrapInterface]], its [[BootstrapInterface::bootstrap()|bootstrap()]] method
|
||||
@ -300,19 +301,25 @@ abstract class Application extends Module
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($this->bootstrap as $class) {
|
||||
foreach ($this->bootstrap as $mixed) {
|
||||
$component = null;
|
||||
if (is_string($class)) {
|
||||
if ($this->has($class)) {
|
||||
$component = $this->get($class);
|
||||
} elseif ($this->hasModule($class)) {
|
||||
$component = $this->getModule($class);
|
||||
} elseif (strpos($class, '\\') === false) {
|
||||
throw new InvalidConfigException("Unknown bootstrapping component ID: $class");
|
||||
if ($mixed instanceof \Closure) {
|
||||
Yii::trace('Bootstrap with Closure', __METHOD__);
|
||||
if (!$component = call_user_func($mixed, $this)) {
|
||||
continue;
|
||||
}
|
||||
} elseif (is_string($mixed)) {
|
||||
if ($this->has($mixed)) {
|
||||
$component = $this->get($mixed);
|
||||
} elseif ($this->hasModule($mixed)) {
|
||||
$component = $this->getModule($mixed);
|
||||
} elseif (strpos($mixed, '\\') === false) {
|
||||
throw new InvalidConfigException("Unknown bootstrapping component ID: $mixed");
|
||||
}
|
||||
}
|
||||
|
||||
if (!isset($component)) {
|
||||
$component = Yii::createObject($class);
|
||||
$component = Yii::createObject($mixed);
|
||||
}
|
||||
|
||||
if ($component instanceof BootstrapInterface) {
|
||||
|
@ -1350,7 +1350,7 @@ class QueryBuilder extends \yii\base\Object
|
||||
$values = (array) $values;
|
||||
}
|
||||
|
||||
if ($column instanceof \Traversable || count($column) > 1) {
|
||||
if ($column instanceof \Traversable || ((is_array($column) || $column instanceof \Countable) && count($column) > 1)) {
|
||||
return $this->buildCompositeInCondition($operator, $column, $values, $params);
|
||||
} elseif (is_array($column)) {
|
||||
$column = reset($column);
|
||||
|
@ -8,6 +8,9 @@
|
||||
namespace yiiunit\framework\base;
|
||||
|
||||
use Yii;
|
||||
use yii\base\BootstrapInterface;
|
||||
use yii\base\Component;
|
||||
use yii\base\Module;
|
||||
use yii\log\Dispatcher;
|
||||
use yiiunit\TestCase;
|
||||
|
||||
@ -29,8 +32,50 @@ class ApplicationTest extends TestCase
|
||||
|
||||
$this->assertInstanceOf(DispatcherMock::className(), Yii::$app->log);
|
||||
}
|
||||
|
||||
public function testBootstrap()
|
||||
{
|
||||
Yii::getLogger()->flush();
|
||||
|
||||
|
||||
$this->mockApplication([
|
||||
'components' => [
|
||||
'withoutBootstrapInterface' => [
|
||||
'class' => Component::class
|
||||
],
|
||||
'withBootstrapInterface' => [
|
||||
'class' => BootstrapComponentMock::class
|
||||
]
|
||||
],
|
||||
'modules' => [
|
||||
'moduleX' => [
|
||||
'class' => Module::class
|
||||
]
|
||||
],
|
||||
'bootstrap' => [
|
||||
'withoutBootstrapInterface',
|
||||
'withBootstrapInterface',
|
||||
'moduleX',
|
||||
function () {
|
||||
}
|
||||
|
||||
],
|
||||
]);
|
||||
$this->assertSame('Bootstrap with yii\base\Component', Yii::getLogger()->messages[0][0]);
|
||||
$this->assertSame('Bootstrap with yiiunit\framework\base\BootstrapComponentMock::bootstrap()', Yii::getLogger()->messages[1][0]);
|
||||
$this->assertSame('Loading module: moduleX', Yii::getLogger()->messages[2][0]);
|
||||
$this->assertSame('Bootstrap with yii\base\Module', Yii::getLogger()->messages[3][0]);
|
||||
$this->assertSame('Bootstrap with Closure', Yii::getLogger()->messages[4][0]);
|
||||
}
|
||||
}
|
||||
|
||||
class DispatcherMock extends Dispatcher
|
||||
{
|
||||
}
|
||||
|
||||
class BootstrapComponentMock extends Component implements BootstrapInterface
|
||||
{
|
||||
public function bootstrap($app)
|
||||
{
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user