How can this layered PHP architecture be improved?
Factory

Three things about this:


Consider using an autoloader (see PRS-0). Then you don't have to bother about, where files get included.
A Factory is used to create a set of objects, which depends on some context. For example, you could have a Filter and a Renderer for XHTML or HTML5. In order not having to check which one is needed again and again, you have an XhmtlFactory and an Html5Factory with createFilter() and createRenderer() methods.
Factory methods usually are named create....


In your context, a Factory is not helping you.

DB Connection

Don't use static methods, if you can avoid it. Inject dependencies whereever possible. Do not (finally) handle errors within your classes. Leave that up to the caller. The method to get an instance is usually called getInstance() (and is one of the few cases, where static calls are reasonable). The initialization is then made in a private constructor.

class Conn
{
    private $conn = null;

    /**
     * Establish PDO DB connection
     */
    private function __construct(Config $conf)
    {
        try { 
            self::$conn = new PDO($conf-&gt;dsn, $conf-&gt;user, $conf-&gt;pass, array(PDO::MYSQL_ATTR_INIT_COMMAND =&gt; "SET NAMES utf8"));
        } catch (PDOException $e) {
            $message = $e-&gt;getMessage();
            // We remove the username if we get [1045] Access denied
            if (preg_match('/\b1045\b/i', $message)) {
                $message = "SQLSTATE[28000] [1045] Access denied for user 'name removed' @ 'localhost' (using password: YES)";
            }
            throw new ErrorException($message);
        }
    }

    /**
     * Get DB connection
     */
    public static function getInstance(Config $conf)
    {
        if (is_null($this-&gt;$conn)) {
            $this-&gt;conn = new Conn($config);
        }
        return $this-&gt;conn;
    }
}

class Config
{
    public $dsn  = 'mysql:dbname=' . DB_NAME . ';host=' . DB_HOST;
    public $user = DB_USER;
    public $pass = DB_PASSWORD;
}  


To make the singleton pattern in Conn complete, the magic method __clone() should made private, so the connection cannot be copied.

Business Logic Layer

Keep the business and data access layer separated. The business layer ideally does not know anything about storage. The data access layer is injected into the business layer.

class Abc implements iAbc
{
    private $data = array();
    protected $dal;

    public function __construct($dal, $id = null)
    {
        $this-&gt;dal = $dal;

        if (!is_null($id)) {
            $this-&gt;setData($id);
        }
    }

    // __set, __get, __isset is here

    public function one(){};

    public function two()
    {
        $name = 'foo';
        $result = $this-&gt;dal-&gt;get_some_data($name);
        return $result;
    };
}


Data Access Layer

class AbcDao
{
    private $db = null;

    public function __construct(Conn $db)
    {
        $this-&gt;db = $db;
    }

    public function get_some_data($name)
    {
        $sql ="SELECT 123;";
        $stmt = $this-&gt;db-&gt;prepare($sql);
        $stmt-&gt;bindParam(':name', $name, PDO::PARAM_STR);
        $stmt-&gt;execute();

        $result = $stmt-&gt;fetchAll();
        return $result;
    }
}


Controller

In your controller, you now really have control.

$config = new Config;        // You could use any other set of config data
$conn   = new Conn($config); // You could use any other storage method
$my_abc = new Abc($conn);
$test   = $my_abc-&gt;two();


or, shorter

$my_abc = new Abc(new Conn(new Config));
$test   = $my_abc-&gt;two();