So I have this class:
class A{
public function do_a(){ return 'a_done';};
public function do_b(){ return 'b_done';};
}
So I require the php file and create an instance of the class:
require_once("A_class.php");
$System = new A();
require_once("user_calls.php"); //here I import the user file with the function calls.
user_calls.php contents:
echo 'this was the result of '.$System->do_a();
echo 'this was the result of '.$System->do_b();
So, that does work, but I don't want the user to have to use $System->do_a();, but only do_a();.
Any solutions?
EDIT: I also want to limit the functions the user could call in the user_calls.php file, to basic native php functions and those in class A.
DISCLAIMER: While this code works, and does what you requested, that doesn't mean that I advocate coding like this. It's very hard to follow for other developers (and maybe even you in the future...), and it also makes use of eval(), which is almost always A Bad Thing(tm). That said, here you go:
<?php
class A {
public function do_a() {
return __METHOD__;
}
public function do_b() {
return __METHOD__;
}
}
$aRef = new ReflectionClass('A');
$aPublicMethods = $aRef->getMethods(ReflectionMethod::IS_PUBLIC);
foreach ($aPublicMethods as $method) {
$php = <<<PHP
function {$method->name}() {
global \$System;
return \$System->{$method->name}();
}
PHP;
eval($php);
}
$System = new A();
echo 'this was the result of ' . do_a();
echo 'this was the result of ' . do_b();
Please also note that if your methods use arguments, things get even more hairy. Also, if you name any of your methods the same as a function in the global namespace (ex. substr()), this will attempt to redefine them, and you'll probably get a Fatal Error.
Methods of a class are either instance methods (they act on a particular instance of a class defined by $this) or they are class methods (They aren't tied to any one particular instance of a class, but provide services that fall within the remit of the class.
An instance method is defined as follows:
public function foo()
{
}
whereas a class method is defined with the STATIC keyword.
static public function bar()
{
}
In the instance method you can use $this to get access to the state of the instance on which the method was called. This is not available in the class method because it's not tied to any one instance. It can access other members of the class (provided they're not tied to an instance) with the self keyword though.
Instance methods are called as follows:
$a = new ObjType ()
$output = $a -> foo ();
Class methods are called as follows:
$output = ObjType::bar ();
No matter which approach you use you either have to provide an instance (for instance methods) or a class (for class methods) to call the method. Calling just foo() or bar() will not work.
You'll have to use a closure. Note that it's calling directly from the class definition, not the object:
class test {
function method() {
echo 'method was called';
}
}
$method = function(){call_user_func('test::method');};
$method();
$method();
$method();
//output:
//method was calledmethod was calledmethod was called
To call the method from the object, rather than the class, you'll have to pass the object into the closure:
class test {
var $count = 0;
function method() {
$this->count++;
echo $this->count . "|<br />";
}
}
$obj = new test;
$obj2 = new test;
$method = function($object){call_user_func(array($object, 'method'));};
$method($obj);
$method($obj);
$method($obj);
$method($obj2);
//output:
//1|
//2|
//3|
//1|
But that's not any prettier or simpler, is it?
If you don't want to clutter up your page, just name the object something short:
$pco = new page_controller_object_with_a_long_name_that_is_annoying;
$pco->do_a();
$pco->do_b();
//etc.
Moving it outside the class as suggested by #LucM sounds the easiest way.
Related
This is an odd situation and I think the answer is 'you can't do that, what are you thinking?' but hope someone can prove me wrong.
My goal is to store a globally scoped function in a variable then inject it for execution within a class object.
I would like to avoid using call_user_func() as this searches for the function in the global namespace and is the same effect as if I were to just execute the global function from within the class object. I would like my class to execute the object as if it were an internal class method, not an external function. This comes close but not quite.
I cannot modify the function or wrap it in a class.
(Why am I jumping through these hoops?) Needs to be used within this class to follow a spec.
I know I can just duplicate the function in the class and be done with it, but you know the issues with that (plus it creeps up on SRP.) Reflection would work perfectly but this function is not in a class, it is just out there in an include. I've tried wrapping it an anonymous function and the closure object doesn't execute the function.
Is there any hope to do this? The function is simple, accepts a scalar param, does some stuff to it, returns a value (and is tightly coupled with other code, cannot be moved or changed.)
function someFunction($param)
{
// do some stuff
return $someScalarValue;
}
What I would hope is something like
$func = someFunction([some value]); // doesn't work of course, this would store result in $func
$cls = new SomeClass($func);
Then a method in the class could run the function object, much like call_user_func but not have to search the global namespace.
protected function someThing()
{
$this->injected_function([some class value]); // also doesn't work of course
}
When you use $this you are in the objects instance scope. You could pass a (reference) method into the constructor.
$myFunc = function($arg) { var_dump($arg); return 314; };
class myClass {
private $func;
public function __construct($func) {
$this->func = $func;
}
public function do($value) {
$this->func->call($this, $value);
}
}
$var = 'Hello world!';
$myObj = new myClass($myFunc);
$value = $myObj->do($var); // $value is now 314
If you do not want the function to be stored in global namespace you can just pass even an anonymous function like this on the fly:
$myObj = new myClass(function($arg) { var_dump($arg); return 314; });
$value = $myObj->do($var); // $value is now 314
Thank you #Markkus Zeller for your comments, as I suspected there is no way to do what I originally was tasked, to "inject" a global function as an dependency. There is, but it only really works with anonymous functions.
After a lot of stressful pushback, I convinced our managers that wrapping this in a simple class was the way to go. This,
// require_once('some-function.php');
function someFunction($param)
{
// do some stuff
return $someScalarValue;
}
. . . now becomes this. (Typed out on the fly and may contain deficiencies, concept only)
// require_once('some-function.php');
require_once('path/to/SomeFunctionClass.php');
function someFunction($param)
{
$cls = new SomeFunctionClass($param);
return $cls->execute();
}
. . . where execute() contains identical code that was in someFunction(). I can now use "SomeFunctionClass" for a DI. There is more to the story, but that is the gist, and this one change can be implemented without modifying any of the 450 or so instances that use this global function (and each of those they can be gradually ported to use the new wrapper.) It also allows me to isolate and mock the functionality for unit testing.
I need an idea to create anonymous class on PHP. I don't know how I can works.
See my limitations:
On PHP you can't make anonymous class, like anonymous function (like class {});
On PHP you don't have class scope (except in namespaces, but it have the same problem below);
On PHP you can't use variables to specify the class name (like class $name {});
I don't have access to install the runkit PECL.
What I need, and why:
Well, I need create a function called ie create_class() that receives a key name and a anonymous class. It'll be useful for me because I want use different name class symbols that PHP can't accept. For instance:
<?php
create_class('it.is.an.example', function() {
return class { ... }
});
$obj = create_object('it.is.an.example');
?>
So, I need an idea that accept this use. I need it because on my framework I have this path: /modules/site/_login/models/path/to/model.php. So, the model.php need to declare a new class called site.login/path.to.model.
On call create_object() if the internal cache have a $class definition (like it.is.an.example it simply return the new class object. If not, need load. So I will use the $class content to search fastly what is the class file.
In PHP 7.0 there will be anonymous classes. I don't fully understand your question, but your create_class() function might look like this:
function create_class(string $key, array &$repository) {
$obj = new class($key) {
private $key;
function __construct($key) {
$this->key = $key;
}
};
$repository[$key] = $obj;
return $obj;
}
This will instantiate an object with an anonymous class type and register it into the $repository. To get an object out you use the key you created it with: $repository['it.is.an.example'].
You can create a dummy class using stdClass
$the_obj = new stdClass();
So basically you want to implement a factory pattern.
Class Factory() {
static $cache = array();
public static getClass($class, Array $params = null) {
// Need to include the inc or php file in order to create the class
if (array_key_exists($class, self::$cache) {
throw new Exception("Class already exists");
}
self::$cache[$class] = $class;
return new $class($params);
}
}
public youClass1() {
public __construct(Array $params = null) {
...
}
}
Add a cache within to check for duplicates
If you really need to to that, you could use eval()
$code = "class {$className} { ... }";
eval($code);
$obj = new $className ();
But the gods won't approve this. You will go to hell if you do it.
I'm a bit confused on how constructors work in PHP.
I have a class with a constructor which gets called when I instantiate a new object.
$foo = new Foo($args);
__construct($params) is called in the class Foo and it executes the appropriate initialization code.
However when I use the class to call a static function, the constructor is called again.
$bar = Foo::some_function(); //runs the constructor from Foo
This causes the constructor to execute, running the object initialization code that I intended only for when I create a new Foo object.
Am I missing the point of how constructors work? Or is there a way to prevent __construct() from executing when I use the class to make static function calls?
Should I use a "factory" function instead to do the object initialization? If so, what's the point of the constructor then?
::EDIT::
I have a form where users can upload photos to an album (create_photo.php) and an area where they can view the album (view_photos.php). Upon form submit:
$photo = new Photo($_FILES['photo'], $_POST['arg1'], ect..);
The Photo constructor creates and saves the photo. However in view_photo.php, when I call:
$photo = Photo::find_by_id($_POST['id']) //user-defined function to query database
This is causing Photo's constructor to run!
I see nothing that replicates your question.
See Demo: http://codepad.org/h2TMPYUV
Code:
class Foo {
function __construct(){
echo 'hi!';
}
static function bar(){
return 'there';
}
}
echo Foo::bar(); //output: "there"
Assumption
PHP 5.x
Different goals, different path
create a new instance of a class (object)
class myClassA
{
public $lv;
public function __construct($par)
{
echo "Inside the constructor\n";
$this->lv = $par;
}
}
$a = new myClassA(11);
$b = new myClassA(63);
because we create a new object PHP calls:
__construct($par);
of the new object, so:
$a->lv == 11
$b->lv == 63
use a function of a class
class myClassB
{
public static $sv;
public static function psf($par)
{
self::$sv = $par;
}
}
myClassB::psf("Hello!");
$rf = &myClassB::$sv;
myClassB::psf("Hi.");
now $rf == "Hi."
function or variabiles must defined static to be accessed by ::, no object is created calling "psf", the "class variable" sv has only 1 instance inside the class.
use a singleton created by a Factory (myClassA is above)
class myClassC
{
private static $singleton;
public static function getInstance($par){
if(is_null(self::$singleton)){
self::$singleton = new myClassA($par);
}
return self::$singleton;
}
}
$g = myClassC::getInstance("gino");
echo "got G\n";
$p = myClassC::getInstance("pino");
echo "got P\n";
Using the factory (getInstance) the first time we construct a new object having $par set to gino.
Using the factory the second time $singleton has already a value that we return. No new object is created (no __construct is called, less memory & cpu is used).
The value of course is an object instanceOf myClassA and don't forget:
myClassC::$singleton->lv == "gino"
Pay attention to singletons:
What is so bad about singletons?
http://www.youtube.com/watch?v=-FRm3VPhseI
By my answer I don't want promote/demote singleton. Simply from the words in the question, I made this calc:
"static"+"__construct"="singleton"!
Here is my workaround:
I put method construct() in static class. Notice, it is different than __construct() which I use in regular classes.
Each class is in own file, so I lazy load that file on first use of class. This gives me event of first use of class.
spl_autoload_register(function($class) {
include_once './' . $class . '.php';
if (method_exists($class, 'construct')) {
$class::construct();
}
});
I define class properties as array in a static method and call them via the method. I'm not sure if it's the best solution or not but works great.
Example:
class Foo
{
private static construct_method()
{
return [
'one' => 1,
'two' => 2
];
}
public static any_method()
{
return self::construct_method()['one'] + self::construct_method()['two'];
}
}
echo Foo::any_method(); // 3
I want to create an instance of a class and call a method on that instance, in a single line of code.
PHP won't allow calling a method on a regular constructor:
new Foo()->set_sth(); // Outputs an error.
So I'm using, if I can call it that, a static constructor:
Foo::construct()->set_sth();
Here's my question:
Is using static constructors like that considered a good practice and if yes, how would you recommend naming the methods for these static constructors?
I've been hesitating over the following options:
Foo::construct();
Foo::create();
Foo::factory()
Foo::Foo();
constructor::Foo();
Static constructors (or "named constructors") are only beneficial to prove an intention, as #koen says.
Since 5.4 though, someting called "dereferencing" appeared, which permits you to inline class instantiation directly with a method call.
(new MyClass($arg1))->doSomething(); // works with newer versions of php
So, static constructors are only useful if you have multiple ways to instantiate your objects.
If you have only one (always the same type of arguments and number of args), there is no need for static constructors.
But if you have multiple ways of instantiations, then static constructors are very useful, as it avoids to pollute your main constructor with useless argument checking, weakening languages constraints.
Example:
<?php
class Duration
{
private $start;
private $end;
// or public depending if you still want to allow direct instantiation
private function __construct($startTimeStamp = null, $endTimestamp = null)
{
$this->start = $startTimestamp;
$this->end = $endTimestamp;
}
public static function fromDateTime(\DateTime $start, \DateTime $end)
{
return new self($start->format('U'), $end->format('U'));
}
public static function oneDayStartingToday()
{
$day = new self;
$day->start = time();
$day->end = (new \DateTimeImmutable)->modify('+1 day')->format('U');
return $day;
}
}
As you can see in oneDayStartingToday, the static method can access private fields of the instance! Crazy isn't it ? :)
For a better explanation, see http://verraes.net/2014/06/named-constructors-in-php/
The naming of any method should be with intention revealing names. I can't tell what 'Foo::factory' does. Try to build to a higher level language:
User::with100StartingPoints();
This would be the same as:
$user = new User();
$user->setPointsTo(100);
You could also easily test whether User::with100StartingPoints() is equal to this.
If you don't need a reference to the newly constructed Foo, why don't you simply make set_sth a static function (and have it create a new Foo internally if required)?
If you do need to get hold of the reference, how would you do it? return $this in set_sth? But then set_sth can be made into a factory function anyway.
The only situation I can think of is if you want to call chainable methods (like in a fluent interface) on a newly constructed instance all in one expression. Is that what you are trying to do?
Anyway, you can use a general-purpose factory function for all types of objects, e.g.
function create_new($type) {
return new $type;
}
create_new('Foo')->set_sth();
It's probably not quite a best practice, but you could use the fact that functions and classes have two different namespaces : you can have a function that have the same name as a class.
This allows one to write this kind of code, for example :
function MyClass() {
return new MyClass();
}
class MyClass {
public function __construct() {
$this->a = "plop";
}
public function test() {
echo $this->a;
}
protected $a;
}
Note that I have defined a function called MyClass, and a class with the same name.
Then, you can write this :
MyClass()->test();
Which will work perfectly, and not get you any error -- here, you'll get the following output :
plop
Addition to Jon's answer: To allow constructor arguments use the following:
function create($type) {
$args = func_get_args();
$reflect = new ReflectionClass(array_shift($args));
return $reflect->newInstanceArgs($args);
}
create('Foo', 'some', 'args')->bar();
Documentation: ReflectionClass->newInstanceArgs
These are called creation methods, and I typically name them createXXX() such as createById() or createEmptyCatalog(). Not only do they provide a nice way to reveal the different intentions of an object's constructors, but they enable immediate method chaining in a fluent interface.
echo Html_Img::createStatic('/images/missing-image.jpg')
->setSize(60, 90)
->setTitle('No image for this article')
->setClass('article-thumbnail');
Propel uses a static method "create". I'd go with that. This method makes the code easier to test rather than just using static methods to perform business logic.
<?php
class MyClass
{
public static function create()
{
return new MyClass();
}
public function myMethod()
{
}
}
Besides, you can also pass parameters to the constructor. For instance:
<?php
class MyClass
{
public function __construct($param1, $param2)
{
//initialization using params
}
public static function create($param1, $param2)
{
return new MyClass($param1, $param2); // return new self($param1, $param2); alternative ;)
}
public function myMethod()
{
}
}
In either case, you'd be able to invoke myMethod right after the create method
<?php
MyClass::create()->myMethod();
// or
MyClass::create($param1, $param2)->myMethod();
A bit late to the party but I think this might help.
class MyClass
{
function __construct() {
// constructor initializations here
}
public static myMethod($set = null) {
// if myclass is not instantiated
if (is_null($set)) {
// return new instance
$d = new MyClass();
return $d->Up('s');
} else {
// myclass is instantiated
// my method code goes here
}
}
}
this can then be used as
$result = MyClass::myMethod();
optional parameters can be passed through either the __constructor or myMethod.
This is my first post and I hope I got the gimmicks right
Say you have two classes, A and B. Is it possible to instantiate both classes once and then let class B call methods in class A, and vice versa?
It can be done using double colon (::) ... ... but then the method becomes static - is that a disadvantage? (see example below)
Can it be done in other ways? With interfaces?
This code shows what I try to do:
class A {
function horse() {
echo "horse";
}
}
class B {
function jump() {
// $A = new A; ... don't want to add this in each method.
$A->horse(); // Fails - $A is out of scope ($A = new A;).
// A::horse(); // Old code style - works.
// $this->horse(); // Works if you extend A - not self-documenting.
// $this->A->horse(); // Fails - out of scope.
}
}
$A = new A;
$B = new B; // Better to use "$B = new B($A);" ?
$B->jump(); // fails - the horse is sleeping.
Edit
Well, I am building a MVC-framework and I want to re-use code from other classes.
Some real-world examples:
a database object that is being passed across classes.
a "url" class that creates/manipulates URLs - used by other classes.
... and a code example:
class url {
function anchor($url,$name) {
return "{$name}";
}
}
class someclass {
function text($str,$url) {
return "{$str}. " . $url->anchor($url,"Read more...");
}
}
I think what you are asking for is multiple inheritance where you could extend both A and B like this
<?php
class C extends A,B {
//...
}
This however is not possible in PHP for good reasons(it actually is creating more problems than it's trying to solve).
Now you might ask yourself if there is any alternative to multiple inheritance and the answer is: Yes, there is! Have a look at the strategy pattern(as Benjamin Ortuzar also has pointed out).
UPDATE:
I just read your question a second time and figured that you might be looking for the singleton pattern, which lets you instantiate an instance of an class only once like this:
class A
{
protected static $_instance;
protected function __construct() //prohibit creating instances from outside
{ }
public static function getInstance()
{
if( self::$_instance === NULL ) {
self::$_instance = new self();
}
return self::$_instance;
}
}
$instance = A::getInstance();
Now A::getInstance() always returns the same instance of A which you can use in B and you can have both the advantages of dynamic functions and the accessibility of static functions.
UPDATE2:
Your database belongs into a registry if you can have more than one db-connection. If you're absolutely certain that you will always need only one db-connection you could as well make it a singleton.
For the URL helper I'd suggest writing a static class if you can and if you really need it to be dynamic make it a singleton, as mentioned before.
I think that this should work:
$B = new B();
$B->jump();
But you should read/refer to http://www.php.net/manual/en/language.oop5.php
Of course you should import the class if you're accessing it from a different php file. And if you're in the object you're calling the method of you should use
$this->jump();
I would suggest reading about the factory and strategy pattern. You can read more about this from chapter one of this fantastic book. link text
I would recomend you reading the whole book.
Maybe (just guessing) you're looking for something like aggregation in COM:
Aggregation is the object reuse mechanism in which the outer object exposes interfaces from the inner object as if they were implemented on the outer object itself.
You can build something like that with the "magic method" __call. Each time a method is called that isn't callable in the object's context this method is invoked and your code can decide what to do with this call. E.g. it can test if another object that is stored as a property of the "outer" object exposes a method with that name and than call that inner object's method.
class Foo {
protected $inner = null;
public function __construct($inner=null) {
if ( is_null($inner) && !is_object($inner) ) {
throw new Exception('...');
}
$this->inner = $inner;
}
public function __call($name, $arguments) {
// also check http://uk.php.net/is_callable
if ( !is_null($this->inner) && method_exists($this->inner, $name) ) {
return call_user_func_array( array($this->inner, $name), $arguments);
}
else {
// add some error handler here
throw new Exception('...');
}
}
function jump() {
$this->horse();
echo " jumps";
}
}
class Bar {
function horse() {
echo "horse";
}
}
$foo = new Foo(new Bar);
$foo->jump();
This works. But I'd recommend something like that only for quite specific circumstances. The most obvious reason beeing that it's hard to tell from the outside what this object $foo really can and cannot do.