say I have :
File BaseFoo.php :
require('MyClass1.php')
class BaseFoo(){
function check(){
//do somme stuff
}
function f1($o){
$c = new MyClass1();
return $c->f1($o);
}
}
File MyClass1.php :
MyClass1(){
function f1(){
???->check() // how to call check() (in initiator BaseFoo class) ?
// do other stuff
}
}
Now question is : in MyClass1, function f1, I want to call check() function which is in initiator Class.
Thank for help !
Because BaseFoo doesn't extend MyClass1, it isn't called a base class. This means that you indeed can't use parent. You need to have an object on which you can call the method.
Depending on what you want, you may need to create an object (or pass one) of class BaseFoo in MyClass1 (local or as a member) or you may make BaseFoo::check() static:
class BaseFoo(){
static function check(){
// Note: you can only access static members here
// Calling non-static methods statically generates an E_STRICT level warning.
}
function f1($o){
$c = new MyClass1();
return $c->f1($o);
}
}
Most likely, however, that's not what you actually want to do. You should ask the question "Who owns what?". Here, BaseFoo owns the MyClass1 object. So you probably want this:
class BaseFoo(){
function check(){
//do somme stuff
}
function f1($o){
$c = new MyClass1();
check();
return $c->f1($o);
}
}
And:
MyClass1(){
function f1(){
// Don't check here, the creator should check
// do other stuff
}
}
You may need to check for different things both in MyClass1 and in BaseFoo though, and you would have 2 separate check methods for that.
you can make function check 'static' so u can call BaseFoo::check()
If you google it you will find your answer, but Check this page
So you can use something like that:
class BaseFoo(){
public static function check(){
//do somme stuff
}
function f1($o){
$c = new MyClass1();
return $c->f1($o);
}
}
class MyClass1(){
function f1(){
BaseFoo::check() // call static function check from BaseFoo
// do other stuff
}
}
Related
In a few different places I call:
$model=NEW MakeCall($form);
I have updated the MakeCall class with several changes that I want to take affect after a given date. I renamed the original class MakeCallOld
How can I leave my calls to:
$model=NEW MakeCall($form);
intact and within MakeCall do this:
class MakeCall
{ ...
public function __construct($form)
{
//Use Legacy MakeCallOld for stuff before 2016-10-01
if ($form['date']<'2016-10-01') {
$object=NEW MakeCallOld($form);
return $object;
}
$this->perform several functions and set variables...
This currently just returns an empty object of class MakeCallOld but it does not appear to run the constructor in MakeCallOld as all properties are empty. I would just like the entire object of MakeCallOld dropped into $model.
What you need is a static factory constructor. This is the way you should be doing it to add initialization logic or switch constructors depending on the argument.
class MakeCall
{
public function __construct($form)
{
$this->form = $form;
}
public function showForm(){
echo $this->form;
}
public static function create($form){
//put logic for picking object or whatever here!
$object = new MakeCall($form);
//Do more initializing if you want here!
return $object;
}
}
$form = "asdasd";
$model= MakeCall::create($form);
$model->showForm();
Constructors don't have a return value, so by saying return $object you are simply ending the control flow there and doing nothing else, never reaching "perform several functions and set variables". Depending on your structure you should consider making MakeCall inherit from MakeCallOld, then you can simply call parent::__construct(); in MakeCall's constructor.
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.
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
I tried these two ways:
(new NewsForm())->getWidgetSchema();
{new NewsForm()}->getWidgetSchema();
With no luck...
PHP does not allow you to do this. Try:
function giveback($class)
{
return $class;
}
giveback(new NewsForm())->getWidgetSchema();
It is a rather weird quirk with the language.
You can't an instanciation and a method call in one instruction... But a way to "cheat" is to create a function that returns an instance of the class you're working with -- and, then, call a method on that function which returns an object :
function my_function() {
return new MyClass();
}
my_function()->myMethod();
And, in this kind of situation, there is a useful trick : names of classes and names of functions don't belong to the same namespace -- which means you can have a class and a function that have the same name : they won't conflict !
So, you can create a function which has the same name as your class, instanciates it, and returns that instance :
class MyClass {
public function myMethod() {
echo 'glop';
}
}
function MyClass() {
return new MyClass();
}
MyClass()->myMethod();
(Yeah, the name of the function is not that pretty, in this example -- but you see the point ;-) )
If it is a static method you can just do this:
NewsForm::getWidgetSchema();
A better option in my opinion would be to use a factory method:
class factory_demo {
public static function factory()
{
return new self;
}
public function getWidgetSchema()
{ }
}
then
factory_demo::factory()->getWidgetSchema()
Of course, you get all the benefits of the factory pattern as well. Unfortunately this only works if you have access to the code, and are willing to change it.