I'm trying to pull of something like this:
class helper {
.. some class variables ..
public function somehelper ($somevar)
{
.. some action ..
}
}
to - $somehelper('somevar!')
i want it to be a lambda function without me declaring a new lambda function. I want the code to be created automatically. I want to create this lambda function autamatically via a core class that will create to each helper function - lambda function with the functions name. I dont want to specify it. I have a template file included, and an instance of a class helper. <a href..><?= $makeSeo($url); ?></a> this will lead to - public function makeSeo($url) in a helper class. autmatically.
Thanks in advanced!
Sounds like you want something to create a lambda given a method name? Assuming your 'Helper' class methods are static, something like this would do it
function makeHelper($fn)
{
//note use of PHP5.3 closure syntax
$helper = function($param) use ($fn) {
return Helper::$fn($param);
};
return $helper;
}
//create a new lambda
$foo=makeHelper('somehelper');
//call it...
$foo('Hello world);
I think you're saying that you want the variable $somehelper to call helper::somehelper from outside the context of the class.
$somehelper = function($somevar) {
return helper::somehelper($somevar);
});
This presume that the somehelper is intended to be a static function (i.e. should be marked as public static function. If it is not, you're going to have to provide more information about where the class instance comes from.
Related
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');
Let's say I have a class:
class test {
public static function sayHi() {
echo 'hi';
}
}
Call it by test::sayHi();
Can I define sayHi() outside of the class or perhaps get rid of the class altogether?
public static function sayHi() {
echo 'hi';
}
I only need this function to encapsulate code for a script.
Maybe the answer is not a static method but a plain function def?
A static method without a class does not make any sense at all. The static keywords signals that this method is identical for all instances of the class. This enables you to call it.. well.. statically on the class itself instead of on one of its instances.
If the content of the method is self-contained, meaning it does not need any other static variables or methods of the class, you can simply omit the class and put the code in a global method. Using global methods is considered a bad practice.
So my advice is to just keep the class, even if it has only that one method within. This way you can still autoload the file instead of having to require it yourself.
Functions in OOP are public by default, you can modify them to private like:
private function test(){
//do something
}
Or like you said, to static, in public or private like:
private static function test(){
//do something
}
But if you're not using OOP, functions by default are global and public, you can't change their access to private. That's not the way they are supposed to works because if you change their type to private, you will NEVER be able to access to that function. Also, static doesn't works because is another property of OOP...
Then, you can simply create that function and access it from everywhere you want (obviously where is available :P because you need to include the file where is stored)
Let's say we've implemented a abstract class which holds some tools. For example a mail function:
abstract class Tools {
public static function sendMail () {
// do some magic mail sending
}
}
Now we have an index.php file, which uses the framework Flight for instance (doesn't mind which framework in particular).
In this index.php we define some routes and assign callback functions to be called if a certain route is requested.
Flight::route('POST /mail', Tools::sendMail);
If I try this code PHP returns this exception:
Fatal error: Undefined class constant 'sendMail'
Is there a way to pass a function like this in PHP?
Use a callable:
public static function route($method, callable $callable)
{
$callable();
}
Flight::route('POST /mail', function () { Tools::sendMail(); });
You can use this:
[__CLASS__,'MethodName']
if the callback is made in the same class or
[Class::class,'MethodName']
if it is not.
You'll need to pass 2 things in order to reference a static class method: The name of the class, and the name of the static function to call
//define the method
function callStaticClassMethod($className, $funcName) {
$className::$funcName();
}
//call the method
callStaticClassMethod('Tools', 'sendMail');
I'm not aware of any other way to directly reference a static function.
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();
?>
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.