0

I am using some database polymorphism to connect table relations through eloquent/laravel. (NOTE the example below has been simplified, the two objects are already extending a base class so I can not extend another that would implement the behavior I want, the baseclass they extend is shared with other classes which are unrelated to what I'm trying to do below)

class Pageable{
  public function table() {
    return $this->morphTo();
  }
}

class User {
  public function pageable() {
    return $this->morphOne('Pageable', 'table');
  }

  public function returnUrl() {
    return "http://...";
  }
}

class Company {
  public function pageable() {
    return $this->morphOne('Pageable', 'table');
  }

  public function returnUrl() {
    return "http://...";
  }  
}

I iterate through pageable and can then retrieve either a User or Company object, however I need a generic function such as returnUrl that I can call on any of the objects that might be polymorphed into that relation. Is there any way to clean this up above or at least create some fail safe checks to ensure all the required method are implemented in the class if for instance they implement the PeageableInterface. For instance could I set in the interface a requirement that this returnUrl function is required?

How would I create such interface?

user391986
  • 29,536
  • 39
  • 126
  • 205

2 Answers2

3

Try using traits.

In your classes, just do the following:

use TraitWithReturnUrl;

then...

trait TraitWithReturnUrl {
    function returnUrl() {
        // do stuff like it's on the object itself
    }
}

Bingo! :)

Also check out my Fatty library, which can be useful for stuff like this as well: https://github.com/kirkbushell/fatty

In both cases, you'll need PHP 5.4+.

Oddman
  • 3,715
  • 1
  • 16
  • 13
  • interesting stuff you got here mister! :) I'll check it out when I have a moment. PS. Say whaaaat ? :P – Gadoma Aug 16 '13 at 16:10
  • awesome reference, where exactly do I define my trait though, which file at which location? I will look into fatty it looks great, is the only difference between the two that fatty is at runtime? – user391986 Aug 16 '13 at 19:46
  • @Oddman I saw your post on L forum :P but we havent "met" actually ;p – Gadoma Aug 16 '13 at 20:40
  • Traits are for more concrete implementations - as what you are doing here, and so shold be the approach you take. You are correct in saying that Fatty is more for runtime extension - it's for providing methods and functionality when you need it, rather than when an object is instantiated. In regards to where you put the traits - that's entirely up to you. Just so long as Laravel can see it, it'll be fine, which is very easy to do with the IoC functionality :) Gadoma - ah yes :) – Oddman Aug 17 '13 at 13:31
1

Traits might be a nicer way to go (new in php 5.5), but you can use interfaces directly, which I think in your case might look like this:

1) Create an interface:

interface Pageable {

    public function pageable();

}

2) Implement interface

class User extends Model implements UserInterface, RemindableInterface, Pageable {

    ... other methods ...

    public function pageable() {
        return $this->morphOne('Pageable', 'table');
    }

}

If, however, the method pageable() is the exact same code in every implementation, you might want to create an abstract class which defines it and then use that as your model's base class:

use Illuminate\Database\Eloquent\Model as BaseModel;

abstract class NewModel extends BaseModel implements Pageable {

    public function pageable() {
        return $this->morphOne('Pageable', 'table');
    }

}

Then your classes:

class User extends NewModel implements UserInterface, RemindableInterface {

    // You now have the pageable() method available

}

Hope that helps you get pointed in the right direction.

fideloper
  • 12,213
  • 1
  • 41
  • 38
  • thanks fideloper! that does help, any input where exactly I should define my interfaces though? – user391986 Aug 16 '13 at 19:47
  • Sure, see my SO answer [here](http://stackoverflow.com/questions/18196184/laravel-4-restful-api-with-content-negotiation/18211495#18211495), which goes into my thinking, and a corresponding blog article on [setting up an application library](http://fideloper.com/laravel-4-application-setup-app-library-autoloading). – fideloper Aug 16 '13 at 20:45