Are these MySQL Abstraction Classes safe from SQL Injection?  Can they be made safe? I was looking at this website:

http://www.devshed.com/c/a/MySQL/Creating-User-Models-in-PHP-and-MySQL/1/
and
http://www.devshed.com/c/a/MySQL/Creating-User-Models-in-PHP-and-MySQL/2/

In the first one they have methods such as:

/**
     * Perform a SELECT statement
     */ 
    public function select($table, $where = '', $fields = '*', $order = '', $limit = null, $offset = null)
    {
        $query = 'SELECT ' . $fields . ' FROM ' . $table
               . (($where) ? ' WHERE ' . $where : '')
               . (($limit) ? ' LIMIT ' . $limit : '')
               . (($offset &amp;&amp; $limit) ? ' OFFSET ' . $offset : '')
               . (($order) ? ' ORDER BY ' . $order : '');
        $this-&gt;query($query);
        return $this-&gt;countRows();
    }

    /**
     * Perform an INSERT statement
     */  
    public function insert($table, array $data)
    {
        $fields = implode(',', array_keys($data));
        $values = implode(',', array_map(array($this, 'quoteValue'), array_values($data)));
        $query = 'INSERT INTO ' . $table . '(' . $fields . ')' . ' VALUES (' . $values . ')';
        $this-&gt;query($query);
        return $this-&gt;getInsertId();
    }


then in the second page:

/**
     * Fetch all users
     */
    public function fetchAll()
    {
        // try to fetch users data from the cache system
        if ($users = $this-&gt;_cache-&gt;get('all')) {
            return $users;
        }
        // otherwise fecth users data from the database
        $this-&gt;_adapter-&gt;select('users');
        $users = array();
        while ($user = $this-&gt;_adapter-&gt;fetch()) {
            $users[] = $user;
        }
        if (count($users) !== 0) {
           $this-&gt;_cache-&gt;set('all', $users); 
        }
        return $users;
    }

    /**
     * Insert new user data (the cache is cleared also)
     */
    public function insert(array $data)
    {
        if ($insertId = $this-&gt;_adapter-&gt;insert('users', $data)) {
            $this-&gt;_cache-&gt;clear();
            return $insertId;
        }
        return false;
    }

    /**
     * Delete the table row corresponding to the specified user (the cache is cleared also)
     */ 
    public function delete($id)
    {
        if ($affectedRow = $this-&gt;_adapter-&gt;delete('users', "id = $id")) {
            $this-&gt;_cache-&gt;clear();
            return $affectedRow; 
        }
        return false;
    }  


Is this a bad way of doing things?  Is this opening me up to sql injection just like anything else where I construct the sql on the fly would?  I want to build my models "right."  Does that mean I need to have all stored procedures or prepared statements?
Active record instances are not "models". They are anti-patterns which RoR likes call that way. And what you are implementing there is an active record.

And no, those queries are not safe. They are wide open for SQL injection, because, instead of using proper SQL prepared statements, you opted for concatenation.

As for build building model, you have to understand that model is a layer. One of two in MVC. The other being - presentation layer (made of controllers, views and templates). You might read this answer, but I am no sure how much of it you will be able to assimilate. 

I think your first priority should be to read the hashphp PDO tutorial and then watching the list if lecture that you can find a the bottom of this post. And only then try another stab at the whole "mvc thing".