PHP - Object Oriented Practices and Inheritance - php

This is the basic class design
class CustomModule {
public __construct() { }
//Run me first automaticly
public function exec($str) { }
}
class Randomizer extends CustomModule {
public __construct() { }
//Call me
public function exec($str) { }
}
As I am designing a plugin/module system for extern developers I need the CustomModule->exec() to run first, I do not want to leave it up to the devs to have to call base->exec($str).
I want CustomModule::exec() called automaticly before Randomizer::exec() is called without having to put code in Randomizer::exec(). Is This Possible perhaps with magic function?

In my opinion, i would use this way:
Instead of calling _construct in exec of Randomizer, you can define a constructor in Randomizer and call parent::_construct
class CustomModule {
//Run me first automaticly
public function exec($str) { }
public __construct($str) {
$this->exec($str);
}
}
class Randomizer extends CustomModule {
//Call me
public function exec($str) {
parent::__construct($str);
}
}

If your object requires some initialization before you can "release* it into the rest of application, then it means that you need a factory for this. This is how you should be solving it, if you require to call some method only once.
If such execution happens each time you call exec() method, then instead you should be using some sort of containment (in a form of decorator or just you standard composition of objects).
Basically, you need to restructure your code.

After a bit more thought I realized this is BAD design. I have to keep the code base simple and scaleable and this would only make a mess in large projects.
As the only program calling the Randomizer::exec() is my inhouse built program I can just call CustomModule::exec() on the previous line and get a boolean response to see if it should continue to the next line.
Sorry to have to end this Q' short

Related

PHP: Logging or tracking when an inherited class calls a parent function

I'm in the process of trying to track outdated or unused functions inside an object class. One idea I had was to create a new class that inherits that original class, and then "track" when that parent's functions are called. When detected, I will migrate the parent's function into the child until eventually only the necessary/needed functions exist.
Is there code that does this automatically within PHP? Here is in example.
class OldUser {
function getFullName() {
return "{$this->firstName} {$this->lastName}";
}
}
class User extends OldUser {
}
-----
$user = new User;
echo $user->getFulLName();
Then in a log somewhere I note:
"{timestamp} function getFullName() called"
Obviously I could add these logs manually, but if there is an existing way for PHP to do it I'd love to default to that methodology.
Alternatively, if there is a better way to do this I am open to suggestions.
Thanks!
If your code is too magic for static code analysis tools, you should probably write some integration/functional tests for your app and take a look at code coverage - non-covered methods may be a dead code (or you need more tests). After this you will not only have cleaner code, but also useful test, so two birds with one stone. :)
One possible way to achieve this without having to manually add the calls is to use a class that doesn't inherit the class you want to track/log:
Something around these lines should do it:
class User{
private $old_user;
// use the same signature of your class constuctor here
public function __construct($arg1, $arg2, ...)
{
$this->old_user = new OldUser($arg1, $arg2, ...);
}
public function __call($name, $arguments)
{
log(sprintf("%s: function %S() called", date('Y-m-d H:i:s'), $name));
call_user_func_array([$this->old_user,$name], $arguments);
}
}
All you need to do from there is implement all of the public methods of OldUser and have those calls trigger the logging and then call the parent function. eg:
class User extends OldUser {
protected function log($method, $backtrace) {
// ...
}
public function getFullName() {
$this->log(__METHOD__, debug_backtrace());
return parent::getFullName();
}
}
debug_backtrace() will allow you to track down where in the code that the function was called.

how to call parent constructor just once in all child instances in php

