Here's the basic premise, I'm using an active record pattern for db objects, and I think I need some direction how to organize these classes. And also in general how I could potentially split up my class structure. Hopefully I don't explain this too terribly. If composition pattern is the way to go I may need a little hand holding on a way to implement it.
Let's say there's the ActiveRecord base class, at the bottom of the totem pole that deals with mapping objects to the db and the db to objects.
A child of ActiveRecord is a sort of generic User class, that deals with user sessions, logins, encryption of the password field on save and such.
Another child of ActiveRecord is a ActiveRecordButSlightlyMoreAdvanced class. Usually this class has nothing to do with User, but here's my issue.
I want to have a subclass that wants to be essentially a combination of User and ActiveRecordButSlightlyMoreAdvanced; UserButSlightlyMoreAdvanced, without having to copy paste all of the methods from User. It doesn't make sense for User to extend ActiveRecordButSlightlyMoreAdvanced, as it'd require essentially overriding a bunch of methods that have undesirable behavior for User.
It would make sense for UserButSlightlyMoreAdvanced to extend ActiveRecordButSlightlyMoreAdvanced, but I'd have to copy and paste a bunch of methods from User.
I know some people think better with pictures, so here's the structure illustrated.
Base
class ActiveRecord
{
....
}
Child
class User extends ActiveRecord
{
....
}
Also Child
class ActiveRecordButSlightlyMoreAdvanced extends ActiveRecord
{
....
}
The Problem
class UserButSlightlyMoreAdvanced extends User AND ActiveRecordButSlightlyMoreAdvanced
{
:( :( :(
}
I've been thinking about this problem for about a month now and cannot think of a solution that doesn't place burden of maintaining the objects dually if there's a change to how one of them implements saving. I'm going to experiment with a few solutions over the next couple of days and possibly post what I think was best in this situation.
My guess is that you meant to say this:
class UserButSlightlyMoreAdvanced extends User AND ActiveRecordButSlightlyMoreAdvanced
{
:) :) :)
}
If that is the case, look into traits http://php.net/manual/en/language.oop5.traits.php
You might try using the strategy pattern. In this case you would create your class:
class UserButSlightlyMoreAdvanced extends ActiveRecord implements ActiveRecordButSlightlyMoreAdvancedStrategy
{
private $_strategy;
public function useStrategy(ActiveRecordButSlightlyMoreAdvancedStrategy $s) {
$this->_strategy = $s;
}
}
and make your strategy class:
interface ActiveRecordButSlightlyMoreAdvancedStrategy
{
// Define what this should do here
}
Make a strategy class that implements the above interface.
class ActiveRecordButSlightlyMoreAdvanced implements ActiveRecordButSlightlyMoreAdvancedStrategry {
// Do stuff here
}
Now when you call those advanced methods, both classes implement the same interface, but the UserButSlightlyMoreAdvanced class just passes the requests through to the strategy object:
class UserButSlightlyMoreAdvanced extends ActiveRecord implements ActiveRecordButSlightlyMoreAdvancedStrategy
{
private $_strategy;
public function useStrategy(ActiveRecordButSlightlyMoreAdvancedStrategy $s) {
$this->_strategy = $s;
}
public function someSlightlyMoreAdvancedFunction () {
return $this->_strategy->someSlightlyMoreAdvancedFunction():
}
}
Hope that helps.
Related
I'm reworking a project on Laravel 5.1
What I realize is that the old classes have become much complicated and do not really follow the 'single responsibility' principle anymore.
So I'm planning to do such:
<?php
class User extends Model
{
}
class SocialUser extends User
{
}
So I have a few questions,
Is it possible to achieve that?
If yes, then does the SocialUser class link back to the same database table which is Users and would it conflict with the User model itself?
Is this all a good design practice at the first place? Or I better make use of traits?
Thank you.
What you’re doing (extending the User model) is perfectly fine, and an approach I use myself in projects.
For example, if an application I’m building has shop-like functionality, then I may create a Customer model that extends my User model, and contains say, order-related relations:
class Customer extends User
{
public function orders()
{
return $this->hasMany(Order::class, 'customer_id');
}
public function worth()
{
return $this->orders()->sum(function ($order) {
return $order->total();
});
}
}
In a recent project, I’ve been working on email campaign functionality and created a Recipient class that extends the User model to add campaign-related methods:
class Recipient extends User
{
public function campaigns()
{
return $this->belongsToMany(Campaign::class, 'recipient_id');
}
}
Because both of these classes extend the User model, I get all of those (and Eloquent) methods:
$customers = Customer::with('orders')->get();
So long as you set the table in your base User model, any classes that inherit it will use that same table, even though the model may be named differently (i.e. Customer, Recipient, Student etc).
IMHO I would go for the Repository pattern. It make's a lot of sense in your situation.
I would do the following:
interface UserRepository {
public function find($id);
public function getAll();
public function create(array $attributes);
public function destroy($id);
//you get the point
}
class CoreUserRepository implements UserRepository
{
//implement the interface rules
}
class SocialUserRepository extends CoreUserRepository
{
//implement the specific logic related to a SocialUser
}
Update
As Mjh described in the comments simply implementing the interface on all UserTypeRepository caused repetition - probably not what you want!
By extending your CoreUser you avoid repetition & maintain a design that will work for your situation.
Although, in your case it could be argued that you are still following SRP because everything in the User model is relating to a user, it's only the type of user which is differing.
Why go for the Repository Pattern?
You are ensuring you have a contractual agreement that all User
Repositories need to implement.
Code is easier to maintain.
Business and data access logic can be tested separately
Should you extend your User model?
Here you are in danger of model pollution. While you can do anything with a model - not everything is a good idea.
Defining relationships on this approach would be a headache due to the confusion caused.
I have seen some similar questions but I have yet to find a good solution for this from the interface all the way to the controller.
My Problem:
I have a few different kinds of applications that will require restarts, each has its own logic for restarting the application(SSH,API calls, etc.). I have set up an interface because although different logic, they all will need some similar functions. I have also created 3 classes, one for each app that implements that interface. where I am having issues is understanding the best way to keep the logic as abstracted from the controller as possible.
Some Questions:
Should I also be creating an Abstract class?
Should this be one controller that handles all types and chooses the correct one?
do I simply inject the different classes into the controller?
Code:
RestartInterface.php
<?php namespace Application\Service\Restart;
interface RestartInterface {
public function start();
public function stop();
public function restart();
}
example of implementing class:
<?php namespace Application\Service\Restart\AppOne;
use Application\Service\Restart\RestartInterface;
class AppOneRestart implements RestartInterface {
public function start() {
}
public function stop() {
}
public function restart() {
}
}
How could I use a service provider to keep this as modular as possible?
What is the best practice in this situation, I would like to be able to use many or as little restart implementations as I want.
thanks!
An abstract class is a way to create a base class you don't need your developers instantiating directly because, usually, there is still missing code from it, like, methods were not fully implemented. So you create an abstract which implements the common methods of your concrete restart classes
abstract class Restart {
public function restart() {
}
}
And then you implement one by one of those classes extending your abstract and creating the missing methods:
class AppOneRestart extends Restart implements RestartInterface {
public function start() {
}
public function stop() {
}
}
Option 1
If your whole application can use a single implementation of it and you just need the ability to swap from one to another, because your business somehow changed, a simple binding will do the trick:
App::bind('RestartInterface', 'AppOneRestart');
Option 2
If during a request you might need one or another, you probably will need to implement the Factory pattern: http://en.wikipedia.org/wiki/Factory_method_pattern, so you inject the factory in your controller:
class RestartApiController extends Controller {
public function __construct(RestartFactory $factory)
{
$this->restart = $factory->make('api');
}
}
I am trying to work out the best way to design my classes and I think abstract classes it the right way here, but I'm not sure! I am building a plugin for Wordpress carts that at the moment, will work for both Woocommerce and WP-Ecommerce. As these two systems have different implementations of certain functionality, such as getting an order object, I want to create a separate class for each platform.
I have the following which will contain generic methods that should be available to the classes that inherit from it. This class should never be instantiated:
class Order_Export {
}
I then have 2 more classes that will inherit from the above:
class Order_WooExport extends Order_Export {
}
class Order_WPExport extends Order_Export{
}
Is my design right here? Am I right in saying the class Order_Export should be an abstract class? What about methods that I want the class inheriting to implement? Do I simply mark the signature in the abstract class and not provide a body, or do interfaces come into play somewhere here?
How about instantiating the right class? Do I create a factory that will return one or the other?
Any advice appreciated!
That sound correct to use abstract base class, as long as you are sure to never need to instantiate Order_Export :
abstract class Order_Export
{
abstract protected function someMeth1();
abstract protected function someMeth2();
public function someMeth3() {
// Do common thing to both Order_WooExport and Order_WPExport
// using someMeth1(), someMeth2()...
}
}
Then :
class Order_WooExport extends Order_Export
{
protected function someMeth1() {
// Do something specific
}
protected function someMeth2() {
// Do something specific
}
}
Finally, the factory seems to be the right way to go too.
my models in CI are set up so that they load "sub"-models whenever they need certain functions. In order to keep my code as accessible and clean as possible, I want those submodels to extend the model they are called to.
So if I have two models:
<?php
class Mymodel extends Model
{
}
And:
<?php
class Submodel extends Model
{
function test() { do something.. }
}
Then I need to, somehow, be able get the submodel to extend mymodel, so that I can do something like $this->mymodel->test(). It doesn't have to be mymodel that submodel extends, it could be any model. Any ideas?
Thanks for your time.
You have an incorrect understanding of inheritance between classes.
Inheritance only flows one way, Down.
if Myodel extends Submodel your $this->mymodel->test() would work, but it does not make sense as sub (child) objects are suppose to inherit from parent objects, not the other way around.
As an analogy, you wouldn't look at a child and tell the parent, "You look just like your child", because it is the child that is a part representation of the parent.
you need to take the word extends very literally, you are literally 'extending' the functionality of the parent.
===================
One way i believe you could accomplish this is to create ghost functions that simply load the proper model and call that models function (though I do not recommend this as it could get very confusing for debugging.
per your example
<?php
class Mymodel extends Model
{
function test() {
$this->load->model('submodel');
$this->submodel->test();
}
}
Submodel
<?php
class Submodel extends Model
{
function test() { do something.. }
}
BUT again, if you are going for clean code, this is NOT the way to go, try and observe inheritance, and design your data with that in mind.
You can create utility model which may extends codeigniter's model and then all your models can extend that utility model. The methods you are going to add to the utility model will be available to all it's child classes aka your models.
How can you call a method which your class does not have or does not inherit from any other classes? Looking at your code, there is no relationship in your classes between Mymodel and Submodel.
i would like to know if it is possible to have a function in PHP which returns an interface or a class which contains an interface?
i tried something like this, but it fails
<?php
//class for list of controllers for ACL
class Gestionale_Action_Helper_Crud extends Zend_Controller_Action_Helper_Abstract {
interface crud_controller
{
public function indexAction();
public function modificaAction();
public function cancellaAction();
public function creaAction();
}
public function getCrudInterface(){
return $this->crud_controller;
}
}
what i wanted to do, in zend framework, create an interface that crud controllers must implement, or even better if i could create an abstract controller and have them implement that
thank you
I'd suggest that you use Zend_Rest_Controller instead of creating your own interface.
Zend_Rest_Controller is an abstract class that defines five basic methods you need in a CRUD-controller: index, get, post, put, and delete.
Combined with Zend_Rest_Route it lets you create nice and clean RESTful application.
You can get more reading on Zend_Rest_Controller at http://weierophinney.net/matthew/archives/228-Building-RESTful-Services-with-Zend-Framework.html and http://techchorus.net/create-restful-applications-using-zend-framework
Just place the interface outside of any class (preferably in a different file) and let it be implemented by all your crud-controllers.
<?php
class GrudController implements CrudInterface
{
// ...
}
i'm not sure i get what it is you want to do, but i'm fairly certain you're asking the wrong question. if you simply want to make sure an object implements a certain interface, this is quite easy to do. lets say for example you have some helper method in a class which deals with a crud controller, you just specify the type in the argument list:
class crud_helper {
public function help(crud_controller $cc) {
$cc->indexAction();
}
}
now you can pass any object that is an instance of a class that implements crud_controller to the method help. but no other object.