Asked  7 Months ago    Answers:  5   Viewed   27 times

How do you organize and manage your helper objects like the database engine, user notification, error handling and so on in a PHP based, object oriented project?

Say I have a large PHP CMS. The CMS is organized in various classes. A few examples:

  • the database object
  • user management
  • an API to create/modify/delete items
  • a messaging object to display messages to the end user
  • a context handler that takes you to the right page
  • a navigation bar class that shows buttons
  • a logging object
  • possibly, custom error handling

etc.

I am dealing with the eternal question, how to best make these objects accessible to each part of the system that needs it.

my first apporach, many years ago was to have a $application global that contained initialized instances of these classes.

global $application;
$application->messageHandler->addMessage("Item successfully inserted");

I then changed over to the Singleton pattern and a factory function:

$mh =&factory("messageHandler");
$mh->addMessage("Item successfully inserted");

but I'm not happy with that either. Unit tests and encapsulation become more and more important to me, and in my understanding the logic behind globals/singletons destroys the basic idea of OOP.

Then there is of course the possibility of giving each object a number of pointers to the helper objects it needs, probably the very cleanest, resource-saving and testing-friendly way but I have doubts about the maintainability of this in the long run.

Most PHP frameworks I have looked into use either the singleton pattern, or functions that access the initialized objects. Both fine approaches, but as I said I'm happy with neither.

I would like to broaden my horizon on what common patterns exist here. I am looking for examples, additional ideas and pointers towards resources that discuss this from a long-term, real-world perspective.

Also, I'm interested to hear about specialized, niche or plain weird approaches to the issue.

 Answers

85

I would avoid the Singleton approach suggested by Flavius. There are numerous reasons to avoid this approach. It violates good OOP principles. The google testing blog has some good articles on the Singleton and how to avoid it:

http://googletesting.blogspot.com/2008/08/by-miko-hevery-so-you-join-new-project.html http://googletesting.blogspot.com/2008/05/tott-using-dependancy-injection-to.html http://googletesting.blogspot.com/2008/08/where-have-all-singletons-gone.html

Alternatives

  1. a service provider

    http://java.sun.com/blueprints/corej2eepatterns/Patterns/ServiceLocator.html

  2. dependency injection

    http://en.wikipedia.org/wiki/Dependency_injection

    and a php explanation:

    http://components.symfony-project.org/dependency-injection/trunk/book/01-Dependency-Injection

This is a good article about these alternatives:

http://martinfowler.com/articles/injection.html

Implementing dependency injection (DI):

  • I believe you should ask what is needed in the constructor for the object to function: new YourObject($dependencyA, $dependencyB);

  • You can provide the needed objects (dependencies) manually ($application = new Application(new MessageHandler()). But you can also use a DI framework (the wikipedia page provides links to PHP DI frameworks).

    Important is that you only pass in what you actually use (call an action on), NOT what you simply pass to other objects because they need it. Here's a recent post from 'uncle Bob' (Robert Martin) discussing manual DI vs using framework.

Some more thoughts on Flavius's solution. I don't want this post to be an anti-post but I think it's important to see why dependency injection is, at least for me, better than globals.

Even though it is not a 'true' Singleton implementation, I still think Flavius got it wrong. Global state is bad. Note that such solutions also use difficult to test static methods.

I know a lot of people do it, approve it and use it. But reading Misko Heverys blog articles (a google testability expert), rereading it and slowly digesting what he says did alter the way I see design a lot.

If you want to be able to test you application, you'll need to adopt a different approach to designing your application. When you do test-first programming, you'll have difficulty with things like this: 'next I want to implement logging in this piece of code; let's write a test first that logs a basic message' and then come up with a test that forces you to write and use a global logger that can't be replaced.

I am still struggling with all the information I got from that blog, and it's not always easy to implement, and I have many questions. But there's no way I can go back to what I did before (yes, global state and Singletons (big S)) after I grasped what Misko Hevery was saying :-)

Wednesday, March 31, 2021
 
hakre
answered 7 Months ago
16

The PHP Language reference has details on what a function and class is: http://www.php.net/manual/en/langref.php

It also explains most the other features of PHP. If want to learn PHP that is the best place to start.

Functions

The function is a grouping of statements (lines of code).

For example the following statements:

$name = 'mary';
$gender = 'girl';
if ($gender == 'girl') {
  $line = $name . ' had a little pony.';
} else if ($gender == 'boy') {
  $line = $name . ' had a little horse.';
}
echo $line;

