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 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.
|
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:
|
For example, the following application configuration makes sure the `log` component is always loaded:
|
||||||
|
|
||||||
```php
|
```php
|
||||||
[
|
[
|
||||||
'bootstrap' => [
|
'bootstrap' => [
|
||||||
'log',
|
'log',
|
||||||
|
function($app){
|
||||||
|
return new ComponentX();
|
||||||
|
},
|
||||||
|
function($app){
|
||||||
|
// some code
|
||||||
|
return;
|
||||||
|
}
|
||||||
],
|
],
|
||||||
'components' => [
|
'components' => [
|
||||||
'log' => [
|
'log' => [
|
||||||
|
@ -3,7 +3,7 @@ Yii Framework 2 Change Log
|
|||||||
|
|
||||||
2.0.13 under development
|
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 #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)
|
- 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)
|
- 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 module ID as specified via [[modules]].
|
||||||
* - a class name.
|
* - a class name.
|
||||||
* - a configuration array.
|
* - a configuration array.
|
||||||
|
* - a Closure
|
||||||
*
|
*
|
||||||
* During the bootstrapping process, each component will be instantiated. If the component class
|
* During the bootstrapping process, each component will be instantiated. If the component class
|
||||||
* implements [[BootstrapInterface]], its [[BootstrapInterface::bootstrap()|bootstrap()]] method
|
* 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;
|
$component = null;
|
||||||
if (is_string($class)) {
|
if ($mixed instanceof \Closure) {
|
||||||
if ($this->has($class)) {
|
Yii::trace('Bootstrap with Closure', __METHOD__);
|
||||||
$component = $this->get($class);
|
if (!$component = call_user_func($mixed, $this)) {
|
||||||
} elseif ($this->hasModule($class)) {
|
continue;
|
||||||
$component = $this->getModule($class);
|
}
|
||||||
} elseif (strpos($class, '\\') === false) {
|
} elseif (is_string($mixed)) {
|
||||||
throw new InvalidConfigException("Unknown bootstrapping component ID: $class");
|
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)) {
|
if (!isset($component)) {
|
||||||
$component = Yii::createObject($class);
|
$component = Yii::createObject($mixed);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($component instanceof BootstrapInterface) {
|
if ($component instanceof BootstrapInterface) {
|
||||||
|
@ -1350,7 +1350,7 @@ class QueryBuilder extends \yii\base\Object
|
|||||||
$values = (array) $values;
|
$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);
|
return $this->buildCompositeInCondition($operator, $column, $values, $params);
|
||||||
} elseif (is_array($column)) {
|
} elseif (is_array($column)) {
|
||||||
$column = reset($column);
|
$column = reset($column);
|
||||||
|
@ -8,6 +8,9 @@
|
|||||||
namespace yiiunit\framework\base;
|
namespace yiiunit\framework\base;
|
||||||
|
|
||||||
use Yii;
|
use Yii;
|
||||||
|
use yii\base\BootstrapInterface;
|
||||||
|
use yii\base\Component;
|
||||||
|
use yii\base\Module;
|
||||||
use yii\log\Dispatcher;
|
use yii\log\Dispatcher;
|
||||||
use yiiunit\TestCase;
|
use yiiunit\TestCase;
|
||||||
|
|
||||||
@ -29,8 +32,50 @@ class ApplicationTest extends TestCase
|
|||||||
|
|
||||||
$this->assertInstanceOf(DispatcherMock::className(), Yii::$app->log);
|
$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 DispatcherMock extends Dispatcher
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class BootstrapComponentMock extends Component implements BootstrapInterface
|
||||||
|
{
|
||||||
|
public function bootstrap($app)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user