kla/php-activerecord — pull request #306 by anther (2013-04-26 20:37:09+00:00)
Title: Feature/Discussion: Scopes

I want to start a discussion on adding scopes to PHPActiveRecord!

This is a branch that I started working on earlier this year after discovering GH-252 by @CarlosBonetti. He began work on what I thought was a very good idea but a pretty rough implementation of scoping features. I've been tweaking and adding to it to the point that I've used this implementation on several live web-apps and feel that this would add a lot of value to PHPActiveRecord and be very nice to not only have in my home version ;p.

I've since updated his code to have a much smoother and slightly less intrusive interface with pre-existing phpactiverecord code. I've also put some checks in place so that it currently won't override any behavior of previous code if scopes are not used at all, thus in theory all previous code behaves the same.

There are still some rough edge cases in the implementation right now but they're all relatively easy to iron out, as rough edges tend to be :p.

I'm going to pull these examples from code we currently have active. I'm also pretty sure the majority of you know what scopes are and how they work but here's an example of this particular implementation in practice.
```
class Company extends BaseModel
{

public static function getAllAgencies()
{
$criteria['conditions'] = array('company_type' => AGENCY_COMPANY_TYPE);
return self::scoped()->where('company_type = ?', AGENCY_COMPANY_TYPE)->order('company_name ASC');
}

public static function nameSearchCompanies($companyName)
{
return self::scoped()->where('company_name LIKE ?', "%$companyName%");
}

public static function nameSearchValidCompanies($companyName)
{
return self::validCompanies()->nameSearchCompanies($companyName);
}

public static function validCompanies()
{
$config = JuggernautClientConfig::instance();
return self::scoped()->where('dead = ?', 0)->order('company_name ASC');
}

public static function nameSearchValidAgencies($companyName)
{
return self::validCompanies()->where(array('company_type' => AGENCY_COMPANY_TYPE))->nameSearchCompanies($companyName);
}

public static function nameSearchRepCompanies($companyName){
return self::repCompanies()->nameSearchCompanies($companyName);
}

public static function repCompanies(){
$scope = self::validCompanies();
if (!restrictedPermissionsStuff()) {
$scope->where("(
CID IN (
SELECT DISTINCT CID FROM contacts AS c INNER JOIN contact_reps AS cr ON cr.iid=c.IID WHERE uid='".$_SESSION['userid']."'
)
OR
CID IN (
SELECT DISTINCT CID FROM company WHERE company_primary_rep = '".$_SESSION['userid']."'
)
)");
}
return $scope;
}

}

#You can then do all sorts of cool flexible stuff like
Company::nameSearchValidAgencies('Aristocrats')->all();
Company::nameSearchCompanies('Aristocrats')->all(array('conditions'=>array('id'='15')));
Company::nameSearchCompanies('Aristocrats')->limit(5)->all();
```

I really want input and some other programmer talents to jump into this because I feel it's very close to being ready to integrate fully and after some scrutiny this can possibly even be added as a feature to the current active build (As it's backwards compatible at the moment).

What do you guys think??