php extending classes - php

I'm using a salesforce class called SforceEnterpriseClient. I've referenced that class many places in my application. I want to extend that class to give it the ability to return a single array from a 1 row recordset, right now the record set is about 3 levels deep. There's a few other things I want to do with it as well. I can handle all that.
Everything I've read about classes says that when I extend a class, I need to call the new one as such:
class MySF extends SforceEnterpriseClient {};
$mySforceConnection = new $MySF;
That means in all of my existing code I have to find/replace.
Is it possible to overwrite the parent with the child so I don't have to play the find/replace game?
class SforceEnterpriseClient extends SforceEnterpriseClient {};
$mySforceConnection = new $SforceEnterpriseClient ;

You can probably play some classloading tricks with the magic __autoload() function and removing references to the salesforce file ie. require, require_once, include, include_once; But in the interest of readability and maintainability, you should probably take the long route here and modify all your references to use the subclass.

How about this, in the source file for the class, rename the class (and most likely the constructor as well) then extend the class using something like
class SforceEnterpriseClient extends renamedClass {};
Then rename the file and create a new file with the old name and include the renamed file. Put the code for your extended version in the new file. The final result is that every file that was using the original will see the new version without having to track them all down.
About the only major issue would be what happens when a new version of the class becomes available.

Unfortunately, that would be the only way to do so. You cannot reverse inhertiance. Sorry and good luck!
Kyle

Maybe you do not need to extend the class in this scenario. You extend a class when you want to add new functionality or change existing functionality AND keep the original class intact. Usually this is the way to go. But, if you need to make a change to an existing class and then update all references to the class to refer to the new class why not simply change the class code itself? That way the references would not have to change.

Also have a look at the factory pattern. Normally you should keep class creation and business logic separate.
So when you come across a problem like this, you only have to go and change the factory...
$sfEnterpriseClient = Factory::getSFEnterpriseClient($params);
that way you can avoid 'new' constructs in your business logic, and makes your code more manageable

Related

PHP 4 class autoloader

I'm working in PHP 4 with classes but there's not __autoload function, so I have problems to load my classes because they are intertwined.
I have a class Ship and a class Movement. The class Ship contains an Movement object and the class Movement contains an Ship object.
So when I do the require Ship, the class is read and throws error when reach the new Movement and conversely.
Some solution? ;)
PHP 4 is really, really old and not-supported. The best option is to move to PHP 5.
If you can't, create a bootstrap file, which requires all class definitions (in the correct order in case of inheritance); make sure the class definition files contains only class definition (and not executable code like $obj = new Movement) and require this file in each file you are actually running in your application.
The point is, the class definition of Movement is not needed before the new Movement statement, and if this statement is in some Ship's method (even if it's in the constructor), you can safely load the Ship.php, then Movement.php, then run the code and it will work.
Also, make sure to load all class definitions before starting the session, if you are using sessions and serialize objects in it.

Open / Closed principle - How to call the new versions?

