Eloquent and SQL Views

I'm currently on a mission to learn ember.js. This is my first attempt at frontend development and ember seems to be the new hotness so I figured I'd give it a shot. I'm building the backend api with Laravel. Out of the box, Laravel is pretty well-suited for building an api. However, after learning what json responses ember expects, I realized there was some work to be done.

The dilemma

I was reading through the ember rest adapter guide and came across the model relationship expectations. Ember expects something like the following.

{
    "company": {
        "id": 1,
        "name": "Acme Company",
        "person_ids": [1, 2, 3]
    }
}


Notice how the relationship ids are contained in an array. Ember does support sideloading models like below.

{
    "company": {
        "id": 1,
        "name": "Acme Company",
        "person_ids": [1, 2, 3],
        "people": [{
            "id": 1,
            "name": "David Adams"
        },
        {
            "id": 2,
            "name": "John Doe"
        },
        {
            "id": 3,
            "name": "Bob Smith"
        }]
    }
}


The problem with this is that if your app is of any size, this isn't an option. Too much data would be loaded.

Laravel is awesome in that you can side/eager load models but there isn't an option for eager loading data outside of entire models. For example, the person_ids in our company models.

My first attempt

The very last section in the eloquent docs informs us that we can define custom accessors that don't have a corresponding column in the database. I thought I would use this feature to accomplish my goal.

class Company extends \Eloquent
{
    protected $table = 'companies';

    protected $appends = ['person_ids'];

    protected $person_ids;

    public function people()
    {
        return $this->hasMany('Person');
    }

    public function getPersonIdsAttribute()
    {
        if (is_null($this->person_ids)) {
            $ids = DB::table('people')->where('company_id', '=', $this->id)->lists('id');

            $this->person_ids = array_map('intval', $ids);
        }

        return $this->person_ids;
    }
}


This accomplishes my goal....but there is one big problem. This solution has the N + 1 query problem. I'm adding a lot of database overhead with this approach. Every model retrieved will require one more query to get all of its data. This isn't optimal at all.

The solution

Rather than require a separate query made by php, it would be better to have sql handle that for us behind the scenes. It would be great to be able to use a sql view to read the data from instead of directly off of the table.

Fact! A sql view is basically a predefined query that is treated like table to read data from. You can create a view from a complex select statement that joins multiple tables and colums from different tables. Once created, you can select from the view, SELECT * FROM your_view_name.

I created a view with the following migration.

class CreateCompaniesView extends Migration 
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        DB::statement("CREATE VIEW companiesView AS
                        SELECT *,
                        (
                            SELECT GROUP_CONCAT(DISTINCT id SEPARATOR ',')
                            FROM people AS p
                            WHERE p.company_id = c.id
                        ) AS person_ids
                        FROM companies AS c");
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        DB::statement("DROP VIEW companiesView");
    }
}


This allows me to issue a query like SELECT * FROM companiesView and get the following resultset:

id created_at updated_at name person_ids
1 2013-11-10 06:29:48 2013-11-10 06:29:48 Acme Company 3,4
2 2013-11-10 06:29:48 2013-11-10 06:29:48 FooBar Industries 2,8,12

Now we need to figure out how to incorporate this view into our eloquent model.

Eloquent and views

We can't simply change the $table property on our model to the newly created view. Views cannot be written to, only read from. We need to provide the writable $table along with a $readFrom property where we can specify a view.

My first thought was to hook into the saving and saved eloquent model events to swap out the view for the real table when saving. I learned that the saving event isn't fired soon enough though. Eloquent has already built part of the query at that point.

Rather than using events, I decided to wrap eloquent with my own BaseModel class. This allows me to override the save() method and juggle the table/view before and after the actual save.

public function save(array $options = [])
{
    $this->toWriteMode();

    try {
        $saved = parent::save($options);
    } catch (\Exception $e) {
        $this->toReadMode();
        throw $e;
    }

    $this->toReadMode();

    return $saved;
}


The toWriteMode() and toReadMode() methods simply swap the $table to the appropriate table or view.

Read only attributes

The next problem is figuring out how to handle these read only attributes, ie. person_ids. These values need to be attributes on the models but not saved to the database.

