0

*Note this is a question regarding Laravel 4, not Laravel 3 (which uses Fluent)

Is it possible to extend the DB class in Laravel 4?

I've tried something as simple as this:

class Content extends DB {}

With this in my route:

print_r(Content::table('content')->get());

And it seems to work as far as using "Content" like "DB".

But if I try and set the table name by default similar to how you would in Eloqeunt and use functions such as where or join I get an error like so:

print_r(Content::where('id', '!=', 4)->get());

With this as the error:

call_user_func_array() expects parameter 1 to be a valid callback, class 'Illuminate\Database\MySqlConnection' does not have a method 'where'

Effectively what i'd like to do is something like this. Whereby I can add a function which does a number of joins/where's but integrate it into the normal flow of using DB. So the class would look like this:

class Content extends DB {
    public $table = 'content';

    public static function joinPermissions($permission_mask)
    {
        return self::where('permissions.mask', '=', $permission_mask)
            ->where('permissions.read', '=', 1)
            ->join('permissions', 'id', '=', 'content.permission_set');
    }
}

And it would be called like so:

Content::orderBy('time_added')
    ->take(10)
    ->joinPermissions($permission_mask)
    ->get();

Is this possible? I imagine it's something to do with needing to extend a different class other than DB because DB returns something else when you use DB::table();. But i'm really struggling to follow the code in Laravel and find what's going on, it seems to be something to do with illuminate but to be honest i'm not really sure what that is. I've also tried looking at Eloquent to see how that does it, but again I simply find Laravel so difficult to look around and understand what's going on.

John Mellor
  • 2,351
  • 8
  • 45
  • 79
  • The DB methods (like 'where', 'join', etc) are part of the Builder class in the Illuminate\Database\Query namespace, not the DB class. What are you trying to do exactly? There might be a better approach than extending the classes that do the database interaction. Generally I would be adding "some_extra_function()" to the model that is using the function. – ARW May 25 '13 at 19:48
  • @AdamWathan i've updated the example to explain a little more. I basically want to include functions within the general flow of using DB, rather than having to write separate functions such as getWithPermissions() – John Mellor May 25 '13 at 19:59
  • Sounds like the Builder class is what you want to extend then, should be able to add those methods there. I'm not sure I totally understand what you are trying to do so I can't suggest a better approach, but I do still think extending that class with very specific behavior like that is probably not truly the best solution. Are you intending to use this stuff with Eloquent or are you just using the DB component and doing things a little more "raw"? What is the "Content" class supposed to represent? – ARW May 25 '13 at 21:07
  • Basically I regularly need to "join permissions" when getting content from the database (think permission to read a forum topic for example) it's better to have a single function to do it rather than always writing out the where/join stuff. – John Mellor May 25 '13 at 22:53

1 Answers1

2

Try using Eloquent and scopes:

class Content extends Eloquent {
    public $table = 'content';

    public function scopeJoinPermissions($query, $permission_mask)
    {
        return $query->where('permissions.mask', '=', $permission_mask)
            ->where('permissions.read', '=', 1)
            ->join('permissions', 'id', '=', 'content.permission_set');
    }
}

Content::orderBy('time_added')
    ->take(10)
    ->joinPermissions($permission_mask)
    ->get();
Dave James Miller
  • 4,928
  • 3
  • 20
  • 18
  • I was trying to avoid the cost of an ORM as what I need to achieve can be 99% completed without one, it seems silly to bring in Eloquent just so that I can have repetitive code for joining permissions within a function rather than doing it separately each time. I've tried to look at how Eloquent works and see how it extends DB but I'm struggling to make my way through the Laravel codebase – John Mellor May 25 '13 at 23:30
  • Dave has the right idea. You cannot extend the DB class and then assign a default table and expected to be able to go Content::where(), you would need to go Content::table('content')->where()... The syntax you have proposed is exactly how Dave's implementation would work. Extending the DB class will not allow you to use the syntax you suggested. – ARW May 25 '13 at 23:43