PHP magic function for accessors and mutators
Exceptions are fine, but consider using less general Exception classes, like BaseException or whatever. This will allow for more flexible error reporting.

First thing that strikes me as odd about your code is that you're using underscore to name your properties, but CamelCase to name your methods. This is quite inconsistent and leads to unnecessary complexity here. Using naming convention that actually helps you is a good idea.

With that in mind, a little change in naming convention could turn into something like this:

function __call($method, $args)
{
    $action = substr($method, 0, 3);
    $prop = strtolower(substr($method, 3));
    $getter = "get".ucfirst($prop);
    $setter = "set".ucfirst($prop);

    switch ($action) {
        case "get" :
            if (isset($this-&gt;_fields[$prop])) {
                return $this-&gt;_fields[$prop];
            } else throw new EntityException("Unknown property {$prop}");
            break;
        case "set" :
            if (isset($this-&gt;_fields[$prop])) {
                $this-&gt;_fields[$prop] = $args[0];
                return null;
            } else
                throw new EntityException("Unknown property {$prop}");
            break;
        default : throw new EntityException("Unknown action {$action[0]}");
    }
}


Notice i use a an array $this-&gt;_fields to store all my fields. This goes for my second point - Safety and Reusability.

Consider this piece of code:

class User
{
    private $_name;   

    function getName(){
        return $this-&gt;_name;
    }
}


We use our getName method everywhere, but later we need to add another field - second name. We can safely insert this second field inside our getName and the code would change without taking any further actions. This is kinda the whole point behind getters and setters - incapsulating logic away.

Now with your code you'll have complications with overriding your setters, and that doesn't make it safe in any way.

Now, reusability. In your base class, you write all your fields explicitly, which doesn't seem very reusable to me. Look this code (warning, large wall of text incoming).

abstract class Entity
{
    private $_fields;
    protected $schema = array();

    function __construct(array $data = array())
    {
        /** Check that our concrete implementation has its Schema */
        if (!$this-&gt;schema) {
            throw new EntityException("Class ".get_called_class()." Schema not defined");
        }
        /**
         * mapping fields value to our schema
         *
         * @TODO Move to separate method to do this not only on Construct;
         */

        $this-&gt;_fields = array_reduce(
            $this-&gt;schema,
            function ($fields, $element) use ($data) {
                $fields[$element] = $data[$element];
                return $fields;
            }
        );
    }

    function __call($method, $args)
    {
         /** Same call implementation here as above */
    }

    /**
     * Inner getter for getter/setter overrides
     */

    protected function getField($name)
    {
        if (!isset($this-&gt;_fields[$name])) {
            throw new EntityException ("Property {$name} not found");
        }
        return $this-&gt;_fields[$name];
    }

    /**
     * Inner setter for getter/setter overrides
     */

    protected function setField($name, $value)
    {
        if (!isset($this-&gt;_fields[$name])) {
            throw new EntityException ("Property {$name} not found");
        }    
        $this-&gt;_fields[$name] = $value;
    }
}

/**
 * Class User
 *
 * Concrete implementation of Entity class
 *
 */
class User extends Entity
{
    /**
     * List of our entity fields
     * @var array
     */
    protected $schema = array("id", "name", "email", "phone");

    /**
     * method getName concrete implementation;
     *
     * @return string
     */

    function getName()
    {
        return "My name is ".$this-&gt;getField("name");
    }
}


try {
    $userData = array("id" =&gt; 1, "name" =&gt; "Andrew", "phone" =&gt; "000000000", "email" =&gt; "test@test.com");

    $user = new User($userData);

    echo $user-&gt;getName()."&lt;br /&gt;";
    echo $user-&gt;getEmail()."&lt;br /&gt;";
    $user-&gt;setPhone("111111111");
    echo $user-&gt;getPhone();

} catch (Exception $e) {
    echo $e-&gt;getMessage();
}


Now, if you want to create a News entity, you can simply write:

class News extends Entity
{
   protected $schema = array("id", "title", "text", "time");
}


And use it at your leisure. Later you can add active record methods to Entity, like save, delete, update and so on, and still use them on any entity you might want.

As to why i used array $_fields instead of simply listing fields - array is much more convenient when you have to map values to your fields and build queries from them.