We need a way to cache these read only values, remove them from being attributes on the model, save the model, and then add them back after the model is saved.

//part of the BaseModel class

    protected $readOnly = [];

    protected $readOnlyCache = [];

    public function save(array $options = [])
    {
        $this->toWriteMode();
        $this->cacheReadOnly();

        try {
            $saved = parent::save($options);
        } catch (\Exception $e) {
            $this->toReadMode();
            throw $e;
        }

        $this->toReadMode();
        $this->restoreReadOnly();

        return $saved;
    }

    protected function cacheReadOnly()
    {
        $this->readOnlyCache = [];

        foreach ($this->readOnly as $key) {
            $value = $this->getAttributeValue($key);
            $this->readOnlyCache[$key] = $value;
            $this->__unset($key);
        }
    }

    protected function restoreReadOnly()
    {
        foreach ($this->readOnlyCache as $key => $value) {
            $this->setAttribute($key, $value);
        }
    }


Sweet. Now in our model classes, we just need to provide an array of $readOnly attributes.

Putting it all together

With the creation of this base model class we can define a company model like below.

class Company extends BaseModel
{
    protected $table = 'companies';

    protected $fillable = ['name'];

    protected $guarded = ['id'];

    public function people()
    {
        return $this->hasMany('Person');
    }
} 


There's absolutely nothing new in this Company class. It works just as you would expect. However, now we can extend this class to create an EagerCompany class.

class EagerCompany extends Company
{
    protected $readFrom = 'companiesView';

    protected $readOnly = ['person_ids'];

    public function getPersonIdsAttribute($ids)
    {
        return $this->intArrayAttribute($ids);
    }
} 


This class will read its data from the view we created earlier and we can save and retrieve it as normal. It will fetch our read only attributes and they will be handled appropriately when saving.

That new intArrayAttribute() method just converts the comma delimited id string returned from the view into an array of integers.

We have some options now. We can use the Company internally but if we need those extra read only attributes, say in an api response, we can use the EagerCompany class.

I found this to work quite well for getting a list of ids for relationships. I also plan to use this same idea for returning counts of relationships.

{
    "company": {
        "id": 1,
        "name": "Acme Company",
        "person_ids": [1, 2, 3],
        "people_count": 3
    }
}


The base model

I've only shown you bits and pieces of this base model up until now. Here's the whole enchilada.

/**
 * Base model for allowing reads from sql views
 *
 * Class BaseModel
 * @package ProgrammingAreHard\Models
 */
abstract class BaseModel extends \Eloquent
{
    /**
     * Writable table
     *
     * @var string
     */
    protected $writeTable;

    /**
     * Read table/view
     *
     * @var string
     */
    protected $readFrom;

    /**
     * Read only attributes (not to be saved)
     *
     * @var array
     */
    protected $readOnly = [];

    /**
     * Cache for read only attribute values
     *
     * @var array
     */
    protected $readOnlyCache = [];

    /**
     * Instantiate and set the table
     *
     * @param array $attributes
     */
    public function __construct(array $attributes = [])
    {
        parent::__construct($attributes);

        $this->writeTable = $this->getTable();

        $this->toReadMode();
    }

    /**
     * Juggle the table and read only attributes
     *
     * @param array $options
     * @return bool
     * @throws \Exception
     */
    public function save(array $options = [])
    {
        $this->toWriteMode();
        $this->cacheReadOnly();

        try {
            $saved = parent::save($options);
        } catch (\Exception $e) {
            $this->toReadMode();
            throw $e;
        }

        $this->toReadMode();
        $this->restoreReadOnly();

        return $saved;
    }

    /**
     * Cache and remove read only attributes
     *
     * @return void
     */
    protected function cacheReadOnly()
    {
        $this->readOnlyCache = [];

        foreach ($this->readOnly as $key) {
            $value = $this->getAttributeValue($key);
            $this->readOnlyCache[$key] = $value;
            $this->__unset($key);
        }
    }

    /**
     * Restore the cached read only attributes
     *
     * @return void
     */
    protected function restoreReadOnly()
    {
        foreach ($this->readOnlyCache as $key => $value) {
            $this->setAttribute($key, $value);
        }
    }

