How can I using Class::Function(params) without static - php

* Sorry, I am learning English now and my English is still not so good. Please understand my situation.
As far as I know, Static is required to use like Class::Function(params);
Like this one.
class Foo {
static function Bar($msg){
echo $msg;
}
}
There is one file in XE(is CMS developed in Korea).
(XE Official Site : http://www.xpressengine.com/?l=en)
Of course, This is a summary of real file
<?php
/**
* Manages Context such as request arguments/environment variables
* It has dual method structure, easy-to use methods which can be called as self::methodname(),and methods called with static object.
*/
class Context
{
/**
* codes after <body>
* #var string
*/
public $body_header = NULL;
/**
* returns static context object (Singleton). It's to use Context without declaration of an object
*
* #return object Instance
*/
function &getInstance()
{
static $theInstance = null;
if(!$theInstance)
{
$theInstance = new Context();
}
return $theInstance;
}
/**
* Add html code after <body>
*
* #param string $header Add html code after <body>
*/
function addBodyHeader($header)
{
is_a($this, 'Context') ? $self = $this : $self = self::getInstance();
$self->body_header .= "\n" . $header;
}
}
This is the comment at the top of this file.
It has dual method structure, easy-to use methods which can be called
as self::methodname(),and methods called with static object.
In this comment, It can use Class::Function() and I have been using in XE.
But it don't tell how they make. How can I make like it?
Edit1 :
The file's name is Context.class.php and It is included in other files.
<?php
require(_XE_PATH_ . 'classes/context/Context.class.php');
Context::addBodyHeader("Some Codes");
?>

In this comment, It can use Class::Function() and I have been using in
XE. But it don't tell how they make. How can I make like it?
The :: is called the scope resolution operator.
They make it as follows:
class MyClass {
public static function saySomething() {
echo 'hello';
}
public function sayHello() {
echo 'hello';
}
public function helloSay() {
self::sayHello();
}
}
MyClass::saySomething();
MyClass::sayHello();
MyClass::helloSay();
They all output: hello

Well in this case they use self, which doesn't need the static, you can compare self:: to $this->, just that self:: also works for static functions.
Maybe the manual helps you

Not sure if this is what you are trying to do, but you can declare "static" in php public static function methodName() and then call the function with Class::Method() You can also check out this for more data on static.
EDIT:
This is from php.net:
The pseudo-variable $this is available when a method is called from
within an object context. $this is a reference to the calling object
(usually the object to which the method belongs, but possibly another
object, if the method is called statically from the context of a
secondary object).
So basically you can do this (call class method static way).

Related

Non-static method App\Console\Setting::KS() should not be called statically - Laravel

I have made my own class
<?php
namespace App\Çonsole;
use App\KernelSetting;
class Setting
{
/**
* #param $setting
* #return
*/
function KS($setting)
{
return KernelSetting::where('setting', $setting)->first()->value;
}
}
Now I am calling it like this Setting::KS('review_time_limit')
How do I return the value from the database entry I get?
I get this
Non-static method App\Console\Setting::KS() should not be called statically
The error message is pretty clear, you need to make the method static in order to call it like that.
static function KS($setting)
{
return KernelSetting::where('setting', $setting)->first()->value;
}
You can read more about static here :
https://www.php.net/manual/en/language.oop5.static.php

Accessing outer variable in PHP 7 anonymous class

PHP 7 added support for anonymous classes, however I can't seem to find any information regarding associated scoping issues. I know I can use the use keyword with callables/closures to access outer scoped variables (like function() use ($outer) { // do work with $outer }), is there any way to do that with an anonymous class?
I would like to be able to do so without relying on the anonymous class constructor arguments, and without doing things like adding a setter method or public property to store the value after the instantiation.
Here's an example:
$outer = 'something';
$instance = new class {
public function testing() {
var_dump($outer); // would like this to dump the string 'something'
}
};
another solution could be
$outer = 'something';
$instance = new class($outer) {
private $outer;
public function __construct($outer) {
$this->outer = $outer
}
public function testing() {
var_dump($this->outer);
}
};
The unique way to access outside variable in this case is use $ _GLOBAL (I don't recommend). If you do not want to use constructor or setter method, my suggestion is to use a STATIC variable inside the anonymous class and set the value after the attribuition to the variable that contains the instance of anonymous class (Its not possible to define the static value before, because the class is anonymous..). Doing this, you have a better control and a static variable, but in certain way this is not very usual, every time when you create a new anonymous class the instance and it values belongs to the VARIABLE that receives the "new object", maybe is better for you to create a real class.. But follow a example with a static value and a anonymous class:
$i = new class {
public static $foo;
};
var_dump($i::$foo); //No value
$i::$foo = "Some value";
var_dump($i::$foo); //Has value
http://php.net/manual/en/language.variables.scope.php
There are some instructions in the php variable scope documentation.
This script will not produce any output because the echo statement refers to a local version of the $a variable, and it has not been assigned a value within this scope. You may notice that this is a little bit different from the C language in that global variables in C are automatically available to functions unless specifically overridden by a local definition. This can cause some problems in that people may inadvertently change a global variable. In PHP global variables must be declared global inside a function if they are going to be used in that function.
In php, the scope that a method inside a class can access is restricted to the inside of the entire class and cannot be accessed up to other scopes. So I think that the effect you want is not implemented in php, at least until the PHP GROUP decides to change the default behavior of PHP.
Of course, you can still use it by declaring variables as global.
Even though the OP did state that they would like to avoid public properties and anonymous class constructor arguments, the accepted answer is exactly that, so here is an example using a public property, which can be improved with a private property and a setter to maintain encapsulation:
class Foo {
public function executionMethod() {
return "Internal Logic";
}
}
$foo = new Foo();
var_dump("Foo's execution method returns: " . $foo->executionMethod());
$bar = new class extends Foo {
public $barVal;
public function executionMethod() {
return $this->barVal;
}
};
$bar->barVal = "External Logic";
var_dump("Bar's execution method returns: " . $bar->executionMethod());
I find this useful if you are unable to override the inherited class's constructor.
This will output:
string(46) "Foo's execution method returns: Internal Logic"
string(46) "Bar's execution method returns: External Logic"
If you want your anonymous class to have access to outer properties and methods that are protected or private, you could take advantage of the fact that closures inherit the scope they're defined in, and tie them into some magic methods for seamless behavior.
This is untested, but I'm pretty sure it'd work:
$class = new class {
/**
* #var \Closure
*/
public static $outerScopeCall;
/**
* #var \Closure
*/
public static $outerScopeGet;
/**
* #param string $name
* #param array $arguments
* #return mixed
*/
public function __call(string $name, array $arguments = [])
{
$closure = static::$outerScopeCall;
return $closure($name, $arguments);
}
/**
* #param string $name
* #param array $arguments
* #return mixed
*/
public function __get(string $name)
{
$closure = static::$outerScopeGet;
return $closure($name);
}
};
$class::$outerScopeCall = function (string $name, array $arguments = []) {
return $this->$name(...$arguments);
};
$class::$outerScopeGet = function (string $name) {
return $this->$name;
};
The $call closure will have access to the definition of $this from where it's defined as opposed to where

Laravel phpunit static assert methods calls [duplicate]

I don't want to write a long text, because it is a short question. PHPUnit tests contain several methods that are static. For example all those \PHPUnit\Framework\Assert::assert*() methods and also the identicalTo, equalTo.
My IDE (with IntelliSense/autocompletion) doesn't accept calls with $this, but with self. I have learned that static functions should be called through the class, not an object, so self.
What is more correct?
$this->assertTrue('test');
or
self::assertTrue('test');
?
(And if "$this" is more correct, can you maybe point out why we should not use "self"?)
Generally, self is only used to refer to static methods and properties (though confusingly you can refer to non-static methods with self, and to static methods with $this, provided the methods called with self don't reference $this.)
<?php
class Test {
public static function staticFunc() {echo "static ";}
public function nonStaticFunc() {echo "non-static\n";}
public function selfCaller() {self::staticFunc(); self::nonStaticFunc();}
public function thisCaller() {$this->staticFunc(); $this->nonStaticFunc();}
}
$t = new Test;
$t->selfCaller(); // returns "static non-static"
$t->thisCaller(); // also returns "static non-static"
Inheritance is important to remember when dealing with $this or self. $this will always refer to the current object, while self refers to the class in which self was used. Modern PHP also includes late static binding via the static keyword, which will operates the same way as (and should be preferred over) $this for static functions.
<?php
class Person {
public static function whatAmI() {return "Human";}
public function saySelf() {printf("I am %s\n", self::whatAmI());}
public function sayThis() {printf("I am %s\n", $this->whatAmI());}
public function sayStatic() {printf("I am %s\n", static::whatAmI());}
}
class Male extends Person {
public static function whatAmI() {return "Male";}
}
$p = new Male;
$p->saySelf(); // returns "I am Human"
$p->sayThis(); // returns "I am Male"
$p->sayStatic(); // returns "I am Male"
As regards PHPUnit in particular, it appears they simply do things the way they've always done them! Though according to their documentation, your code should work fine using static methods.
The phpunit documentation says you can use either and doesnt advocate one over the other. So you choose!
https://phpunit.readthedocs.io/en/9.2/assertions.html
PHPUnit 4.8.9: vendor/phpunit/phpunit/src/Framework/Assert.php:
/**
* Asserts that a condition is true.
*
* #param bool $condition
* #param string $message
*
* #throws PHPUnit_Framework_AssertionFailedError
*/
public static function assertTrue($condition, $message = '')
{
self::assertThat($condition, self::isTrue(), $message);
}
Technically static::assertTrue() is correct, but the common usage of the assert methods is $this->assertTrue().

PHPUnit - Use $this or self for static methods?

I don't want to write a long text, because it is a short question. PHPUnit tests contain several methods that are static. For example all those \PHPUnit\Framework\Assert::assert*() methods and also the identicalTo, equalTo.
My IDE (with IntelliSense/autocompletion) doesn't accept calls with $this, but with self. I have learned that static functions should be called through the class, not an object, so self.
What is more correct?
$this->assertTrue('test');
or
self::assertTrue('test');
?
(And if "$this" is more correct, can you maybe point out why we should not use "self"?)
Generally, self is only used to refer to static methods and properties (though confusingly you can refer to non-static methods with self, and to static methods with $this, provided the methods called with self don't reference $this.)
<?php
class Test {
public static function staticFunc() {echo "static ";}
public function nonStaticFunc() {echo "non-static\n";}
public function selfCaller() {self::staticFunc(); self::nonStaticFunc();}
public function thisCaller() {$this->staticFunc(); $this->nonStaticFunc();}
}
$t = new Test;
$t->selfCaller(); // returns "static non-static"
$t->thisCaller(); // also returns "static non-static"
Inheritance is important to remember when dealing with $this or self. $this will always refer to the current object, while self refers to the class in which self was used. Modern PHP also includes late static binding via the static keyword, which will operates the same way as (and should be preferred over) $this for static functions.
<?php
class Person {
public static function whatAmI() {return "Human";}
public function saySelf() {printf("I am %s\n", self::whatAmI());}
public function sayThis() {printf("I am %s\n", $this->whatAmI());}
public function sayStatic() {printf("I am %s\n", static::whatAmI());}
}
class Male extends Person {
public static function whatAmI() {return "Male";}
}
$p = new Male;
$p->saySelf(); // returns "I am Human"
$p->sayThis(); // returns "I am Male"
$p->sayStatic(); // returns "I am Male"
As regards PHPUnit in particular, it appears they simply do things the way they've always done them! Though according to their documentation, your code should work fine using static methods.
The phpunit documentation says you can use either and doesnt advocate one over the other. So you choose!
https://phpunit.readthedocs.io/en/9.2/assertions.html
PHPUnit 4.8.9: vendor/phpunit/phpunit/src/Framework/Assert.php:
/**
* Asserts that a condition is true.
*
* #param bool $condition
* #param string $message
*
* #throws PHPUnit_Framework_AssertionFailedError
*/
public static function assertTrue($condition, $message = '')
{
self::assertThat($condition, self::isTrue(), $message);
}
Technically static::assertTrue() is correct, but the common usage of the assert methods is $this->assertTrue().

php file having wrapper class instead of arguments in file's functions

I've the following files:
`index.php`
`settings.php`
`functions.php`
settings.php:
....
$object = new SomePhpClass();
....
index.php:
require_once('settings.php');
require_once('functions.php');
....
some_function($object);
some_other_function($object);
....
functions.php:
function some_function(SomePhpClass $object){
//Do something with $object
}
function some_other_function(SomePhpClass $object){
//Do some here
}
In my above code, I've passed the $object in the function. The above code works as of now. I want the functions.php to accept a wrapper class to SomePhpClass instead of directly passing the $object. I'm a newbie here and don't know how to go about writing the wrapper class to achieve such thing.
Wrapper classes can be used for a lot of different reasons. Most of the time you use them to either hide the functionality of existing classes of yours so that the consumer only sees a limited interface (facade) or you can also use them to augment the functionality of an existing class or its method (decorator). Sometimes they are used as an adapter between different interfaces.
The basic idea of a wrapper class is that you define a class which contains the object you are wrapping (usually as private property) and defines the methods you want to make accessible. If your intention is to hide certain methods of your original object, the methods on your wrapper class will be a subset of your wrapped object's methods and will simply forward the call to the wrapped object and return whatever it returned. If you want to extend the object's functionality, you can also define new methods on your wrapper which do whatever magic you want them to do on your object.
A typical implementation could look something like this:
class SomePhpWrapper {
/**
* The wrapped object
*/
private $wrapped;
/**
* Wrapping constructor
*/
public function __construct(SomePhpClass $object) {
$this->wrapped = $object;
}
/**
* A method of the wrapped object we would like to explose on the wrapper
*/
public function someMethod($someArgument) {
return $this->wrapped->someMethod($someArgument);
}
/**
* A decorated method which calls the wrapper class's method but also does something else
*/
public function query($params) {
$returnValue = $this->wrapper->query($params);
doSomethingFunky();
return $returnValue;
}
/**
* Another exposed method
*/
public function ping() {
return $this->wrapped->ping()
}
/**
* A decorator method that does not exist on the wrapped object but would be useful
*/
public function somethingComplicated() {
$this->wrapped->query(this);
$this->wrapped->query(that);
}
}
This wrapper hides some methods of your original class and also add a new method called somethingComplicated().
This wrapper, however, is not a subclass of your original class. When you write functions that use this wrapper class, they should not expect SomePhpClass, they should expect SomePhpWrapper instead. In your case:
function some_function(SomePhpWrapper $object) {
$object->ping(); // works
$object->somethingComplicated(); // works
$object->getDebug(); //fails, as getDebug() is not exposed by the wrapper
}
To use this wrapper you could go like this:
$object = new SomePhpClass();
$wrapper = new SomePhpWrapper($object);
some_function($wrapper);

Categories