3

I'm writing an app in modular way, so I can possibly reuse some of the components. I've also written utility functions that are shared among different components. For example, if I have classes A (in A.php), B (in B.php), and C (in C.php), and a function f (in utils.php), and this function is used in both A, B, and C, how does one organize the code?

For testing purposes, I run A.php, B.php, and C.php separately, so I need to include utils.php in all of them. Is doing require_once 'utils.php' in all three files a good solution? I've heard there may be a minor performance issue with using require_once. Or should I maybe write a separate 'test.php', whre I would import all the files I need, and use that code for testing instead of writing tests in actual class files?

  • 1
    Related: http://stackoverflow.com/questions/1812472/in-a-php-project-how-do-you-store-access-and-organize-your-helper-objects – Pekka Dec 12 '10 at 13:16
  • you need to include your utils into some bootstrap file, like one with db settings and stuff. – Your Common Sense Dec 12 '10 at 13:16
  • Also note that require_once operator (as well as other _once stuff) is an ugly crutch, for those who can't control their program flow – Your Common Sense Dec 12 '10 at 13:24
  • @Col. Shrapnel: I do have a bootstrap file which glues the components together. But when I'm testing individual classes, bootstrapping is not run. –  Dec 12 '10 at 13:36
  • How's that? What are you testing then? Make a test environment that includes bootstrap – Your Common Sense Dec 12 '10 at 13:43
  • @Col. Shrapne: Well, I ended up doing something similar. I've moved tests to a separate file, and I've added test-specific bootstapping. Having an application-wide bootstrap there does not make sense for me since I'm deliberately separating the test from the rest of the app for.. err.. testing purposes. :) –  Dec 12 '10 at 20:32

4 Answers4

3

First of all, require_once is certainly not "too" slow for running your tests. Remember, premature optimization is the root of all evil. Yes, it has some overhead, but unless it causes errors or slows down your production environment, don't bother. Measure, measure measure.

A good strategy that i tend to use is similar to the one of Zend Framework.

My classnames are based on my directory structure. For example, a class named Http_Client_Curl would be lokated in the following directory:

Http/Client/Curl.php

With a structure like this, it's very easy and convenient to use auto loading. See spl_autoload_register. This means that you can let PHP automatically include all files and classes as you need them, based on a pretty straight forward convention.

alexn
  • 57,867
  • 14
  • 111
  • 145
2

If you are speaking in terms of PHP 5.3, I believe namespaces and auto-loading would fit right into your application fairly well. On the other hand, legacy code tends to be organized into "libraries" or "includes" with a core "includes.inc.php" that uses the factory method, or various other design pattern, to load the classes.

0

If you’re programming object oriented you’d also put the function f into a class; a utils class in your utils.php file.

require_once may have a minimal hit on performance as it will have to remember and check if a file has already been included, but it’s the best way to include files, to make sure you have the files you need. You can then include all the dependencies of that file/class.

Tests should of course not be in your class files. I don’t quite get if all your classes are for testing now or if you’re testing your classes …

Kissaki
  • 8,810
  • 5
  • 40
  • 42
  • Yes, I'm testing my classes. I typically have a line of if defined('STDIN') and write my test code with assert() within the if block. –  Dec 12 '10 at 13:33
0

Regarding require_once:

Yes, it has some performance issues. When you are sure you are including the file only once, don't put it, it's an unnecessary check.

Some advices:

  • Try to use absolute_path when calling require
  • The time difference between require_once() vs. require() is typically not that significant, with the exception of a very large application that has hundreds of require*() calls, which case it really is slow
  • Use an opcode cache, like APC!
4v4l0n42
  • 313
  • 1
  • 2
  • 6
  • I try to use dirname(__FILE__) where applicable. And in the bootstrapping code, I define a $BASEPATH variable that contains the dir name of the bootstrap.php which is placed in the project root and always run. –  Dec 12 '10 at 13:35
  • Being sure to do less checks is not really a good idea. :) You never know what will come or what others do with your code. – Kissaki Dec 12 '10 at 13:35