    /**
     * Get the writable table
     *
     * @return string
     */
    public function getWriteTable()
    {
        return $this->writeTable;
    }

    /**
     * Swap to the writable table
     *
     * @return void
     */
    protected function toWriteMode()
    {
        $this->setTable($this->getWriteTable());
    }

    /**
     * Get the readable table/view
     *
     * @return string
     * @throws \Exception
     */
    public function getReadFrom()
    {
        if (is_null($this->readFrom)) {
            $this->readFrom = $this->getWriteTable();
        }

        return $this->readFrom;
    }

    /**
     * Swap to the readable table/view
     *
     * @return void
     */
    protected function toReadMode()
    {
        $this->setTable($this->getReadFrom());
    }

    /**
     * Convert the value to an int array if needed
     *
     * @param string|array $value
     * @return array
     */
    protected function intArrayAttribute($value)
    {
        if (is_string($value) and strlen($value) > 0) {
            $value = explode(',', $value);
            $value = array_map('intval', $value);
        }

        return is_array($value) ? $value : [];
    }
}


The controller

Here's a very simplified version of my controller.

class CompaniesController extends \BaseController 
{
    /**
    * Display a listing of companies.
    *
    * @return Response
    */
    public function index()
    {
        $res = new stdClass;
        $res->companies = EagerCompany::all()->toArray();

        return Response::json($res);
    }

    /**
    * Display a single company.
    *
    * @param  int  $id
    * @return Response
    */
    public function show($id)
    {
        $res = new stdClass;
        $res->company = EagerCompany::find($id)->toArray();

        return Response::json($res);
    }
}


I feel like this is a pretty good way to handle eager loading of non-model data. Maybe there's a better way to do this. I'd love to hear any ideas if you have some!

Tags: PHP, Intermediate, Laravel

Is ORM abstraction a pipe dream?

Abstraction layers in your projects allow for extreme flexibility. That's a given. Define a QueueInterface and create implementations for Beanstalkd, Amazon SQS, and IronMQ. Swap them out without touching anything but your IoC container. That's awesome.

I was recently introduced to the repository pattern, a type of abstraction and organizational technique. The idea being, create a repository for each of your models to retrieve and persist to and from. A supposed benefit of the repository pattern is the ability to abstract your ORM and create different implemenations for Eloquent, Doctrine, Propel, etc. This abstraction intrigued me. I set off to put this idea into practice and see what it took. Here are my findings.

The goal

My goal for this project was to abstract my ORM. Pretty straightforward, right? Just take the repository pattern to the extreme. Way easier said than done.

Heads up! I'm using Laravel as my framework of choice.

Time to go to work

I decided my first task was to create a UserRepository interface. An interface that had method stubs like create(array $fieldValues), findById($id), and currentUser(), etc.

Next up was to create my first implementation. Because Laravel is my framework, it made sense to implement the Eloquent ORM first. That was pretty easy, but then I realized something...my EloquentUserRepository is going to return Eloquent models. Okay...need to create a UserInterface.

Looks like I need to abstract Eloquent's sexy dynamic setter/getter action. I created my UserInterface with setEmail($email), getEmail(), setPassword($password), and getPassword(), save() methods.

Persisting for ORM X

At this point I started thinking I should peek at some other ORMs to see how they do things. Doctrine was in my line of sights. As soon as I learned about Doctrine's EntityManager I knew architecting this thing was going to be difficult.

In Doctrine, you wouldn't typically call save() on your models. You use the EntityManager to persist($model) and flush() the models. This wraps the save in a SQL transaction for you. I like that a lot. It means transactions are handled for you when you do something like the following.

$user = new User();
$user->setName('David');

$profile = new UserProfile();
$profile->setLocation('Dallas');
$profile->setOccupation('Software Developer');
// relate this profile to the user
$profile->setUser($user);

$em = $this->getDoctrine()->getManager();
$em->persist($user);
$em->persist($profile);
$em->flush();

I want to use transactions with Eloquent, so it looks like I need to add a save(UserInterface $user) method to the UserRepository interface. I'll just call save() on the Eloquent model inside of the EloquentUserRepository's save(UserInterface $user) method.

