Custom Error Classes in OOP I have a class which parses a .csv file and converts it into successful rows and errors. Currently I have 12 different kind of errors (mail is not valid, missing column x, row is duplicate etc.).

Each error has a custom message. I also need to know in other classes what kind of error a row was, so a simple string is not enough. So far I am using this error class:

&lt;?php

namespace App\Registration\GroupUploads;

/**
 * Represents all possible errors that may occur during a group upload.
 */
class Error
{

  const USEREXISTS  = 7;
  const MAILINVALID = 1;
  const SEALUSED    = 2;
  const MIXEDUP     = 3;
  // ..

  protected $id;
  protected $options;

  /**
   * Each error has a unique ID
   * @param int $id
   * @param array $options optional
   */
  protected function __construct($id, $options = null)
  {
    $this-&gt;id      = $id;
    $this-&gt;options = $options;
  }

  /**
   * Get Message of current object
   * @return string
   */
  public function getMessage()
  {
    switch ($this-&gt;id) {
      case static::USEREXISTS:
        return 'User already exists';
        break;

      case static::MAILINVALID:
        return 'Mail is not valid';
        break;

      case static::SEALUSED:
        return 'Sealnr is already used by other user.';
        break;

      case static::SEALUSED:
        return 'They messed up and mixed the seals inbetween orgas.';
        break;

      // ...

      default:
        return 'No message provided for error code';
        break;
    }
  }

  /**
   * Create error for an existing user
   * @return bool
   */
  public static function getDuplicateUserError()
  {
    return new static(static::USEREXISTS);
  }

  /**
   * Check if class is duplicate user error
   * @return bool
   */
  public function isDuplicateUserError()
  {
    return $this-&gt;id == static::USEREXISTS;
  }

  // ...

}


There are 12 constants, each representing the id of a specific error. There is one method getMessage() which uses a switch with 12 cases. Then I have 12 messages of the kind getErrorMessageX and another 12 methods isThisErrorNameX. 

I feel that this is kind of messy and redundant. Also their might be me more error cases in the future, which will bloat up the class even more.

I thought about creating 12 separate classes, each class named by the error name. Something like that:

&lt;?php 

namespace App\Registration\GroupUploads;

/**
 * Error for existing user
 */
class UserExistsAlreadyError
{

  public function getMessage()
  {
    return 'User already exists';
  }

}


So instead of if($error-&gt;isDuplicateUserError()) I would write if($error instanceof UserExistsAlreadyError) .

However, I think creating 12 different classes, where each consists only of 12 lines, is a bit too much. Is there a better solution then those two extremes?
This is how I ended up doing it now:

&lt;?php

namespace App\Registration\GroupUploads\Errors;

/**
 * Error that appear during parsing csv file
 * @var [type]
 */
abstract class Error
{
  const USEREXISTS  = 7;
  const MAILINVALID = 1;
  const SEALUSED    = 2;
  const MIXEDUP     = 3;
  const QUALMISSING = 20;

  public $id;
  protected $msg;

  /**
   * Get error message
   * @return [type] [description]
   */
  public function getMsg()
  {
    return $this-&gt;msg;
  }

  /**
   * Error if user existed before registration
   * @param  [type] $name [description]
   * @return [type]       [description]
   */
  public static function userAlreadyExists($name)
  {
    $error = new Error();
    $error-&gt;id   = static::USEREXISTS;
    $error-&gt;msg  = "User " . $name .  " already exists";
    return $error;
  }

  /**
   * Mail is not valid
   * @param  [type] $mail [description]
   * @return [type]       [description]
   */
  public static function mailInvalid($mail)
  {
    $error = new Error();
    $error-&gt;id   = static::MAILINVALID;
    $error-&gt;msg  = "The mail " . $mail .  " is not valid";
    return $error;
  }

  //..
}


This way the getMsg method is short. Also adding a new error only requires to add one method instead of two (and no modification of the getMsg function).

To identify an error I call if($error-&gt;id == Error::USEREXISTS){...}.

Having the id was quite important, because I wanted to store the errors in DB.