I am trying to develop an object oriented PHP application in which whole php application will be extending from MyApplicationBase base class. But the problems is I want to create only single instance of MyApplicationBase. Below is the code which explains what I mean
class MyApplicationBase{
static $called=0;
public var $db;
function __construct()
{
self::$called++;
echo "<pre>MyApplicationBase Created ".self::$called." times</pre>";
$this->db=new DatabaseWrapper();
}
}
class ApplicationSecurity extends MyApplicationBase{
function is_logged_in()
{
$res=$this->db->query("user check db query goes here");
return ($res)?true:false;
}
//..... other methods related to ApplicationSecurity class
}
class ApplicationBusinessLogic extends MyApplicationBase{
// business logic methods here which may use base class vars like $db
// this may also use instance of ApplicationSecurity class
}
class ApplicationTemplating extends MyApplicationBase{
protected function outputHeader()
{
require_once('path/to/themes/header.php');
}
protected function outputSidebar()
{
require_once('path/to/themes/siderbar.php');
}
protected function outputMainbody()
{
require_once('path/to/themes/mainbody.php');
$app=new ApplicationBusinessLogic();
$app->initiate();
}
protected function outputFooter()
{
require_once('path/to/themes/footer.php');
}
public function outputTemplate()
{
$this->outputHeader();
$this->outputSidebar();
$this->outputMainbody();
$this->outputFooter();
}
}
//index.php file code starts here--------
$myPhpApplication = new ApplicationTemplating();
$myPhpApplication->outputTemplate();
My goal is when I create instance of my application then It only call the single instance of "MyApplicationBase" class instead of calling it multiple times. Please do tell me how can I achieve this. I am google for 5 hours but unable to find any solution yet.
I am trying to develop an object oriented PHP application in which whole php application will be extending from MyApplicationBase base class.
As PHP has single inheritance, this is by far the most worst idea to do object oriented PHP programming.
But the problems is I want to create only single instance of MyApplicationBase.
As every class is a MyApplicationBase you actually don't want that because it would mean you could instantiate exactly one class in your whole application.
What you're probably looking for is some kind of ApplicationClass which you pass along and of which just a single instance exists.
This would at least allow you in the future to throw such a "block in road" away more easily then if you would have got extended from there.
In any case you should program against an ApplicationInterface instead of an ApplicationClass to make this throwing away - as it will be necessary - easier.
The best thing for sure would be to not do anything in that direction and only write code you need in the first place.
To only write code you need, you need to develop test-driven. Why not start with that if you want to do object oriented programming?
Well I suppose that you want to avoid multiple connections to the database in this case. Solution is simple with Dependency injection, just initialize your database connection outside of MyApplicationBase class and then pass it as a constructor parameter (beware of constuctor hell though). Like this:
class MyApplicationBase{
static $called=0;
public $db;
function __construct($db)
{
self::$called++;
echo "<pre>MyApplicationBase Created ".self::$called." times</pre>";
$this->db= $d;
}
}
$db = new DatabaseWrapper();
$templating = new ApplicationTemplating($db);
$security = new ApplicationSecurity($db);
You could also take a look at some framework, they usually come with some dependency injection capabilities.

Phpunit does not execute effective parent test case?

I'm currently testing a wrapper to an API with PHPUnit (CLI).
Due to the nature of the tests, I can pretty much use the same code for testing two different use cases. The only difference is in the values I send to the API as parameters.
So, I decided to write a class DefaultTest, where I test the API using default values used by the API and a second CustomTest(Case) where I test my parameter container with differing values. CustomTest inherites from DefaultTest, as all the functions used for validating the returned data are equivalent in both cases.
Here's some code for your understanding:
class DefaultTest extends PHPUnit_Framework_TestCase {
public function testAPIMethod()
{
$this->checkParameterContainer();
$this->validateResults();
}
public function checkParameterContainer()
{
/* Set up default parameter container */
}
public function validateResults()
{
/* Validate the results */
}
}
class CustomTest extends DefaultTest {
public function checkParameterContainer()
{
/* Set up custom parameter container */
}
public function validateResults()
{
parent::validateResult();
}
}
PHPUnit takes the child class, executes the testAPIMethod, leading to CustomTest::checkParameterContainer() and DefaultTest::validateResults() being executed.
But DefaultTest's testAPIMethod is never executed, as DefaultTest::checkParameterContainer() is never called.
Both classes are fully valid TestCases and DefaultTest is executed normally when not specialized.
So, my question for you guys: Why is that? Do I miss something here? Is this by design?
In case, somebody needs it: PHPUnit uses reflection to find test methods on each class, but will not search in parent classes. So the following will be needed in the child test class:
public function testAPIMethod()
{
parent::testAPIMethod();
}

PHP extending a class