Hmm...what about relationships?

After looking at Doctrine, I realized I needed to create different method stubs somewhere for relating and un-relating models.

I wonder how Propel handles relationships. Hmm...looks like you set related models on each other and then save() it, which cascades the saves.

//Propel relationship saving
$author = new Author();
$author->setFirstName("Leo");
$author->setLastName("Tolstoy");
// no need to save the author yet

$publisher = new Publisher();
$publisher->setName("Viking Press");
// no need to save the publisher yet

$book = new Book();
$book->setTitle("War & Peace");
$book->setIsbn("0140444173");
$book->setPublisher($publisher);
$book->setAuthor($author);
$book->save(); // saves all 3 objects!

About that...do I create a UserRelationship interface? Do I add methods to the UserInterface? How should I go about handling the cascading saves by Propel versus the immediate saves done by Eloquent versus the flushing done by Doctrine? Uhhh...I'll just not worry about that for now. Validation is what I need next!

Validation

I like the idea of validating data for models before I stick the data inside the model. In Laravel, I can just create a create a class specifically for validation and use Laravel's validation class. I'll do that and validate an array of POST data from the request.

Just to be safe, I better take a peek at how Doctrine handles validation. Umm...a bit different. Looks like I can get a handle on a validator object and pass it a model or I can create a some kind of form object from my models and validate it by passing it a Request object. Looks like a need to create interfaces for each of my form validators and have different implementations for each ORM. That sucks.

Wonder how Propel handles validation. Looks like you validate a Propel model by calling a validate() on the model itself. Great...so Laravel validates an array of data, Doctrine a Request object, and Propel the models themselves. How do I interface that?

Observers

I think I want to be able to hook into different events and have event listeners for certain actions. Eloquent already has some Eloquent events defined for saving, updating, deleting models. That's nice but no good for me. I need generic events being fired.

I need to fire those same events in all of my UserRepository implementations. Yet another thing to keep in mind.

This is rough

Geez, I had no idea how much planning this would take. I'm not getting anywhere. Although a cool idea, this proof of concept isn't worth the time I'm spending on it.

What do you have to show for this?

Not much! :( I wish I had some cool demo where I could change a flag in the code and Eloquent would be used, change it again and Doctrine would be used, change it again and Propel would be used...but, alas, I do not.

The truth is I've spent so much time reading about how these different ORM's handle different aspects and not writing any code. After learning how different each ORM is, I've found it incredibly difficult to interface the different components to make an ORM agnostic project work.

I do not want to sound like I'm whining about something I was promised by using the repository pattern. That is not the intention of this post at all. The repository pattern most definitely has its benefits, but completely abstracting your ORM was a little too difficult for me. It was hindering me from actually producing anything.

It's not all doom and gloom for me though. This forced me to take a look at Doctrine(which I'm liking the more I see) and Propel. Learning how these different ORM's handle validation, relationships, transacations, etc has been a great experience for me. It has helped me form some opinions about what I like and don't like in an ORM, which is great. I didn't even think about that indirect benefit when I started.

As of right now, for me, I've decided that I can use the repository pattern for organizational purposes, but not ORM abstraction. I think I need to pick an ORM and stick with it to get anything done.

Overall I'm really glad I attempted this. I learned a lot. I hope this post starts a discussion on proper ORM abstraction. I would love to here your guys' thoughts on the subject.

Tags: PHP, Intermediate

We Need Some Closure

Heard of anonymous functions, Closures, or lambda functions? Seen some php that looks kinda like jQuery? Anonymous functions confused the crap outta me at first. Let's try to add these concepts to your programming toolbelt.

Mary had a little lambda

Anonymous functions are nothing more than functions you can assign to a variable. Consider the following example.

function add($x, $y)
{
    return $x + $y;
}

$subtract = function($x, $y) {

    return $x - $y;
};

echo add(2, 3); // "5"

echo $subtract(8, 2); // "6"

