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();
}
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.
So I am making a Magento module in PHP. I want my logging to be consistent across all classes. My idea was to define a method in the helper class and call it. However being the pre-optimizer that I am, I figure making multiple calls to a class via the Mage::Helper() method to be more expensive than it needs to be, especially since most of my logging in singleton models anyways. So my now my idea is to use closures, define my method in the helper, make one call to the helper and register the method in a class variable.
class Comp_Mod_Helper_Data extends Mage_Core_Helper_Abstract {
public function getLogger() {
return function ($obj, $type= Zend_Log::DEBUG) {
Mage::log($obj, $logType, 'comp-mod.log', true);
};
}
}
Use:
class Comp_Mod__IndexController extends age_Core_Controller_Front_Action {
private $_log;
protected function _construct() {
$this->_log = Mage::Helper('mod')->getLogger();
}
}
However while it works ... it is not great to use. I'm either stuck doing:
$log = $this->_log;
$log('hello world');
// one awkward liner
($this->_log)('hello world');
While neat that it works is not readable nor standard, i.e. confusing!. The error that it get when using $this->_log('hello world'); is that the method does not exist. I assume because PHP is looking for a method call when using the syntax $this->method();
I do understand that A) I could just suck it up and use Mage::Helper everywhere, and B) that I could store the helper object in a variable and call like $this->helper->log(), and C) that static variables work, see PHP closure as static class variable
So, is there a way to get a non-static class variable to call the closure instead of looking for a non-existing method?
You could make use of the __call magic method:
class Comp_Mod__IndexController extends age_Core_Controller_Front_Action {
public function __call($method, array $args)
{
switch ($method)
{
case '_log':
return call_user_func_array(Mage::Helper('mod')->getLogger(), $args);
}
return null;
}
}
Then use it like you wanted to:
$this->_log('string to log');
Assuming that I have to create a class that takes some text do some processing and return it ... with no dependency and it's a stateless class..
I'd like to know would be better to create a stateless class without constructor or just create a static class (in php it's just Static methods)
class like this:
class ClassName
{
public function processText($text)
{
// Some code
$text = $this->moreProcessing($text);
return $text;
}
protected function moreProcessing($text)
{
return $text;
}
}
and this:
class ClassName
{
public static function processText($text)
{
// Some code
$text = static::moreProcessing($text);
return $text;
}
protected static function moreProcessing($text)
{
return $text;
}
}
I Know that dependency injection into the class where these classes are used would be better but assume that I just won't have dependency injection..
My question is mainly would it be better to create static class for the simple example above?
Practically you will see no difference whatsoever.
It's only in the syntax, and the ability of a constructor to perform stuff automatically, though you still have to create instances to invoke the constructor, which in this case is not far off calling some equivalent static member function.
However, non-static member functions are supposed to affect internal state so, if you have no state, static member functions seem more conventional, and will be slightly less surprising to users of the class.
The best approach, though, is to stick your functions in a namespace. Classes are for data and functions operating on that data... even static ones.
I am very new to OOP and very rusty on PHP. I was wondering if this is a valid method to call a function from a class?
class newclass {
public function testfunc {
return '1';
}
}
Could I call it like this:
echo testfunc->newclass();
or like this:
echo newclass()::testfunc;
I always see it defined in examples like below and it seemed like extra code?:
$this = new newclass();
$this->testfunc();
echo $this;
Any help would be greatly appreciated as I'm just starting to wrap my head around this OOP thing. If I'm out to lunch maybe someone could suggest a link to a really good guide for a true beginner in classes/OOP. Thanks!
Both ways work and have their use cases.
Your first case is a regular function call using an instance of a class, your second case is a call to a static function.
Static should be used with care and the use of it is very often a sign that refactoring/redesign is necessary.
The point of object oriented programming is to model the world by writing classes (blueprints) and then create as many independent instances of that class with the word new as needed. Each instance is a little organism with the DNA of the class and you can call the same class method on every single instance without influencing the other instances.
A static call however is not related to an instance of a class and therefore there is no object being used. It's a global call of some tool functionality and in fact breaks the idea of encapsulation.
So, I'm not saying there are no use cases for static classes and methods but they should be used with care.
new is the keyword to instantiate the class. If you want to use a method without an instance of the class, it should be a static method. to have a static method, declare the method as static.
class foo
{
public static function bar()
{
return 'hello!';
}
}
How to use it?
echo foo::bar(); //Will print hello
You could make testfunc static and call it like so:
class newclass{
public static function testfunc{
return '1';
}
}
echo newclass::testfunc();
There is nothing like this echo testfunc->newclass(); and doing it like
$class = new newclass();
echo $class->testfunc();
is the proper way to do it when the method is an instance method and not a static one. Note, there is no ability to reference $this within the static method.
You can create a static wrapper for the constructor which would allow for chaining method calls on the same line.
<?php
class ClassA {
static function create() { return new self(); }
function method1() { ... }
}
ClassA::create()->method1();
you can include the php file that contains your functions
<?php
//print.php
function printHello(){
echo "Hello world";
}
?>
then include it and call the function...
<?php
include "print.php";
printHello();
?>
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.