I have a question about extending a class in PHP.
The examples I see on the php site just have 1 line of code in the method...is it the same if the method has tons of code??
If this is the base class:
class BaseClass {
public function WithWayTooMuchCode {
// like 100 lines of code here
}
}
Then do I have to copy all the code over if I want to use the same method, but change only 1 or 2 things?
class MyOwnClass extends BaseClass {
public function WithWayTooMuchCode {
// like 100 lines of code here
// do I have to copy all of the other code and then add my code??
}
}
This seems a little not DRY to me...
Yes, unless those 1 or 2 things happen to be at the beginning or the end. You can call the parent function via
parent::WithWayTooMuchCode();
Which you can place anywhere in the child/overridden method.
If it doesn't feel DRY, consider splitting the function into smaller methods.
do I have to copy all the code over if I want to use the same method,
but change only 1 or 2 things?
No, you don't have to copy all of the code, assuming you're adding to the function and not removing pieces of it.
so it follows:
class BaseClass {
public function WithWayTooMuchCode {
// like 100 lines of code here
}
}
class MyOwnClass extends BaseClass {
public function WithWayTooMuchCode {
parent::WithWayTooMuchCode();
//additionally, do something else
}
}
$moc = new MyOwnClass();
$moc->WithWayTooMuchCode();
You can use the parent::WithWayTooMuchCode() wich will execute the parent method and after you can add your code. It will look like this :
class MyOwnClass extends BaseClass {
public function WithWayTooMuchCode {
parent::WithWayTooMuchCode()
// do I have to copy all of the other code and then add my code??
}
}
You can write down a separate function for that things that you want to do separately in parent class and then Call then in you way.
In other words, separate out the things you need to do separately ans create a function for them. And call them separately in child class. The final function in child class will call parent class function as well those separate functions.
You have a few choices. Assuming;
class BaseClass {
public function WithWayTooMuchCode {
// like 100 lines of code here
}
}
You can do
class MyOwnClass extends BaseClass {
public function AnotherFunction() {
// put other code here
}
}
This allows you to do MyOwnClass->AnotherFunction() and MyOwnClass->WithWayTooMuchCode()
or you could do
class MyOwnClass extends BaseClass {
public function WithWayTooMuchCode() {
// put new code here
}
}
which will allow you to run MyOwnClass->WithWayTooMuchCode() and will ONLY run the "new code", not the "100 lines".
Finally you could do
class MyOwnClass extends BaseClass {
public function WithWayTooMuchCode() {
parent::WithWayTooMuchCode();
// Do more processing
}
}
which will allow you to run MyOwnClass->WithWayTooMuchCode() will run the "100 lines of code" AND the new code. You can put the parent before/after/during your new code, so you can tailor it as required
In addition to the other answers I should point out that this problem can be addressed by events. They are a way to determine points in a class where you can add your own functionality from outside. If you have control over the codebase and the time/inclination you might want to consider implementing this functionality. Unfortunately PHP doesn't support them directly in the way that, say, C# does so you'd have to do the work.
If you only have this issue in a single place I doubt you should bother, but if it's becoming a pattern you might want to consider this approach.

PHP: run class method when another class method is run?

PHP:
run function when a specific class method is run
what I want is to run some additional functions when a class method is run without altering the already existing class.
how?
With a decorator:
class MyClassDecorator
{
protected $decoratedInstance;
public function __construct($decoratedInstance)
{
$this->decoratedInstance = $decoratedInstance;
}
public function methodNameInOriginalClass()
{
$this->decoratedInstance->methodIWantToRunBefore();
$this->decoratedInstance->methodNameInOriginalClass();
$this->decoratedInstance->methodIWantToRunAfter();
}
public function __call($method, $args)
{
if (method_exists($this->decoratedInstance, $method)) {
return call_user_func_array(
array($this->decoratedInstance, $method),
$args
);
}
}
}
The above assumes that the methods you want to call are public on the $decoratedInstance.
That is not possible, you will have to alter the function to achieve that. But you might be in need of an observer pattern (The zend guys describe the observer pattern on zend.com, too)
Your best bet is to extend the original class and override the method adding your code.
class MyClass extends OriginalClass
{
public function originalMethod()
{
parent::originalMethod();
// My code...
}
}
$myClass = new MyClass();
$myClass->originalMethod();
What you are trying to do is called Aspect Oriented Programming.
Currently PHP has not support for that out of the box, although you can use extensions. Here is post that explains some of the options: http://sebastian-bergmann.de/archives/573-Current-State-of-AOP-for-PHP.html
runkit: Replace, rename, and remove user defined functions and classes.
funcall: Call callbacks before or after specified functions/methods being called.
intercept: Allows the user to have a user-space function called when the specified function or method is called.
not that using these is necessarily a good idea.

Categories