Simply question of theory
When building a class that is not going to be used by any other client-coders, what is the best method of execution? Consider the following:
class Test
{
public function __construct()
{
$this->foo();
$this->bar();
}
public function foo(){ //do something }
public function bar(){ //do something }
}
$test = new Test;
As I know exactly what I want this class to do, and the order it should be done in, I simply call the functions during construction. However The same can be done by doing:
class Test
{
public function __construct(){}
public function foo(){ //do something }
public function bar(){ //do something }
}
$test = new Test();
$test->foo();
$test->bar();
What are the advantages to doing it one way or the other? Be it performance, debugging, etc.
Edit
This is a general purpose question. Looking to hear all possibilities and concerns regarding these two ways of executing methods within a class.
In the 1st way you can make those functions private and use them only within the object itself.
class Test
{
public function __construct()
{
$this->foo();
$this->bar();
}
private function foo(){ //do something }
private function bar(){ //do something }
}
$test = new Test;
//so:
$test->foo(); //will throw an error
If you make the functions protected instead of private, any class that inherits from this class would be able to to use the functions (while still not allowing for the functions to be called on the outside)
With your second option, any object can call those functions outside the class definition, and depending on your code, you might not want that.
To elaborate on Neal's answer: If you can, make the functions private. That way, if you want to change them later, you know they are only used within their class.
So, to answer you question: The first answer is preferred because is makes your code easier to maintain. Performance wise, there is no difference.
Related
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.
I'm writing a plugin for WooCommerce, Today something came across my mind suddenly, I was thinking if there is a way to expend PHP Classes like the way we do that in JavaScript without touching anything in the PHP class( Since WooCommerce will get updated and our changed will be gone ).
I found solutions like using __call method but like i said, the class shouldn't be edited. I want to be able to use something like this WC()->My_custom_method() without touching Woocommerce class.Is it even possible?
For example in JavaScript all we need to do is :
Foo.prototype.bar = function (){
// ...
}
Foo.bar();
PHP does not have prototypical inheritance and classes have no prototype like in JavaScript. You can simulate what you are asking with some hackery, but that will ultimately result in hard to maintain code. So don't go there.
There is a GitHub project at https://github.com/bdelespierre/prototype.php with a Proof of Concept implementation. You might find it interesting to study.
Needless to say, if your aim is just to add some functionality to a class, you can still use PHP's inheritance, e.g. extend the WooCommerce class and add your modifications in the subclass. Then use an instance of that new class instead, e.g.
class MyClass extends SomeWooCommerceClass {
public function bar() {
// your own implementation of bar
}
}
$myObj = new MyClass();
$myObj->bar();
If your aim is to change the behavior of an existing object instance, consider wrapping the instance into a Decorator, e.g.
class WooCommerceDecorator {
private $instance;
public function __construct(SomeWooCommerceClass $instance) {
$this->instance = $instance;
}
public function foo() {
$original = $this->instance->foo();
$original+= 42;
return $original;
}
// … more methods
Then use it by passing the object to the decorator:
$woo = new SomeWooCommerceClass();
$decoratedWoo = new WooCommerceDecorator($woo);
echo $decoratedWoo->foo();
Also see the PHP manual on Inheritance
Your best call would be to use extended class.
class MyClass extends Foo {
public function methodInFoo() {
echo "I Am extended";
parent::methodInFoo();
}
public function additionalFunction() {
echo "I am new method that is not presented in Foo";
}
}
That way you even can have Composer to auto-update core classes and while you are using this extended class, you will have your own functions along with all functionality in core class.
I don't recommend this but you could do something like
class Test {
private $myMethods = array();
public addMethod($name, $func) {
$myMethods[$name] = $func;
}
public callMethod() {
$myMethods[$name]();
}
}
....
$test->addMethod("doSomething", function(){ echo 123;});
$test->callMethod("doSomething");
I didn't test the code it's just an idea
I am looking for a way to redeclare, overwrite or rename a function in PHP4, in order to perform a unittest on a class that makes a call to another function. I want this function to be a test function instead.
I have several constraints:
It has to work for PHP4.
It has to work right out-of-the-box WITHOUT installing something else. (No adp or whatever).
Technically, it is possible using the override_function() or rename_function() functions.
That's not a very clean way to handle it though, and instead I'd recommend that you update your class to allow you to redirect the call somewhere else.
For example, you can change this:
class MyClass {
public function doSomething() {
...
do_complex_calc();
...
}
}
To something like this:
class MyClass {
public $calc_helper = 'do_complex_calc';
public function doSomething() {
...
$helper = $this->calc_helper;
$helper();
...
}
}
$x = new MyClass();
$x->calc_helper = 'another_func_for_testing';
$x->doSomething();
That can be cleaned up even more, but it shows the general idea. For example, I wouldn't recommend leaving the $calc_helper variable as public - I'd implement some sort of a method to let you change it instead.
for overwriting the function you can check if function exits using function_exists but you can redeclare the function
if (!function_exists('function_name')) {
// ... proceed to declare your function
}
I am trying to separate my interface and implementation. So I have a bunch of functions that perform various tasks. I originally had them all as Public and then I would call them from other pages. I am trying to tighten this up by making all of the real workload functions private and then using 1 public function to call them.
Here's what I am trying:
class TestClass
{
public function pub1()
{
$this->test1();
$this->test2();
$this->test3();
}
private function test1()
{
$t1 = '1';
return $t1
}
private function test2()
{
$t2 = '2';
return $t2
}
private function test3()
{
$t3 = '3';
return $t3
}
}
I think this works but I cannot figure out how to call the functions. I can call pub1() fine but I cannot seem to call the functions below test1(), test2(), test3().
I can make this work if I do a one for one of the public to private functions but I was hoping to not have to do that.
Any help on this would be great.
Thanks!
Your call to pub1() should be correctly calling test1(), test2(), and test3() as you have written it. However, your test functions are returning a value, which your pub1() function then throws away. If you don't need to actually return anything from those test functions to the caller, then you should be ok as is.
You should rethink your design.
Objects have a strong relation with the real world. See the object as a black box, and look what properties and methods you need on the outside.
So:
if you want to call a function outside of a class use a public.
If you want to call a function inside a class or in a derived class, use protected.
If you want to call a function only inside a class, use private.
If you have a interface, define it! And let a class implement it.
Maybe something like this?
public function pub1 ($name) {
return $this->$name();
}
I have a set of independent functions which I want to put in a class.
They do not depend on any objects of the class, so while calling them, all the values required would be passed as arguments.
Is it fine if I declare all of them as static so that i can call them with just one command like className::functionName(argument1,argument2,...)
or do i keep them as normal public function and call them through a class object?
You can (but you shouldn't do it):
class YourClass {
public static function yourMethod( ) {
echo "method called";
}
}
YourClass::yourMethod();
The reason why you shouldn't do it is because when you use the static call in some other class / function / whatever you have tightly coupled the YourClass to the other class. hence you are making it pretty hard to do unit tests or simply switch to another moethod without going trhough all the code where it is used. And also don't forget you just added something globally.
You also say:
I have a set of independent functions which I want to put in a class.
This is a big code smell in my book. This makes it sound like your class violates the SRP principle in SOLID programming.
Hence I would just instantiate the class.
Let's see why it makes your code hard to test:
class SomeClassWithMethods
{
public static function doSomething()
{
}
}
class SomeClassYouWantToTest
{
public function doSomething()
{
return SomeClassWithMethods::doSomething(); // this is now tightly coupled and would be impossible to mock when unit testing it
}
}
Also that that SomeClassWithMethods::doSomething is now globally defined.
We like to call this the silver bullet :) :
Yes this is not bad.
You can define them as static functions and like you said - you can call them with just one statement.
class Foo {
public static function bar( ) {
echo "bar called";
}
}