I'm trying to grasp the Open/Closed principle (in my case for PHP, but that shouln't really make a difference).
The way i understand it is that a class is never open for modification. Only for bug fixing. If i wanted to add new code to the class, then i'd have to create a new one and extend the 'old' class. That's the only way i can add new code to it.
In a way i can see the advantages of this. Because basically you create some sort of versioning system, where old code always work, but you can always try to use the new classes too.
But how does this work in practice? I mean, suppose i have the following class:
class MyObject
{
public function doSomething()
{
echo 'Im doing something';
}
}
So somewhere i'm probably instantiating this class:
$obj = new MyObject();
But then i decide that it's good to have another method in that object. So i can do something else too. According to the OCP i can't modify the class. So i have to create a new one, which extends to old one right?
First problem. How do i call the new class? Because it isn't really a complete new object. Like. a User object is a User object. I can't suddenly give it completely diffent name just because it needs another method. Anyway, i create the new class:
class MyNewObject extends MyObject
{
public function doSomethingElse()
{
echo 'Im doing something else now';
}
}
Now this also means i have to change the line of code where i instantiated the "MyObject" class and replace it with the "MyNewObject" class, right..? And if that's done in more than one place, then i have to search through my source code... (Think about a method in a controller class, which almost always uses the 'new' keyword to instantiate certain classes).
The same basically applies to inheritance. I'd have to find each class the inherits the old class and have to replace that with the new class.
So basically my questions are:
How do you name the new classes which have the new methods? Just becasue i added some new functionality, doesn't mean i can give the class a whole new name...
And what if the 'old' classs is instantiated (or inherited) from multiple places. Then i'd have to find all of those places... Where's the gain?
The Open Closed Principle isn't intended to be used as a kind of version control system. If you really need to make changes to the class, then go ahead and make those changes. You don't need to create new classes and change all the places that instantiated the old one.
The point of the Open Closed Principle is that a well-designed system shouldn't require you to change existing functionality in order to add new functionality. If you are adding a new class to the system, you shouldn't need to search through all your code to find the places where you need to reference that class or have special cases for it.
If the design of your class isn't flexible enough to handle some new piece of functionality, then by all means change the code in your class. But when you change the code, make it flexible so you can handle similar changes in the future without code changes. It's meant to be a design policy not a set of handcuffs to prevent you from making changes. With good design decisions, over time your existing code will require fewer and fewer changes when you add new functionality to the system. It's an iterative process.
I would argue that by adding a function, you're not modifying the class behavior.
In all the instances where doSomething() is currently being called in your app, simply by adding doSomethingElse() to the class will have no effect. Since you're not changing doSomething(), the behavior is the same as it was before.
Once you determine that your doSomething() implementation isn't cutting it for certain circumstances, you can extend the class and override doSometing(). Again, the original still behaves the same as it always did, but now you have a new doSomething() to work with also.
I realize that this goes against the strict definition of open/closed, but this is the real world, and that's how I interpreted that principle in my code.
You need to create a constructor in your MyNewObject class which calls the parent class' constructor:
function __construct() {
parent::__construct();
}
This way you can instantiate the new class and still access all the functionality of the extended one.
You can then also override any function in the parent class (as long as it is not marked final of course).
So you could do:
$newObj = new MyNewObject();
$newObj->doSomething();
$newObj->doSomethingElse();

PHP workaround to extend classes of the same name?

I know extending a class with the same name is not possible, but I was curious if anyone knew of a way to load a class then rename it, so i can later extend it with the original name. Hopefully like something below:
<?php
//function to load and rename Class1 to Class2: does something like this exist?
load_and_rename_class('Class1', 'Class2');
//now i can extend the renamed class and use the original name:
class Class1 extends Class2{
}
?>
EDIT:
Well, I understand that this would be terrible practice in a basic OOP environment where there are large libraries of class files. But i'm using the CakePHP MVC framework and it would make great sense to be able to extend plugin classes in this way since the framework follows a well established naming convention (Model names, view names, controller names, url routes (http://site.com/users), etc).
As of now, to extend a CakePHP plugin (eg: Users plugin) you have to extend all the model, view, and controller classes each with different names by adding a prefix (like AppUsers) then do some more coding to rename the variable names, then you have to code the renamed url routes, etc. etc. to ultimately get back to a 'Users' name convention.
Since the MVC framework code is well organized it would easily make sense in the code if something like the above is able to be implemented.
I'm trying to work out why this would be necessary. I can only think of the following example:
In a context that you have no control over, an object is initialised:
// A class you can't change
class ImmutableClass {
private function __construct() {
$this->myObject = new AnotherImmutableClass();
}
}
$immutable = new ImmutableClass();
// And now you want to call a custom, currently non existing method on myObject
// Because for some reason you need the context that this instance provides
$immutable->myObject->yourCustomMethod();
And so now you want to add methods to AnotherImmutableClass without editing either Immutable class.
This is absolutely impossible.
All you can do from that context is to wrap that object in a decorator, or run a helper function, passing the object.
// Helper function
doSomethingToMyObject($immutable->myObject);
// Or decorator method
$myDecoratedObject = new objectDecorator($immutable->myObject);
$myDecoratedObject->doSomethingToMyObject();
Sorry if I got the wrong end of the stick.
For more information on decorators see this question:
how to implement a decorator in PHP?.
I happen to understand why you would want to do this, and have come up with a way to accomplish what the end goal is. For everyone else, this is an example of what the author may be dealing with...
Through out a CakePHP application you may have references to helper classes (as an example > $this->Form->input();)
Then at some point you may want to add something to that input() function, but still use the Form class name, because it is through out your application. At the same time though you don't want to rewrite the entire Form class, and instead just update small pieces of it. So given that requirement, the way to accomplish it is this...
You do have to copy the existing class out of the Cake core, but you do NOT make any changes to it, and then when ever you upgrade cake you simply make an exact copy to this new directory. (For example copy lib/Cake/View/Helper/FormHelper.php to app/View/Helper/CakeFormHelper.php)
You can then add a new file called app/View/Helper/FormHelper.php and have that FormHelper extend CakeFormHelper, ie.
App::uses('CakeFormHelper', 'View/Helper');
FormHelper extends CakeFormHelper {
// over write the individual pieces of the class here
}