The first function declaration should look familiar. Nothing fancy going on here. The second function is the interesting one. $subtract is what's called a lamda function. It is a function that has no name. If we assign it to a variable, we can invoke it just like a normal function, passing parameters in via the paranthesis. Crazy name, not-so-crazy to learn!

Time for Closure

So what the heck is a Closure? It's a type of lambda function that is aware of its surroundings. Now that we know what a Closure is let's move on...just kidding! Let's look at an example.

$multiplier = 10;

$multiply = function($x) use ($multiplier) {

    return $x * $multiplier;
};

echo $multiply(1); // "10"
echo $multiply(4); // "40"
echo $multiply(10); // "100"

A Closure is an anonymous function that you can pass variables to remember and use later. In the above example, the Closure is remembering the $multiplier variable. It uses it on all future invocations.

I refer to all anonymous functions as Closures. So for the remainder of this post, I'll use the term Closure interchangeably with lambda function and anonymous function.

While these examples are extremely simple and not very useful, it introduces a very powerful feature in php. Let's continue on to see how we can make these ideas a little more useful for us.

Knowledge! Closures can have any number of arguments and use variables.

When are these things useful?

These are neat but it's difficult to figure out how these can be useful at first glance. Let's set up a scenario to utilize Closures.

Let's pretend we have a list of objects that we need to make sure all pass some sort of validation. Fairly common scenario, right? First, we'll define some requirements for this validation class:

  • Can add objects to be validated
  • Can add custom validation rules
  • Can validate all objects at once using custom validation rules

To satisfy these requirements, we could code the following class.

class Validator
{
    /**
     * Objects to be validated
     *
     * @var array
     */
    protected $objects = [];

    /**
     * Validation rules to use
     *
     * @var array
     */
    protected $rules = [];

    /**
     * Errors generated for the validation attempt
     *
     * @var array
     */
    protected $errors = [];

    /**
     * Add an object to be validated
     *
     * @param $obj
     * @return void
     */
    public function addObject($obj)
    {
        $this->objects[] = $obj;
    }

    /**
     * Add a validation rule
     *
     * @param callable $rule
     */
    public function addRule(Closure $rule)
    {
        $this->rules[] = $rule;
    }

    /**
     * Validate all objects in the validator
     *
     * @return bool
     */
    public function validate()
    {
        //empy the errors array
        $this->errors = [];

        //loop through all objects to be validated
        foreach ($this->objects as $object) {

            //loop through all rules to check against the object
            foreach ($this->rules as $rule) {

                //run the rule against the current object
                $rule($object);
            }
        }

        //if there are 0 errors, the validation passes and returns true, returns false otherwise
        return count($this->errors) == 0;
    }

    /**
     * Add an error to the validator
     *
     * @param string $key
     * @param string $error
     */
    public function addError($key, $error)
    {
        $this->errors[$key][] = $error;
    }

    /**
     * Get all errors generated
     *
     * @return array
     */
    public function getErrors()
    {
        return $this->errors;
    }
}

Well that looks cool and all, but there seems to be something missing. The validate() method isn't adding any errors when checking the rules, but it's relying on the count of the errors to determine if the validation passes. This is clearly broken...or is it? Let's actually use our Validator and see it in action.

//create our validator object
$validator = new Validator;

//define a rule
$validPhone = function($person) use ($validator) {

    //strip all non-integer characters
    $phone = preg_replace("/[^0-9]/", "", $person->phone);

    if (strlen($phone) !== 10) {

        $validator->addError($person->name, "Invalid phone number.");
    }
};

//add the rule to the validator
$validator->addRule($validPhone);

//define and add a valid email rule in one go
$validator->addRule(function($person) use ($validator) {

    if ( ! filter_var($person->email, FILTER_VALIDATE_EMAIL)) {

        $validator->addError($person->name, "Invalid email.");
    }
});

//define and add a valid name rule in one go
$validator->addRule(function($person) use ($validator) {

    if (strlen(trim($person->name)) == 0) {

        $validator->addError($person->name, "No name.");
    }
});

//let's create some objects to validate
$cory         = new stdClass;
$cory->name   = "Cory";
$cory->phone  = "123-456-7890";
$cory->email  = "cory@";

$shawn         = new stdClass;
$shawn->name   = "Shawn";
$shawn->phone  = "456-45-2";
$shawn->email  = "shawn";

$topanga        = new stdClass;
$topanga->name  = "Topanga";
$topanga->phone = "789-012-3456";
$topanga->email = "topanga@johnadamshigh.edu";

//add the objects to be validated
$validator->addObject($cory);
$validator->addObject($shawn);
$validator->addObject($topanga);

In the above code, we're defining three rules: has valid phone, has valid email, and has name.

When defining the first rule, we're assigning it to the $hasPhone variable and then adding it the validator with the addRule() method. Our Closure takes one argument, a $person object. It uses the $validator object. By using the same Validator instance, the Closure has access to it every time it gets invoked. In this example, we're using it to add errors.

Remember! It's important to note that unlike function arguments, variables being passed in the use parenthesis must already exist outside of the Closure.

The other rules, valid phone and valid email, aren't being assigned to variables. We're skipping that part and defining them right in the addRule() method of the Validator. Both ways are completely valid. jQuery advocates heavy use of this technique. It's the same idea.

Now that we've set up our Validator, we can run it and see what we get.

// run the validation
$isValid = $validator->validate(); //false

//dump the results
var_dump($validator->getErrors());

/*
    array (size=2)
      'Cory' =>
        array (size=1)
          0 => string 'Invalid email.' (length=14)
      'Shawn' =>
        array (size=2)
          0 => string 'Invalid phone number.' (length=21)
          1 => string 'Invalid email.' (length=14)
*/

As expected, our errors are assigned to the appropriate names. Awesome!

Why not create a class?

It's ideal to create classes that you can reuse multiple times in various places. However, sometimes you just know that some code will only ever run once and it's not worth creating a whole class or multiple classes to fill the requirement. Closures fit the bill perfectly. All Closures are objects in php. They allow us to adhere to object-oriented principles with extreme flexibility without requiring classes to be created for absolutely everything.

We could have tackled this another way. We could have defined a RuleInterface with check($object) and getError() methods. Then, we could have created classes that implement this interface for each rule. In this case, that'd be three separate classes. We could then create those rule objects and pass them to a Validator object that would check the rules against the objects being validated. If the rule check fails, get the error from the rule object and add it to the Validator's errors.

Symfony 2 actually uses this strategy for validating form input. It makes sense for common rules that will be used multiple times.

Our contrived example makes a little more sense to use Closures because we're validating "person" objects and maybe we never need to run this same combination of rules against a list of people anywhere else in our application.

Containers

Nowadays, it's very common to see Closures being used for containers. These containers' purpose is to create objects and inject their dependencies so we don't have to do that every single time. Consider the following example.

$container = [];

$container['EmailTemplate'] = function(){

    return new EmailTemplate;
};

$container['DataSource'] = function(){

    return new MySQLDataSource;
};

$container['NewsLetterSender'] = function() use ($container) {

    //used to created emails
    $template   = $container['EmailTemplate']();

    //used to track stats about the sending
    $dataSource = $container['DataSource']();

    return new NewsLetterSender($dataSource, $template);
};

$newsLetterSender = $container['NewsLetterSender']();

//versus the more verbose and less flexible

$newsLetterSender = new NewsLetterSender(new EmailTemplate, new MySQLDataSource);

As you can see, the $container's only responsibility is to create and assemble new objects. This concept is known as Inversion of Control. It's so popular because it's an elegant way to encourage dependency injection. While both of those concepts are out of the scope of this post, they are worth mentioning because you will most likely see this idea used elsewhere.

Learning is fun! Check out net tut's post about dependency injection and the IoC container!

To Closure this post

Anonymous functions are a sweet feature in php. Although a little hard to conceptualize their use, they can be quite handy. I hope I've been able to shed a little light on these unique functions. I highly encourage you to toy around with them. If you're just starting to learn php, you're bound to see them used more and more.

Homework! As practice, create a Sorter class that you can pass sort Closures instead of validation Closures to sort objects into an array.

**Hint!** Instead of a $this->errors instance variable, change it to $this->sorted and instead of addError($key, $error), change it to sortObject($category, $object).

Tags: PHP, Beginner