Here is my source:
class Test {
public static function a() {
$share_var = ClassConfig::getVarA(); // return a hardcoding const 10;
// echo $share_var;
// ...
}
}
public static function b() {
$share_var = ClassConfig::getVarA(); // return a hardcoding const 10;
// echo $share_var;
// ...
}
}
}
So $share_var = ClassConfig::getVarA(); is called twice. So I do something like this:
class Test {
private static $share_var = ClassConfig::getVarA(); // return a hardcoding const 10;
public static function a() {
// echo $share_var;
// ...
}
}
public static function b() {
// echo $share_var;
// ...
}
}
}
But it failed.
How can I do that.
You can define the property as static, but it's no option for you because you can't call a method during class variable definition
class TestA {
private static $share_var_private = 10; // You can do this, but you can't call another method here eg TestB::a();
private static $share_var_private = Config::getA(); // This won't work
public static function a() {
echo self::$share_var_private;
}
}
If you want static methods, then you need something like own initialize method which will initialize the property but it has its disadvantages.
/**
* This is example of what I've described, but it is not so good for usage because you have to call init() method before you can use the class. You could call init method in each class method, but you can imagine it wouldn't be nice.
*/
class TestWithInit {
/**
* When it's defined as static, it can't be defined as private in php
*/
private static $share_var_static; // You can't call another class here eg TestB::a();
public static function init() {
self::$share_var_static = Config::getVarA();
}
public static function a() {
echo self::$share_var_static;
}
public static function b() {
echo self::$share_var_privat; // This would also work ... calling private variable as static (::)
}
}
Better option is probably singleton pattern which is instance of class but just once and is some ways it's quite close to static methods(NOT SAME).
class TestSingleton {
/**
* Singleton instance
*
* #var TestSingleton
*/
private $instance = null;
/**
* My special config value
*/
private $share_var;
/**
* For singleton make construct private
*/
private function __construct() {
// You can now initialize this private variable in constructor
self::$share_var = Config::getVarA();
}
/**
* Returns instance of this class
*
* #return TestSingleton
*/
public static function getInstance() {
if (self::$instance === null) {
self::$instance = new self(); // also new TestSingleton() woudl work
}
// return the instance
return self::$instance;
}
/**
* See this method is not static anymore
*/
public function a() {
echo $this->share_var_static;
}
/**
* See this method is not static anymore
*/
public function b() {
echo $this->share_var_static;
}
}
// Then you would call the method as:
TestSingleton::getInstance()->a();
TestSingleton::getInstance()->b();
// or
$myInstance = TestSingleton::getInstance();
$myInstance->a();
$myInstance->b();
Next option is to use normal non-static methods and object instance, and initialization of the object property in constructor, but I guess you know how.
I assume you wanted something more like static...
You must use self:
class Test {
private static $share_var = 'Something';
public static function a() {
echo self::$share_var;
}
public static function b() {
echo self::$share_var;
}
}
Test::a();
Test::b();
class Test {
private $share_var = ClassConfig::getVarA();
public static function a() {
echo $this->share_var;
}
public static function b() {
echo $this->share_var;
}
}
if you want to learn more about static Keyword, you can click the followed link, it's detail: static keyword
Related
Why does this work:
/* #var $foo ClassName */
$foo->someFunction();
but this one not:
/* #var $this->foo ClassName */
$this->foo->someFunction();
Here's the complete setup:
abstract class Bar
{
$foo = null;
}
class Cool
{
// some function sets $this->foo
public function doSthWithFoo() // does not work
{
/* #var $this->foo ClassName */
$this->foo->someFunction();
}
public function doSthWithFoo2() // works just fine
{
$test = $this->foo
/* #var $test ClassName */
$test->someFunction();
}
}
Another approach would be to define the $foo variable in the new class again:
class Cool
{
/* #var $foo ClassName */
$foo = null;
// ...
}
Of cource the PHP code is executed properly, but the PHPDoc is buggy.
(PhpStorm 2018.2.2)
Thanks in advance!
I cannot answer your question directly as I do not know why that doesn't work but I normally do this to get around the situation
<?php
class foo
{
/** #var SomeClass $foo */
protected $foo;
// the rest of the class
}
And now you should get the proper code completion for $this->foo->availableThings()
I want to try to explain by code below:
class Foo
{
public function myFooFunction()
{
return 'this is foo function';
}
}
class Bar
{
public $foo;
public function __construct(Foo $foo)
{
$this->foo = $foo;
}
public function myBarFoonction()
{
return 'this is bar function';
}
}
$foo = new Foo();
echo $foo->myFooFunction(); //call in Foo object
$bar = new Bar($foo);
echo $bar->myBarFoonction(); // call in Bar object
echo $bar->foo->myFooFunction(); // call in Foo object
if you call $bar->foo - you must call function in that object
I have this issue to solve:
I create two classes where the second is an extends of the first and there I want to
set and get an variable from the first class, but... I can't find the 'right' way to do it
basically this:
class class_one {
protected $value;
private $obj_two;
public function __construct() {
$this->obj_two = new class_two;
}
public function firstFunction() {
$this->obj_two->obj_two_function();
echo $this->value; // returns 'New Value' like set in the class two
}
}
class class_two extends one {
public function obj_two_function() {
"class_one"->value = 'New Value';
}
}
How can I do this?
First class should not initialize the second, unless you're seeking Uroboros! Protected variables can be set by an extended class without any function support. Just go $this->protVariable = "stuff";
But you will need a function that may be protected to set ClassOne's private variable from the second class. Likewise a function must be made in ClassOne to actually retrieve its value.
class ClassOne {
private $privVariable;
protected $protVariable;
/**
*/
function __construct () {
}
/**
* This function is called so that we may set the variable from an extended
* class
*/
protected function setPrivVariable ($privVariable) {
$this->privVariable = $privVariable;
}
}
In the second class you can then call to parent::setPrivVariable() to set the value using the parent function.
class ClassTwo extends \ClassOne {
/**
*/
public function __construct () {
parent::__construct ();
}
/**
* Set the protected variable
*/
function setProtVariable () {
$this->protVariable = "stuff";
}
/**
* see ClassOne::setPrivVariable()
*/
public function setPrivVariable ($privVariable) {
parent::setPrivVariable ( $privVariable );
}
}
I want to have a class that i can use it this way:
Thing::doThis()->doThat()->doImportantThing();
OR
Thing::doThat()->doImportantThing();
OR
Thing::doImportantThing();
But currently i can only use it this way:
$thing = new Thing();
$thing->doThis()->doThat()->doImportantThing();
What do i have to change in the class so i can use it the way i want? I already return a Thing instance in every function call.
I want to use that for a simple reason, imagine a mail class, in the constructor you define a default from and to, but you might want to change it, so you do Mail::setFrom()->send(). If you want to change the to, you use Mail::setTo()->send(). It just makes it easier to use if it's going to be used in different projects by different people.
I want by calling Mail::{something} to have like a constructor call and then run the {something} function.
You can do this
class Thing {
public static function __callStatic($name, $arguments){
$thing = new self;
return $thing->$name($arguments);
}
public function __call($name, $arguments){
return $this->$name($arguments);
}
private function doThis(){
echo 'this'.PHP_EOL;
return $this;
}
private function doThat(){
echo 'that'.PHP_EOL;
return $this;
}
private function doImportantThing(){
echo 'Important'.PHP_EOL;
return $this;
}
}
Thing::doThis()->doThat();
Thing::doThat()->doImportantThing();
It is a really ugly work-around, though. And it disables you to have private methods.
DEMO
One great thing for static methods is that they can work in object context, and can be called like this: $instance->staticMethod()
Here it is (even you get code completion in ide, and works as axpected as you want):
class Mail
{
public static $from;
public static $to;
public static $subject;
public static $message;
protected static $onlyInstance;
protected function __construct ()
{
// disable creation of public instances
}
protected static function getself()
{
if (static::$onlyInstance === null)
{
static::$onlyInstance = new Mail;
}
return static::$onlyInstance;
}
/**
* set from
* #param string $var
* #return \Mail
*/
public static function from($var)
{
static::$from = $var;
return static::getself();
}
/**
* set to
* #param string $var
* #return \Mail
*/
public static function to($var)
{
static::$to = $var;
return static::getself();
}
/**
* set subject
* #param string $var
* #return \Mail
*/
public static function subject($var)
{
static::$subject = $var;
return static::getself();
}
/**
* set message
* #param string $var
* #return \Mail
*/
public static function message($var)
{
static::$message = $var;
return static::getself();
}
public static function send()
{
echo "<pre><b>Hurrah mail sent</b>"
. "\nFrom:\t ".static::$from.""
. "\nTo:\t ".static::$to." "
. "\nSubject: ".static::$subject.""
. "\nMessage: ".static::$message;
echo "</pre>";
}
}
Example usage:
Mail::from('george#garcha')
->to('michel#tome')
->subject('hehe works')
->message('your welcome')
->send();
Output
Hurrah mail sent
From: george#garcha
To: michel#tome
Subject: hehe works
Message: your welcome
Example 2 (this also works):
Mail::from('george#garcha')
->to('michel#tome');
Mail::subject('hehe works')
->message('your welcome')
->send();
Why do I get undefined property Takeover::user2 on function takeover?
I'm not sure what I'm doing wrong. Can someone help?
I can call user2->addsaldo() on main file but I can't call it inside another function. Why?
Class user
class User {
/**
* #AttributeType int
*/
private $iduser;
/**
* #AttributeType float
*/
private $saldo=0;
/**
* #AssociationType Portefolio
* #AssociationKind Composition
*/
public $idportefolio;
public function __construct($iduser){
$this->iduser = $iduser;
}
/**
* #access public
*/
public function getid() {
// Not yet implemented
}
/**
* #access public
*/
public function addsaldo($saldo) {
$this->saldo = $saldo;
}
}
Class takeover
class Takeover {
/**
* #AttributeType int
*/
private $idTakeover;
/**
* #AssociationType root
* #AssociationMultiplicity 1
*/
public $Root;
public $IdeasTakerover=array();
public function __construct($idTakeover){
$this->idTakeover = $idTakeover;
}
/**
* #access public
*/
public function GetIdCompraRoot() {
// Not yet implemented
}
public function AddIdeasTakeover($idTakeover, $idideia) {
$this->idTakeover = $idTakeover;
$this->idideia = $idideia;
array_push($this->IdeasTakerover,$idideia);
}
/**
* #access public
*/
public function Takeover() {
$this->user2->addsaldo(200); //USER2 DOES EXIST
}
}
Creating users and calling them:
$takeover = new Takeover(1);
for ($i=0; $i<$conta; $i++ ){
$takeover->AddIdeasTakeover(1,$idsideias[$i]);
}
$takeover->Takeover();
if ($partial == "user") {
$booleanUser = TRUE;
$iduser=substr($buffer, 4);
${'user'.$iduser} = new User($iduser);
}
The problem is not in this class. The problem is that $GLOBALS['user2'] is not defined when referenced here: $GLOBALS['user'.$this->IdeiasTakeover[$i]]. You then call addsaldo() on an undefined array element in $GLOBALS.
On another note, it is impossible to write good code using $GLOBALS. Global variables are bad news. You should not be using/referencing global variables. The exception would be at a low level when referencing $_POST, $_GET, etc. Even still, all the good PHP frameworks wrap these in a request object.
Edit
Dependency Injection is a better way for one class to use another:
class X {
$yInstance;
public function __construct($yInstance)
{
$this->yInstance = $yInstance;
}
public function x()
{
//Call your 'y' method on an instance of Y
$this->yInstance->y();
}
}
class Y {
public function y()
{
echo 'Y::y() called!';
}
}
Call X::x()
$y = new Y();
$x = new X($y);
$x->x();
Output:
Y::y() called!
The easiest way to do this is to use a dependency injection container. Here is my favorite one for PHP: http://symfony.com/doc/current/components/dependency_injection/introduction.html
Also, check out Martin Fowlers classic article about IOC:
http://martinfowler.com/articles/injection.html
Good luck!
I have an object created within a method, and I would like to further process it in another method of the same class.
I tried it like this, but $obj is not passed through to method two():
class SomeClass {
public static function one($id)
{
$obj = new self();
$obj->id = $id;
//...
return $obj;
}
public function two()
{
$obj->id = 2;
return $obj;
}
}
$obj = SomeClass::one($id)->two();
Is there a way to achieve this?
I found this thread How to chain method on a newly created object?, but it's still not quite clear whether this is possible or not.
two is a static method. You're trying to invoke it on an instance, and static methods by definition don't work on a specific instance.
Make the method not static, and manipulate $this instead of $obj.
If I'm not misunderstanding what you're trying to do, if you don't make the second method static, you can return an object and it'll be passed in as $this in the chained call;
class SomeClass {
public $id = 0;
public static function one($id)
{
$obj = new self(); // Create and return new object
$obj->id = $id;
return $obj;
}
public function two()
{
$this->id = 3; // The new object is $this here
return $this;
}
}
$obj = SomeClass::one(5)->two();
Method chaining only makes sense when you are using setters.
In combination with PHPDoc most IDE's (like NetBeans) will support code completion/autocomplete feature again.
p.s note that method chaining can give your more chance on errors like PHP Fatal error: Call to a member function .... on a non-object in .... when mixing in more classes with returning
class Example {
protected $var = null;
public function __construct() {
}
public function __destruct() {
unset($this->var); // explicit memory clearing
}
/**
* #return \Example
*/
public static function create() {
return new self();
}
/**
* #return \Example
*/
public static function getInstance() {
return self::create();
}
/**
* #return \Example
*/
public static function newInstance() {
return self::create();
}
/**
*
* #param mixed $var
* #return \Example
*/
public function setThing1($var) {
$this->var = $var;
return $this;
}
/**
*
* #param mixed $var
* #return \Example
*/
public function setThing2($var) {
$this->var = $var;
return $this;
}
}
Example::create()->setThing1(1)->setThing2('2');