Can be grouped together into a function so it can be reused:

getSentence('mary', 'girl');
getSentence('peter', 'boy');
function getSentence($name, $gender) {
  if ($gender == 'girl') {
    $line = $name . ' had a little pony.';
  } else if ($gender == 'boy') {
    $line = $name . ' had a little horse.';
  }
  echo $line;
}

Notice the two function calls:

getSentence('mary', 'girl');
getSentence('peter', 'boy');

These two statements run the whole block of code inside the getSentence function and pass it the variables $name and $gender. With the first function $name = 'mary' and $gender = 'girl' and in the second $name = 'peter' and $gender = 'boy'.

So the main benefit of functions is that you have grouped code for reuse, allowing the passing of different values for the variables needed by the function. These variables are called the function parameters.

Another benefit of having the code grouped is easier readability. You are essentially naming the block of code, and giving them a specific purpose. Making it easy to read and remember it's use.

Another benefit is that redundancy is removed. You do not have to write the block of code more then once. You just define it once, and call it multiple times. This also makes editing of the function code affect all calls to that function - which reduces errors in having to edit multiple locations when changing just one aspect.

eg:

We can make sure the $name string has an uppercase first character.

function getSentence($name, $gender) {
  $name = ucfirst($name);
  if ($gender == 'girl') {
    $line = $name . ' had a little pony.';
  } else if ($gender == 'boy') {
    $line = $name . ' had a little horse.';
  }
  echo $line;
}

We made just one change, and it affected every function call to getSentence(). In this case both:

getSentence('mary', 'girl'); 

and

getSentence('peter', 'boy'); 

Classes are a grouping of functions.

class Play {
  function getSentence($name, $gender) {
    $name = ucfirst($name);
    if ($gender == 'girl') {
      $line = $name . ' had a little pony.';
    } else if ($gender == 'boy') {
      $line = $name . ' had a little horse.';
    }
    echo $line;
  }
  function getSong($name) {
    // code here
  }
}

All we did was put

class Play { /** functions here **/ }

around a group of functions.

This offers the same benefits that functions do for statements except classes does it for functions.

Classes go further to build a programming methodology called Object Oriented programming (OOP), which you can read more about in link to PHP Language reference.

This defines classes as the template or definition of Objects. Objects being similar to real world objects, with the functions being called "methods" that can be called for the object.

So the class Play can be thought of as the object called "Play" with the methods "getSentence" and "getSong". These methods can then manipulate the properties of the object "Play" or return useful information about "Play". In this way, all the code inside Play becomes independent of code elsewhere in the program.

When the code inside Play requires some code elsewhere to function, it can be brought in using "inheritance", which is a major part of OOP. I will not go into detail about this as it is a very broad topic.

I would recommend getting a book on OOP and reading it to really understand why you should use classes and methods and when to use them.

Wednesday, March 31, 2021
 
danjah
answered 7 Months ago
76

Id say its more of Decorator... http://en.wikipedia.org/wiki/Decorator_pattern

Wednesday, March 31, 2021
 
Kemrop
answered 7 Months ago
18

You can use the strategy pattern or something like it to use has a (composition) instead of is a (inheritance):

public class TypeA : CustomButtonUserControl, IMagician {
    IMagician magicObj = new Magical();
    public void DoMagic() {
        magicObj.DoMagic();
    }
}

public class TypeB : CustomButtonUserControl, IMagician {
    IMagician magicObj = new Magical();
    public void DoMagic() {
        magicObj.DoMagic();
    }
}

public class Magical : IMagician {
    public void DoMagic() {
        // shared magic
    }
}

There are other ways to instantiate your private IMagician members (such as passing them as a param via constructor) but the above should get you started.

Wednesday, July 28, 2021
 
PeanutsMcgee
answered 3 Months ago
25

A single Android project can indeed have multiple apps, although you could argue about the benefits of having several apps in a single project if they are unrelated.

Anyway, this is perfectly reasonable in case you have several versions of the same app with some differences among them (target devices, branding...). In that case the Gradle build system allows you to have build variants (each build variant being a combination of a product flavor and a build type). According to the official documentation (Configuring Gradle Builds > Work with build variants):

The build system uses product flavors to create different product versions of your app. Each product version of your app can have different features or device requirements. The build system also uses build types to apply different build and packaging settings to each product version. Each product flavor and build type combination forms a build variant. The build system generates a different APK for each build variant of your app.

Sunday, October 10, 2021
 
Dulini Atapattu
answered 7 Days ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :