Skip to content

Instantly share code, notes, and snippets.

@rizqidjamaluddin
Created March 15, 2015 12:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rizqidjamaluddin/be7de406022b9a1afa43 to your computer and use it in GitHub Desktop.
Save rizqidjamaluddin/be7de406022b9a1afa43 to your computer and use it in GitHub Desktop.
Factory/Criteria pattern with service provider bindings
<?php
class CriteriaFactory {
protected $transformations = [];
public function __construct(Array $t = []) {
$this->transformations = $t;
}
/**
* $factory can either be the FQCN or a closure that generates said class
*/
public function add($key, $factory) {
$this->transformations[$key] = $factory;
}
public function convert($key, Callable $callback = null) {
// add safety checks for missing keys here, you get the idea
if (is_callable($this->transformations[$key])) {
$i = $this->transformations[$key]();
} else {
$i = new $this->transformations[$key];
}
if ($callback) {
$callback($i);
}
return $i;
}
}
<?php
class CriteriaFactoryServiceProvider extends ServiceProvider {
public function register() {
$this->app->bind(CriteriaFactory::class, function(Application $app) {
$i = new CriteriaFactory;
// this is how you register a new factory method
$i->add("posts-by-user", function () use ($app) {
return new PostsByUserCriteria($app['sentry']->getUser());
});
return $i;
});
}
}
<?php
class PostsByUserCriteria implements Criteria {
public function __construct(User $user) {
$this->user = $user;
}
public function setUser(User $user) {
$this->user = $user;
}
/**
* This gets an eloquent/QB instance
*/
public function perform($queryBuilder) {
return $queryBuilder->where("user_id", $this->user->id);
}
}
<?php
// in some controller somewhere, so like you'd have ?filter=posts-by-user
$filters = $this->criteriaFactory->convert(Input::get('filter'));
// then in the repository, this just supports one criteria but yeah
function getPosts(Criteria $criteria) {
return $criteria->perform($this->startQuery())->get();
}
// the callback thing is useful if you want to configure the filter during conversion, e.g. for ?filter=posts-by-user&user=84
$this->criteriaFactory->convert(Input::get('filter'), function (PostsByUserCriteria $criteria) {
$criteria->setUser(Input::get('user'));
})
// then you can use the same repository method as above
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment