Yii handling “getLastInsertId” with Oracle

With MySQL or SQLite, when you insert something with an auto_increment field, it will automatically deal with the ActiveRecord by putting the last inserted id into $model->id. Because Oracle needs sequences and triggers to deal with that, neither the PDO driver nor the Yii PDO code felt it necessary to deal with that. Most people are probably fine with commiting to a database and throwing in Oracle specific sequence_name.nextval.

I just added a class in the models to extend CActiveRecord. The only thing you need to do with this is have your model extend this instead of CActiveRecord and add the variable schemaName to the model:

class User extends QActiveRecord
{
	public $sequenceName = 'USERS_SEQ';	
...

Yii Migrations: Dealing with auto_increment for Oracle and MySQL

Oracle deals with auto_increment by using sequences and triggers:

create sequence test_seq
start with 1
increment by 1
nomaxvalue;

create trigger test_trigger
before insert on test
for each row
begin
select test_seq.nextval into :new.id from dual;
end;
/

And MySQL is just an auto_increment keyword on the end of a column declaration:

CREATE TABLE animals (
id MEDIUMINT NOT NULL AUTO_INCREMENT,
name CHAR(30) NOT NULL,
PRIMARY KEY (id)
)
So I created a simple Autoincrement class:

/protected/migrations/Autoincrement.php

Which I included in the migration file for a schema.  This class will handle checking the driver and executing the appropriate sql.
Autoincrement::up('USERS', Yii::app()->db->driverName);
Autoincrement::down('USERS', Yii::app()->db->driverName);

What needs to be remembered here is to add a “sequenceName” to the model class, that is of the form “TABLENAME_SEQ”.

Using Facebook authentication with Yii (PHP)

Note: There many ways to implement this, but this seemed to make the most sense to me at the time.

A login can either come from someone clicking a login link and being sent to a login page or we can force the login and not allow guests.  The login/logout button is easy enough, just modify the distributed site controller’s login and logout “action” methods.  In order to force the login, the best wat to do this is to implement a behavior.  Please see Larry Ullman’s blog for more information on that.

Then we get to the IdentityFactory.  Yii has a nice configuration system in place for its components, so I did some Identity components extending the standard Yii UserIdentity that was included with the Yii distribution. I have the login entry point call on the identity factory which checks a param in the config and returns an instance of the appropriate object.

These objects are where all authentication type specifics happen.  Lets take a look at a simple flow diagram:

Facebook auth flow

So the IdentityFactory chooses which identity we’re using based on the config.  It will send the request over to the FacebookIdentity, which gets all the info needed for the UserIdentity class to query the database, update information there, and then set the user session.

The more interesting part is the connection between FacebookIdentity and the Facebook SDK.  For this I made use of a Yii extension.  I used yii-facebook-opengraph, which, while not the most mature of facebook connect extensions, is the most actively developed and the closest to functional.  (Last year Facebook made a huge change to their SDK which is not at all backwards compatible so they broke most extensions that exist and most developers did not make updates to their extensions.)  This extension only needed one method added to help deal with the Facebook problem with access tokens.


// had to add this function to deal with php's poor handling of expired access tokens
public function setAccessToken($access_token){
return $this->_getFacebook()->setAccessToken($access_token);
}