PHP OOP - Require or Extend

I was wondering if there is any major different in the following, and whether one is more 'standard' than the other:
<?php
class Account extends Database {
public function myMethod()
{
// Do something
}
}
?>
or
<?php
require('database.class.php');
class Account {
public function myMethod()
{
// Do something
}
}
?>
Cheers :)
Edit:
This question actually relates to a tutorial series I have been following which describes the above two methods - which didn't make any clear sense.
So thank you for the constructive answers on clearing that one up!
Those are two completely separate language constructs.
Your first example deals with inheritance. Basically, you already have a class called Database, but you want to have a specialized version of that class to handle accounts. Rather than build a brand new Account class and copy/paste all the functionality you already have in your Database class, you simply tell PHP that you want to use the existing Database class as a baseline. You create any account-specific functionality in the new Account class, and anything database-related comes automatically. This is assuming, of course, that you have some way of specifying where the Database class is defined - for example, a require declaration at the top of the class, or an __autoload() or spl_autoload_register() function call defining a way to find and locate the file containing the Database class.
In your second example, your database-related code is completely separated from your Account class. They're completely distinct entities, and if you wanted to do anything database-related in your Account class, you would have to explicitly instantiate a new Database object within that class (or pass it to that class, or one of its functions, as a parameter.
Basically, extends helps define what a class is, whereas require shows where a class definition (or other code) is stored.
Both code snippets aren't even equivalent.
The first declares Account to extend Database, a is-a relation.
In the second code snippet, you are simply saying that you require 'database.class.php' ... and that neither has anything to do with OO, nor defines a is-relation from Account to Database.
Both are completely different in first one class is inherited by another class but in the second one the class is included in your script only.
Means if you extend all the public and protected methods are available in your derived class and you can create object of derived class and can use methods with derived class's object.
But in the second method the class is included in your script and require this class it's own method and work independently.
The first means you create a new class, which has all the functionality of Database class and those you implement.
The second means that you create a new class, but it doesn't have Database functionality since it's not extending it. If you need database access in your Account class, you can create an instance in constructor, or pass already created instance as constructor parameter.
It's hard to say what is more standard, since it depends on what You actually want to achieve.
To put it in most simple terms:-
require or include is structural programming.
extends is object oriented

php dynamic class inheritance

I know I can generate a class at runtime by executing
$obj = (object)array('foo' => 'bar');+
this way I can use
echo $obj->foo; //bar
What if want to make $obj inherits from an existing class?
What I wanna achive:
I'm forking paris project on github (https://github.com/balanza/paris). It's an active record class. I wonder I need to declare a class for every object, even if it's empty:
class User extends Model{}
I guess I might use dynamic object to avoid this boring stuff.
You could always do eval('class User extends Model{}') but is not a good idea. Really, you should just create the class in a file, then opcode caching will work properly, it can be version tracked, etc etc.
tl;dr: Define the model class, it is the Right Thing To Do™.
If there is really no other way for you to do it, you can create a "dynamic" inheritance with my Dynherit class. It creates the inheritance you want but from files and only with classes you didnt already loaded.
Download v0.62 : http://optimisationphp.komrod.com/source/sha/test/dynamic_inheritance_01/dynherit_v0.62.zip
GitHub link : https://github.com/Komrod/Dynherit
Strictly to your question, the only way I can see it possible is by using Runkit, which let's you re-declare classes on the fly. Not sure how portable that solution is.
You can use a Prototype design pattern to clone an object, then you can add everything you need in cloned one

Categories