Laminas 프로젝트의 Mezzio 프레임워크는 에러 로그를 파일에 기록하지 않고 개발 모드가 활성화되어 있는 경우 화면에 에러 로그를 상세하게 표시를 해주는 구조로 되어 있습니다. 개발 모드가 활성화되어 있는 경우라면 불편함이 없지만 서비스 서버에서는 에러를 확인하기 어렵다라는 문제가 있습니다. Mezzio 프레임워크에서 에러 로그를 파일에 기록하는 방법에 대해 알아보겠습니다.
기본적인 에러 핸들링에 대해서는 Mezzio 프레임워크 문서에 나와 있습니다. 다만, 이 문서에 나와 있는 예제는 말 그대로 기본적인 틀만 있어 실제 에러 로그를 파일에 기록하기 위해서는 추가적인 작업이 필요합니다.
1. laminas-log 설치 : composer require laminas/laminas-log
2. Laminas\Log\Writer\AbstractWriter 클래스를 상속받아 아파치 로그 파일에 에러를 기록할 writer 클래스 작성합니다. laminas-log에서 제공하는 Laminas\Log\Writer\Stream 클래스의 경우 아파치 가상호스트별 로그 파일에 기록하지 못하고 아파치 기본 로그 파일에 기록을 하기 때문에 별도 클래스를 만들었습니다. 기본 로그 파일을 사용해도 문제없다면 별도 클래스를 만들지 않고 Laminas\Log\Writer\Stream를 사용하시면 됩니다.
<?php
declare(strict_types=1);
namespace App;
use Laminas\Log\Formatter\Simple as SimpleFormatter;
use Laminas\Log\Writer\AbstractWriter;class ErrorLogWriter extends AbstractWriter
{
private const LOG_FORMAT = '%priorityName% (%priority%): %message% %extra%';protected $formatter = null;
public function __construct()
{
$this->formatter = new SimpleFormatter(self::LOG_FORMAT);
}protected function doWrite(array $event)
{
error_log($this->formatter->format($event));
}
}
3. 에러 리스너에서 사용할 Psr\Log\LoggerInterface의 팩토리 클래스를 작성합니다. 이 팩토리 클래스는 2번에서 만든 writer를 사용하는 Laminas\Log\PsrLoggerAdapter 객체를 리턴합니다.
<?php
declare(strict_types=1);
namespace App;
use Psr\Container\ContainerInterface;
use Laminas\Log\Logger;
use Laminas\Log\PsrLoggerAdapter;class LoggerFactory
{public function __invoke(ContainerInterface $container)
{
$writer = new ErrorLogWriter();
$laminasLogger = new Logger();
$laminasLogger->addWriter($writer);
$psrLogger = new PsrLoggerAdapter($laminasLogger);
return $psrLogger;
}
}
4. dependencies.global.php 파일의 factories 항목에 다음을 추가합니다.
Psr\Log\LoggerInterface::class => App\LoggerFactory::class,
5. ErrorLogListener 클래스를 작성합니다. Mezzio 문서에 있는 예제를 사용하시면 됩니다.
6. ErrorLogListenerDelegatorFactory 클래스를 작성합니다. 이것 또한 Mezzio 문서에 있는 것과 같으나 에러 로그 기록이 개발 서버에서는 필요없다면 디버그 설정 확인 로직을 추가합니다.
$debug = $container->get('config')['debug'];
if ($debug !== true) {
$listener = new ErrorLogListener($container->get(LoggerInterface::class));
$errorHandler->attachListener($listener);
}
7. dependencies.global.php 파일의 delegators 항목에 다음을 추가합니다.
Laminas\Stratigility\Middleware\ErrorHandler::class => [
App\ErrorLogListenerDelegatorFactory::class,
],