Если речь идет только об OCP, вы можете использовать шаблон проектирования цепочки ответственности, вы можете создать класс (открытый для расширения, закрытый для изменений), который имеет поле «следующий», которое из того же типа класса и сделайте нужные преобразования следующим образом:
interface ErrorHandler {
function handleError($request);
}
abstract class NodeInErrorHandlerChain {
private $next; // It should have the same `NodeInErrorHandlerChain` type
public NodeInErrorHandlerChain($next) {
$this->next = $next;
}
abstract protected function currentHandler($exception, $request);
public function handle($exception, $request) {
$current = currentHandler($exception, $request);
return $current != null ? $current :
($next == null ? null : $next->handle($exception, $request));
}
}
Затем реализуйте его следующим образом:
class ModelNotFoundNode extends NodeInErrorHandlerChain {
protected function currentHandler($exception, $request) {
if($exception instanceof ModelNotFoundException) {
return ModelNotFoundHandler($request); // This should be easy to implement
}
}
}
Итак, теперь вы проверяете только на ModelNotFoundException
, если вы хотите проверить другие типы, создайте ModelNotFoundNode
с $next
, не равным нулю, а скорее равным, например, ValidationException
(вы бы реализовали его таким же образом), поэтому добавление любого другого исключения из этих просто создайте другой класс, который расширяет NodeInErrorHandlerChain
, и сделайте его $next
для предыдущего последнего элемента цепочки, когда вы создаете цепочку (например, в поставщике, который обеспечивает внедрение зависимостей в вашем приложении).
$this->app->singleton(NodeInErrorHandlerChain::class, function ($app) {
return new ModelNotFoundNode(ValidationExceptionNode(null));
});