1 | <?php |
||
2 | |||
3 | /* |
||
4 | * This file is part of the overtrue/wechat. |
||
5 | * |
||
6 | * (c) overtrue <[email protected]> |
||
7 | * |
||
8 | * This source file is subject to the MIT license that is bundled |
||
9 | * with this source code in the file LICENSE. |
||
10 | */ |
||
11 | |||
12 | namespace EasyWeChat\Kernel\Log; |
||
13 | |||
14 | use EasyWeChat\Kernel\ServiceContainer; |
||
15 | use InvalidArgumentException; |
||
16 | use Monolog\Formatter\LineFormatter; |
||
17 | use Monolog\Handler\ErrorLogHandler; |
||
18 | use Monolog\Handler\FormattableHandlerInterface; |
||
19 | use Monolog\Handler\HandlerInterface; |
||
20 | use Monolog\Handler\RotatingFileHandler; |
||
21 | use Monolog\Handler\SlackWebhookHandler; |
||
22 | use Monolog\Handler\StreamHandler; |
||
23 | use Monolog\Handler\SyslogHandler; |
||
24 | use Monolog\Handler\WhatFailureGroupHandler; |
||
25 | use Monolog\Logger as Monolog; |
||
26 | use Psr\Log\LoggerInterface; |
||
27 | |||
28 | /** |
||
29 | * Class LogManager. |
||
30 | * |
||
31 | * @author overtrue <[email protected]> |
||
32 | */ |
||
33 | class LogManager implements LoggerInterface |
||
34 | { |
||
35 | /** |
||
36 | * @var \EasyWeChat\Kernel\ServiceContainer |
||
37 | */ |
||
38 | protected $app; |
||
39 | |||
40 | /** |
||
41 | * The array of resolved channels. |
||
42 | * |
||
43 | * @var array |
||
44 | */ |
||
45 | protected $channels = []; |
||
46 | |||
47 | /** |
||
48 | * The registered custom driver creators. |
||
49 | * |
||
50 | * @var array |
||
51 | */ |
||
52 | protected $customCreators = []; |
||
53 | |||
54 | /** |
||
55 | * The Log levels. |
||
56 | * |
||
57 | * @var array |
||
58 | */ |
||
59 | protected $levels = [ |
||
60 | 'debug' => Monolog::DEBUG, |
||
61 | 'info' => Monolog::INFO, |
||
62 | 'notice' => Monolog::NOTICE, |
||
63 | 'warning' => Monolog::WARNING, |
||
64 | 'error' => Monolog::ERROR, |
||
65 | 'critical' => Monolog::CRITICAL, |
||
66 | 'alert' => Monolog::ALERT, |
||
67 | 'emergency' => Monolog::EMERGENCY, |
||
68 | ]; |
||
69 | |||
70 | /** |
||
71 | * LogManager constructor. |
||
72 | * |
||
73 | * @param \EasyWeChat\Kernel\ServiceContainer $app |
||
74 | */ |
||
75 | 290 | public function __construct(ServiceContainer $app) |
|
76 | { |
||
77 | 290 | $this->app = $app; |
|
78 | 290 | } |
|
79 | |||
80 | /** |
||
81 | * Create a new, on-demand aggregate logger instance. |
||
82 | * |
||
83 | * @param array $channels |
||
84 | * @param string|null $channel |
||
85 | * |
||
86 | * @return \Psr\Log\LoggerInterface |
||
87 | * |
||
88 | * @throws \Exception |
||
89 | */ |
||
90 | 1 | public function stack(array $channels, $channel = null) |
|
91 | { |
||
92 | 1 | return $this->createStackDriver(compact('channels', 'channel')); |
|
93 | } |
||
94 | |||
95 | /** |
||
96 | * Get a log channel instance. |
||
97 | * |
||
98 | * @param string|null $channel |
||
99 | * |
||
100 | * @return mixed |
||
101 | * |
||
102 | * @throws \Exception |
||
103 | */ |
||
104 | 2 | public function channel($channel = null) |
|
105 | { |
||
106 | 2 | return $this->driver($channel); |
|
107 | } |
||
108 | |||
109 | /** |
||
110 | * Get a log driver instance. |
||
111 | * |
||
112 | * @param string|null $driver |
||
113 | * |
||
114 | * @return mixed |
||
115 | * |
||
116 | * @throws \Exception |
||
117 | */ |
||
118 | 8 | public function driver($driver = null) |
|
119 | { |
||
120 | 8 | return $this->get($driver ?? $this->getDefaultDriver()); |
|
121 | } |
||
122 | |||
123 | /** |
||
124 | * Attempt to get the log from the local cache. |
||
125 | * |
||
126 | * @param string $name |
||
127 | * |
||
128 | * @return \Psr\Log\LoggerInterface |
||
129 | * |
||
130 | * @throws \Exception |
||
131 | */ |
||
132 | 8 | protected function get($name) |
|
133 | { |
||
134 | try { |
||
135 | 8 | return $this->channels[$name] ?? ($this->channels[$name] = $this->resolve($name)); |
|
136 | 4 | } catch (\Throwable $e) { |
|
137 | 4 | $logger = $this->createEmergencyLogger(); |
|
138 | |||
139 | 4 | $logger->emergency('Unable to create configured logger. Using emergency logger.', [ |
|
140 | 4 | 'exception' => $e, |
|
141 | ]); |
||
142 | |||
143 | 4 | return $logger; |
|
144 | } |
||
145 | } |
||
146 | |||
147 | /** |
||
148 | * Resolve the given log instance by name. |
||
149 | * |
||
150 | * @param string $name |
||
151 | * |
||
152 | * @return \Psr\Log\LoggerInterface |
||
153 | * |
||
154 | * @throws InvalidArgumentException |
||
155 | */ |
||
156 | 8 | protected function resolve($name) |
|
157 | { |
||
158 | 8 | $config = $this->app['config']->get(\sprintf('log.channels.%s', $name)); |
|
159 | |||
160 | 8 | if (is_null($config)) { |
|
161 | 2 | throw new InvalidArgumentException(\sprintf('Log [%s] is not defined.', $name)); |
|
162 | } |
||
163 | |||
164 | 6 | if (isset($this->customCreators[$config['driver']])) { |
|
165 | 1 | return $this->callCustomCreator($config); |
|
166 | } |
||
167 | |||
168 | 5 | $driverMethod = 'create'.ucfirst($config['driver']).'Driver'; |
|
169 | |||
170 | 5 | if (method_exists($this, $driverMethod)) { |
|
171 | 4 | return $this->{$driverMethod}($config); |
|
172 | } |
||
173 | |||
174 | 1 | throw new InvalidArgumentException(\sprintf('Driver [%s] is not supported.', $config['driver'])); |
|
175 | } |
||
176 | |||
177 | /** |
||
178 | * Create an emergency log handler to avoid white screens of death. |
||
179 | * |
||
180 | * @return \Monolog\Logger |
||
181 | * |
||
182 | * @throws \Exception |
||
183 | */ |
||
184 | 2 | protected function createEmergencyLogger() |
|
185 | { |
||
186 | 2 | return new Monolog('EasyWeChat', $this->prepareHandlers([new StreamHandler( |
|
187 | 2 | \sys_get_temp_dir().'/easywechat/easywechat.log', |
|
188 | 2 | $this->level(['level' => 'debug']) |
|
189 | )])); |
||
190 | } |
||
191 | |||
192 | /** |
||
193 | * Call a custom driver creator. |
||
194 | * |
||
195 | * @param array $config |
||
196 | * |
||
197 | * @return mixed |
||
198 | */ |
||
199 | 1 | protected function callCustomCreator(array $config) |
|
200 | { |
||
201 | 1 | return $this->customCreators[$config['driver']]($this->app, $config); |
|
202 | } |
||
203 | |||
204 | /** |
||
205 | * Create an aggregate log driver instance. |
||
206 | * |
||
207 | * @param array $config |
||
208 | * |
||
209 | * @return \Monolog\Logger |
||
210 | * |
||
211 | * @throws \Exception |
||
212 | */ |
||
213 | 2 | protected function createStackDriver(array $config) |
|
214 | { |
||
215 | 2 | $handlers = []; |
|
216 | |||
217 | 2 | foreach ($config['channels'] ?? [] as $channel) { |
|
218 | 2 | $handlers = \array_merge($handlers, $this->channel($channel)->getHandlers()); |
|
0 ignored issues
–
show
Bug
introduced
by
![]() |
|||
219 | } |
||
220 | |||
221 | 2 | if ($config['ignore_exceptions'] ?? false) { |
|
222 | $handlers = [new WhatFailureGroupHandler($handlers)]; |
||
223 | } |
||
224 | |||
225 | 2 | return new Monolog($this->parseChannel($config), $handlers); |
|
226 | } |
||
227 | |||
228 | /** |
||
229 | * Create an instance of the single file log driver. |
||
230 | * |
||
231 | * @param array $config |
||
232 | * |
||
233 | * @return \Psr\Log\LoggerInterface |
||
234 | * |
||
235 | * @throws \Exception |
||
236 | */ |
||
237 | 2 | protected function createSingleDriver(array $config) |
|
238 | { |
||
239 | 2 | return new Monolog($this->parseChannel($config), [ |
|
240 | 2 | $this->prepareHandler(new StreamHandler( |
|
241 | 2 | $config['path'], |
|
242 | 1 | $this->level($config), |
|
243 | 1 | $config['bubble'] ?? true, |
|
244 | 1 | $config['permission'] ?? null, |
|
245 | 1 | $config['locking'] ?? false |
|
246 | ), $config), |
||
247 | ]); |
||
248 | } |
||
249 | |||
250 | /** |
||
251 | * Create an instance of the daily file log driver. |
||
252 | * |
||
253 | * @param array $config |
||
254 | * |
||
255 | * @return \Psr\Log\LoggerInterface |
||
256 | */ |
||
257 | 1 | protected function createDailyDriver(array $config) |
|
258 | { |
||
259 | 1 | return new Monolog($this->parseChannel($config), [ |
|
260 | 1 | $this->prepareHandler(new RotatingFileHandler( |
|
261 | 1 | $config['path'], |
|
262 | 1 | $config['days'] ?? 7, |
|
263 | 1 | $this->level($config), |
|
264 | 1 | $config['bubble'] ?? true, |
|
265 | 1 | $config['permission'] ?? null, |
|
266 | 1 | $config['locking'] ?? false |
|
267 | ), $config), |
||
268 | ]); |
||
269 | } |
||
270 | |||
271 | /** |
||
272 | * Create an instance of the Slack log driver. |
||
273 | * |
||
274 | * @param array $config |
||
275 | * |
||
276 | * @return \Psr\Log\LoggerInterface |
||
277 | */ |
||
278 | 1 | protected function createSlackDriver(array $config) |
|
279 | { |
||
280 | 1 | return new Monolog($this->parseChannel($config), [ |
|
281 | 1 | $this->prepareHandler(new SlackWebhookHandler( |
|
282 | 1 | $config['url'], |
|
283 | 1 | $config['channel'] ?? null, |
|
284 | 1 | $config['username'] ?? 'EasyWeChat', |
|
285 | 1 | $config['attachment'] ?? true, |
|
286 | 1 | $config['emoji'] ?? ':boom:', |
|
287 | 1 | $config['short'] ?? false, |
|
288 | 1 | $config['context'] ?? true, |
|
289 | 1 | $this->level($config), |
|
290 | 1 | $config['bubble'] ?? true, |
|
291 | 1 | $config['exclude_fields'] ?? [] |
|
292 | ), $config), |
||
293 | ]); |
||
294 | } |
||
295 | |||
296 | /** |
||
297 | * Create an instance of the syslog log driver. |
||
298 | * |
||
299 | * @param array $config |
||
300 | * |
||
301 | * @return \Psr\Log\LoggerInterface |
||
302 | */ |
||
303 | 1 | protected function createSyslogDriver(array $config) |
|
304 | { |
||
305 | 1 | return new Monolog($this->parseChannel($config), [ |
|
306 | 1 | $this->prepareHandler(new SyslogHandler( |
|
307 | 1 | 'EasyWeChat', |
|
308 | 1 | $config['facility'] ?? LOG_USER, |
|
309 | 1 | $this->level($config) |
|
310 | ), $config), |
||
311 | ]); |
||
312 | } |
||
313 | |||
314 | /** |
||
315 | * Create an instance of the "error log" log driver. |
||
316 | * |
||
317 | * @param array $config |
||
318 | * |
||
319 | * @return \Psr\Log\LoggerInterface |
||
320 | */ |
||
321 | 2 | protected function createErrorlogDriver(array $config) |
|
322 | { |
||
323 | 2 | return new Monolog($this->parseChannel($config), [ |
|
324 | 2 | $this->prepareHandler( |
|
325 | 2 | new ErrorLogHandler( |
|
326 | 2 | $config['type'] ?? ErrorLogHandler::OPERATING_SYSTEM, |
|
327 | 2 | $this->level($config) |
|
328 | ) |
||
329 | ), |
||
330 | ]); |
||
331 | } |
||
332 | |||
333 | /** |
||
334 | * Prepare the handlers for usage by Monolog. |
||
335 | * |
||
336 | * @param array $handlers |
||
337 | * |
||
338 | * @return array |
||
339 | */ |
||
340 | 2 | protected function prepareHandlers(array $handlers) |
|
341 | { |
||
342 | 2 | foreach ($handlers as $key => $handler) { |
|
343 | 2 | $handlers[$key] = $this->prepareHandler($handler); |
|
344 | } |
||
345 | |||
346 | 2 | return $handlers; |
|
347 | } |
||
348 | |||
349 | /** |
||
350 | * Prepare the handler for usage by Monolog. |
||
351 | * |
||
352 | * @param \Monolog\Handler\HandlerInterface $handler |
||
353 | * |
||
354 | * @return \Monolog\Handler\HandlerInterface |
||
355 | */ |
||
356 | 3 | protected function prepareHandler(HandlerInterface $handler, array $config = []) |
|
357 | { |
||
358 | 3 | if (!isset($config['formatter'])) { |
|
359 | 3 | if ($handler instanceof FormattableHandlerInterface) { |
|
360 | 3 | $handler->setFormatter($this->formatter()); |
|
361 | } |
||
362 | } |
||
363 | |||
364 | 3 | return $handler; |
|
365 | } |
||
366 | |||
367 | /** |
||
368 | * Get a Monolog formatter instance. |
||
369 | * |
||
370 | * @return \Monolog\Formatter\FormatterInterface |
||
371 | */ |
||
372 | 3 | protected function formatter() |
|
373 | { |
||
374 | 3 | $formatter = new LineFormatter(null, null, true, true); |
|
375 | 3 | $formatter->includeStacktraces(); |
|
376 | |||
377 | 3 | return $formatter; |
|
378 | } |
||
379 | |||
380 | /** |
||
381 | * Extract the log channel from the given configuration. |
||
382 | * |
||
383 | * @param array $config |
||
384 | * |
||
385 | * @return string |
||
386 | */ |
||
387 | 2 | protected function parseChannel(array $config) |
|
388 | { |
||
389 | 2 | return $config['name'] ?? 'EasyWeChat'; |
|
390 | } |
||
391 | |||
392 | /** |
||
393 | * Parse the string level into a Monolog constant. |
||
394 | * |
||
395 | * @param array $config |
||
396 | * |
||
397 | * @return int |
||
398 | * |
||
399 | * @throws InvalidArgumentException |
||
400 | */ |
||
401 | 4 | protected function level(array $config) |
|
402 | { |
||
403 | 4 | $level = $config['level'] ?? 'debug'; |
|
404 | |||
405 | 4 | if (isset($this->levels[$level])) { |
|
406 | 3 | return $this->levels[$level]; |
|
407 | } |
||
408 | |||
409 | 1 | throw new InvalidArgumentException('Invalid log level.'); |
|
410 | } |
||
411 | |||
412 | /** |
||
413 | * Get the default log driver name. |
||
414 | * |
||
415 | * @return string |
||
416 | */ |
||
417 | 3 | public function getDefaultDriver() |
|
418 | { |
||
419 | 3 | return $this->app['config']['log.default']; |
|
420 | } |
||
421 | |||
422 | /** |
||
423 | * Set the default log driver name. |
||
424 | * |
||
425 | * @param string $name |
||
426 | */ |
||
427 | 1 | public function setDefaultDriver($name) |
|
428 | { |
||
429 | 1 | $this->app['config']['log.default'] = $name; |
|
430 | 1 | } |
|
431 | |||
432 | /** |
||
433 | * Register a custom driver creator Closure. |
||
434 | * |
||
435 | * @param string $driver |
||
436 | * @param \Closure $callback |
||
437 | * |
||
438 | * @return $this |
||
439 | */ |
||
440 | 1 | public function extend($driver, \Closure $callback) |
|
441 | { |
||
442 | 1 | $this->customCreators[$driver] = $callback->bindTo($this, $this); |
|
443 | |||
444 | 1 | return $this; |
|
445 | } |
||
446 | |||
447 | /** |
||
448 | * System is unusable. |
||
449 | * |
||
450 | * @param string $message |
||
451 | * @param array $context |
||
452 | * |
||
453 | * @return mixed |
||
454 | * |
||
455 | * @throws \Exception |
||
456 | */ |
||
457 | 1 | public function emergency($message, array $context = []) |
|
458 | { |
||
459 | 1 | return $this->driver()->emergency($message, $context); |
|
0 ignored issues
–
show
Are you sure the usage of
$this->driver()->emergency($message, $context) targeting Psr\Log\LoggerInterface::emergency() seems to always return null.
This check looks for function or method calls that always return null and whose return value is used. class A
{
function getObject()
{
return null;
}
}
$a = new A();
if ($a->getObject()) {
The method The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes. ![]() |
|||
460 | } |
||
461 | |||
462 | /** |
||
463 | * Action must be taken immediately. |
||
464 | * |
||
465 | * Example: Entire website down, database unavailable, etc. This should |
||
466 | * trigger the SMS alerts and wake you up. |
||
467 | * |
||
468 | * @param string $message |
||
469 | * @param array $context |
||
470 | * |
||
471 | * @return mixed |
||
472 | * |
||
473 | * @throws \Exception |
||
474 | */ |
||
475 | 1 | public function alert($message, array $context = []) |
|
476 | { |
||
477 | 1 | return $this->driver()->alert($message, $context); |
|
0 ignored issues
–
show
Are you sure the usage of
$this->driver()->alert($message, $context) targeting Psr\Log\LoggerInterface::alert() seems to always return null.
This check looks for function or method calls that always return null and whose return value is used. class A
{
function getObject()
{
return null;
}
}
$a = new A();
if ($a->getObject()) {
The method The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes. ![]() |
|||
478 | } |
||
479 | |||
480 | /** |
||
481 | * Critical conditions. |
||
482 | * |
||
483 | * Example: Application component unavailable, unexpected exception. |
||
484 | * |
||
485 | * @param string $message |
||
486 | * @param array $context |
||
487 | * |
||
488 | * @return mixed |
||
489 | * |
||
490 | * @throws \Exception |
||
491 | */ |
||
492 | 1 | public function critical($message, array $context = []) |
|
493 | { |
||
494 | 1 | return $this->driver()->critical($message, $context); |
|
0 ignored issues
–
show
Are you sure the usage of
$this->driver()->critical($message, $context) targeting Psr\Log\LoggerInterface::critical() seems to always return null.
This check looks for function or method calls that always return null and whose return value is used. class A
{
function getObject()
{
return null;
}
}
$a = new A();
if ($a->getObject()) {
The method The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes. ![]() |
|||
495 | } |
||
496 | |||
497 | /** |
||
498 | * Runtime errors that do not require immediate action but should typically |
||
499 | * be logged and monitored. |
||
500 | * |
||
501 | * @param string $message |
||
502 | * @param array $context |
||
503 | * |
||
504 | * @return mixed |
||
505 | * |
||
506 | * @throws \Exception |
||
507 | */ |
||
508 | 1 | public function error($message, array $context = []) |
|
509 | { |
||
510 | 1 | return $this->driver()->error($message, $context); |
|
0 ignored issues
–
show
Are you sure the usage of
$this->driver()->error($message, $context) targeting Psr\Log\LoggerInterface::error() seems to always return null.
This check looks for function or method calls that always return null and whose return value is used. class A
{
function getObject()
{
return null;
}
}
$a = new A();
if ($a->getObject()) {
The method The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes. ![]() |
|||
511 | } |
||
512 | |||
513 | /** |
||
514 | * Exceptional occurrences that are not errors. |
||
515 | * |
||
516 | * Example: Use of deprecated APIs, poor use of an API, undesirable things |
||
517 | * that are not necessarily wrong. |
||
518 | * |
||
519 | * @param string $message |
||
520 | * @param array $context |
||
521 | * |
||
522 | * @return mixed |
||
523 | * |
||
524 | * @throws \Exception |
||
525 | */ |
||
526 | 1 | public function warning($message, array $context = []) |
|
527 | { |
||
528 | 1 | return $this->driver()->warning($message, $context); |
|
0 ignored issues
–
show
Are you sure the usage of
$this->driver()->warning($message, $context) targeting Psr\Log\LoggerInterface::warning() seems to always return null.
This check looks for function or method calls that always return null and whose return value is used. class A
{
function getObject()
{
return null;
}
}
$a = new A();
if ($a->getObject()) {
The method The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes. ![]() |
|||
529 | } |
||
530 | |||
531 | /** |
||
532 | * Normal but significant events. |
||
533 | * |
||
534 | * @param string $message |
||
535 | * @param array $context |
||
536 | * |
||
537 | * @return mixed |
||
538 | * |
||
539 | * @throws \Exception |
||
540 | */ |
||
541 | 1 | public function notice($message, array $context = []) |
|
542 | { |
||
543 | 1 | return $this->driver()->notice($message, $context); |
|
0 ignored issues
–
show
Are you sure the usage of
$this->driver()->notice($message, $context) targeting Psr\Log\LoggerInterface::notice() seems to always return null.
This check looks for function or method calls that always return null and whose return value is used. class A
{
function getObject()
{
return null;
}
}
$a = new A();
if ($a->getObject()) {
The method The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes. ![]() |
|||
544 | } |
||
545 | |||
546 | /** |
||
547 | * Interesting events. |
||
548 | * |
||
549 | * Example: User logs in, SQL logs. |
||
550 | * |
||
551 | * @param string $message |
||
552 | * @param array $context |
||
553 | * |
||
554 | * @return mixed |
||
555 | * |
||
556 | * @throws \Exception |
||
557 | */ |
||
558 | 1 | public function info($message, array $context = []) |
|
559 | { |
||
560 | 1 | return $this->driver()->info($message, $context); |
|
0 ignored issues
–
show
Are you sure the usage of
$this->driver()->info($message, $context) targeting Psr\Log\LoggerInterface::info() seems to always return null.
This check looks for function or method calls that always return null and whose return value is used. class A
{
function getObject()
{
return null;
}
}
$a = new A();
if ($a->getObject()) {
The method The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes. ![]() |
|||
561 | } |
||
562 | |||
563 | /** |
||
564 | * Detailed debug information. |
||
565 | * |
||
566 | * @param string $message |
||
567 | * @param array $context |
||
568 | * |
||
569 | * @return mixed |
||
570 | * |
||
571 | * @throws \Exception |
||
572 | */ |
||
573 | 2 | public function debug($message, array $context = []) |
|
574 | { |
||
575 | 2 | return $this->driver()->debug($message, $context); |
|
0 ignored issues
–
show
Are you sure the usage of
$this->driver()->debug($message, $context) targeting Psr\Log\LoggerInterface::debug() seems to always return null.
This check looks for function or method calls that always return null and whose return value is used. class A
{
function getObject()
{
return null;
}
}
$a = new A();
if ($a->getObject()) {
The method The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes. ![]() |
|||
576 | } |
||
577 | |||
578 | /** |
||
579 | * Logs with an arbitrary level. |
||
580 | * |
||
581 | * @param mixed $level |
||
582 | * @param string $message |
||
583 | * @param array $context |
||
584 | * |
||
585 | * @return mixed |
||
586 | * |
||
587 | * @throws \Exception |
||
588 | */ |
||
589 | 1 | public function log($level, $message, array $context = []) |
|
590 | { |
||
591 | 1 | return $this->driver()->log($level, $message, $context); |
|
0 ignored issues
–
show
Are you sure the usage of
$this->driver()->log($level, $message, $context) targeting Psr\Log\LoggerInterface::log() seems to always return null.
This check looks for function or method calls that always return null and whose return value is used. class A
{
function getObject()
{
return null;
}
}
$a = new A();
if ($a->getObject()) {
The method The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes. ![]() |
|||
592 | } |
||
593 | |||
594 | /** |
||
595 | * Dynamically call the default driver instance. |
||
596 | * |
||
597 | * @param string $method |
||
598 | * @param array $parameters |
||
599 | * |
||
600 | * @return mixed |
||
601 | * |
||
602 | * @throws \Exception |
||
603 | */ |
||
604 | 1 | public function __call($method, $parameters) |
|
605 | { |
||
606 | 1 | return $this->driver()->$method(...$parameters); |
|
607 | } |
||
608 | } |
||
609 |