Possible approaches to have a "namespaced variable" in PHP 8 - php

I want to know if there is a way to namespace values, in a similar way that we namespace functions in PHP.
You can have:
namespace pizza\land;
function turn_oven_on(){}
And you can access that function with pizza\land\hello()
I wonder if there is a way to do something similar for values.
This is not correct, I am just illustrating what I mean:
namespace pizza\land;
namespaced $ingredients = array('pepperoni', 'garlic');
Then access it with $pizza\land\ingredients.
Other parts in the same runtime can do:
namespace pasta\land;
namespaced $ingredients = array('tomato', 'mozzarella');
Then access it with $pasta\land\ingredients.
Of course that doesn't work, but it serves as an example of what I mean.
I know there is the obvious way, which would be to use the Singleton pattern where the constructor sets the value of a public property for the singleton instance (the one and only one instance of the class).
I dislike this setup, and in that case I prefer to go the killer route and just do global $pseudonamespaced_pizza_land_ingredients.
I wonder, is there anything else I can do to achieve this setup using the latest version of PHP (now 8.1)?
Why?
To have the same effect you have with global but at the same time avoid collision.
Well, let's say I am working with some procedural code and I need a value that can be accessed across multiple functions.
So I want to use that value within the realms of that bunch of functions.
I do not want to wrap all those functions into one Class and then use a property for that class, because in that case I just prefer the Singleton or the global.
Also, if not possible. Why not?
I cannot believe that this hasn't been mentioned before as something to consider for integration into PHP. So, there must be a reason for this not being possible, if it isn't. It would be a cool solution for all those codebases that are mostly procedural and use global way too often... ehem... WordPress...

I think this could be a good answer for this question as the goal is to have variable live inside of the namespace, and that OP has overcomplicated the question for no reason.
Assuming that you have a variable named $number in the global scope of a PHP script. Inside a function, we have another variable with the same name $number, and we assign and change values of it within the function. But, the global variable remains unchanged. This is variable scope. In the same way, classes can be namespaced to give it scope.
Consider having a following code:
<?php
namespace Math;
function add($a, $b) {
return $a + $b;
}
const PI = 3.14;
class Geometry {
static function getCircleArea($radius) {
return PI * $radius ** 2;
}
}
First, we declare the namespace. (So, all the classes, interfaces, constants and function below it will be items of that namespace)
Then, we declared a normal function.
Then, a class constant.
Then, a class.
Now let's access to theseMath namespace's items from another file(functions, constants, and classes).
<?php
// includes the Math.php file
// It's like you had all the code of Math.php written here
include_once 'Math.php';
echo Math\add(2,3); // 5
echo Math\PI; // 3.14
echo Math\Geometry::getCircleArea(10); // 314.15

Thanks to #shingo's comment under the question, this is how I now learned that this can be achieved.
// Namespace
namespace whatever;
// Class with static property
class StaticStuff {
static string $variable = 'Hey';
}
// Access it
echo StaticStuff::$variable; // Hey
// Edit it
StaticStuff::$variable = 'Miau!';
// Access it again
echo StaticStuff::$variable; // Miau!
Specifically:
Define a class
With a static property
Inside a namespace

Related

PHP callback: Is there an equivalent for ::class for a method of a class?

In PHP it is possible to get a full class name via class name resolution like this:
Example:
namespace Name\Space;
class ClassName {}
echo ClassName::class;
Output: Name\Space\ClassName
This is better than using the string Name\Space\ClassName directly in the code because code introspection especially in IDEs can find an error directly.
I wonder if there is something similar for methods of a class - this would be specifically useful for callback functions.
This is how you can basically can pass a callback:
$a = function($callback,$arg) { return $callback($arg); }
$a('getInfo',5);
Instead of passing a string here (which might change), I would prefer to do something like this:
$a(MyClass::class::getInfo,5);
With I "go to declaration" click in the IDE I could go directly to getInfo plus I see errors in case with method does not exist anymore. Is there a way to achieve what I want to do here?
In fact, you work with callable type. And PHP allows setting method/function name only as a string. But if you use classes and objects you will have a different way to set callback. For example:
$a = function($callback, $arg) {
return call_user_func($callback, $arg));
}
// call a static method of the class with
// using fullname space and method name as a string
$a('Name\Space\MyClass::getInfo',5);
// call a static method of the class
// with using ::class
$a([MyClass::class, 'getInfo'], 5);
// call a method of an object
$myObject = new MyClass();
$a([$myOject, 'getInfo'], 5);
Three possibilities.
(1)
echo `__CLASS__`;
...returns namespace\classname as a string.
(2)
If you're trying to get the namespace\classname from another class, i.e., not the one where you're currently executing code, then I would suggest setting a public property inside each class such as:
public static $classname = __CLASS__;
which you could then access from anywhere as:
ClassName::$classname
Put it in each of your classes. Always use the same property name.
(3)
Have you considered the PHP function debug_backtrace() which returns a call stack with the most recent call at index = 0;
So, if:
$caller = debug_backtrace();
Then, $caller[0]['class'] contains the fully qualified class name, including any namespace, at the point where you called debug_backtrace().
I'm guessing that #2 is the solution that will work for you.
Just thought of a 4th possibility that doesn't depend on you adding any code to each class. Might add some overhead though, but so does my 3rd solution above.
(4)
$declared_classes = get_declared_classes();
This lists all of the classes currently declared within the PHP scope as fully qualified namespace\classname. You could search the returned array for partial string matches within the array and return the whole namespace\classname string.
One thing to keep in mind. You might have duplicates if different namespaces have same-named classes.
I've added this as a comment somewhere else but figured it might warrant an actual answer to this question. If you use:
$callback = [MyClass::class, 'myMethod'];
Then at least one IDE (PhpStorm) will recognize this as the callable that it is, allow you to navigate to it, mention it in "show usages" and automatically change it when it is renamed through a refactor. I use this in my code if, for instance, I reference a method in a test:
$this->mock(MyClass::class, function(MockInterface $mock) {
$mock->shouldReceive([MyClass:class, 'myMethod'][1])->andReturn(10);
});
Not the cleanest syntax, but it's workable.

defining class variables in method?

Every example I've seen for defining a variable in a class, does so outside of any methods, for example:
class Testclass
{
public $testvar = "default value";
function dosomething()
{
echo $this->testvar;
}
}
$Testclass = new Testclass();
$Testclass->testvar = "another value";
$Testclass->dosomething();
How would you go about defining a variable inside a method, and making that definition available to any other method inside that class?
Note that I would only want to define the variable in one function, not have a different definition for each function.
I think you should read up on good object oriented practices. I mean, why do you want to make a variable available "inside a method"?
Variable's created within methods are local to that specific method and as such, scope is restricted to it.
You should instead use a instance member/variable which is available object wide if your trying to access a variable between methods. Or possibly you could pass the variable by ref between methods. Of course if its a value which never changes then it should be static variable on the class (class member).
I suggest having a read of the the OO tutorial on tutsplus. Tutsplus are generally great quality. http://code.tutsplus.com/tutorials/object-oriented-php-for-beginners--net-12762
Alternatively, you could do the OO python course (intro to computer science) on Udacity - its also very high quality. Don't worry that its Python, specific language and syntax is irrelevant when trying to understand core OO concepts. https://www.udacity.com/course/cs101
Also, this is a common topic so have a search around, ie Passing Variables between methods?
I hope that helps
Edit: to address your comment. something like this:
class Testclass
{
private $csvResult = []; // instance member array to store csv results
function dosomething()
{
$this->$csvResult = fgetcsv($blah);
}
function processResult()
{
foreach ($this->$csvResult as $item) {
var_dump($item)
}
}
}
But again, as Adrian Cid Almaguer mentioned, you really are best to build a solid foundation of OO for yourself instead of just using this example without truly understanding it.
The real name of the variables class is "properties". You may also see them referred to using other terms such as "attributes" or "fields". In OOP (Object Oriented Programming) You can't define a property inside a method (the real name of a class function is method, not function), because this is a attribute of a class, not an attribute
of a method.
The properties define the attributes of a class, and the methods defines the behavior of a class. For example if you have a class named Person, the person have Name and Age, they are your properties, they are the attributes that describe your class, they can't be inside a method that describe a behavior of your class because the properties of your class must be accessed from any method that need it to show his behavior.
You can read some examples in:
http://www.killerphp.com/tutorials/object-oriented-php/

Php global variable range?

update:
the code i put below will be invoked by a form on other webpage. so that's why I didn't made a instance of a obj.
More detail code:
$serverloc='serverURL';
class Aclass{
function push(){
global $serverloc;
echo $serverloc;
funNotinClass();
}
function otherFunction(){
echo $serverloc;
}
}
funNotinClass(){
echo $serverloc;
}
There is a Class contains 2 functiona "push()" and "otherFunction()" and there is independent function "funNotinClass()" and push() calls it. The class is for a web form in other page. When user click submit the form call the class and use the push() function. A weird thing I found is that the global var $serverloc is invisible to push() and funNotinClass()(they don't print out any thing), but otherFuction() which is a function just like puch() inside of the Aclass can just use the $serverloc(I dont even add global in front of it). How strange....anyone know what is the reason caused this?
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
I read many information about the scope of a global var in php.
they all say a global var is defined outside of function or class and you can use it by using global this key word.
So this is my code
$serverloc='serverURL';
class Aclass{
function Afunction(){
global $serverloc;
echo $serverloc;
}
}
but when I run this class it didn't print anything out.
Is that because I did something wrong or global var just doesn't work this way. Since all the example I read before are just access a global var in functions directly not a function in a class
As per DaveRandom's comment - you haven't actually made an instance of an Aclass object.
This works and displays data as expected:
<?php
$serverloc='serverURL';
class Aclass{
global $serverloc;
function Afunction()
{
echo $serverloc;
}
}
$me = new Aclass();
$me->Afunction(); // output: serverURL
?>
Edit: DaveRandom seems to post asnwers as comments. Go Vote up some of his other answers, the rep belongs to him not me. I am his ghostwriter tonight.
If it is class globals you are after you could do like
class myClass
{
private $globVar = "myvariable";
function myClass()
{
return $this->globVar;
}
}
but when I run this class it didn't print anything out
You don't run classes, in the sense of executing them. A class is a just a data structure that holds data and functions related (called methods).
As most traditional data structures, you create instances of them (called objects), and then you execute actions on them. One way to execute actions on objects (instances of classes), is to pass a message for it to do something: that is calling a method.
So, in your case you could do:
$obj = new Aclass(); // create an object, instance of Aclass
$obj->Afunction(); // ask it to perform an action (call a method)
Having said that, sometimes you want to create a class only for grouping related functions, that never actually really share data within an object. Often they may share data through a global variable (eg.: $_SERVER, $_GET, etc). That may be the case of your design right there.
Such classes can have its methods executed without never instantiating them, like this:
Aclass::Afunction();
While relying on global variables is usually an indicator of quick'n dirty design, there are cases in which it really is the best trade-off. I'd say that a $serverlocation or $baseurl may very well be one of these cases. :)
See more:
The basics on classes and objects in the PHP manual
About the static keyword

Should I keep variables used only in one class method local or declare them as class properties?

I've been wondering if a class property is instantiated and used only in one class method should it be a class property at all or should it just be a local variable accessible to that class method only?
For example, should I keep a variable only used in one method as a local variable like this:
class myClass
{
public function myMethod()
{
$_myVariableUsedOnlyOnce = "Hello World";
echo $_myVariableUsedOnlyOnce;
}
}
Or should I make the variable a private class property like this:
class myClass
{
private $_myVariableUsedOnlyOnce;
public function myMethod()
{
$this->_myVariableUsedOnlyOnce = "Hello World";
echo $this->_myVariableUsedOnlyOnce;
}
}
Which approach "smells"? What are the benefits to making all method variables class properties other than when I need to print_r() the entire object for debugging purposes?
Thanks
If you need it to have persistence across function calls, a class property would be best so that it moves around as the object does. You also might want to use it for other reasons in future in other functions. However, it does add overhead.
Generally, the class should have some real-world analogue, so if your variable corresponds to something that makes sense e.g. a person class has a $height, then it belongs as a class property. Otherwise, if it's just a part of the internal calculations of a method, then it doesn't really belong attached to the class e.g. a person does not have a $shoelaceIterator or whatever.
I'd argue that a confusing object design would be more of a smell than a potentially small memory overhead (although this depends on how big the variable is).
These local variables are not properties of your object.
They are not defining your object, then they should not be declared as private member.
First I would ask if you really need the variable/property at all if you are only using it once. As for which one "smells", a property is stored in memory for the entire life of the object whereas the variable is only in memory until the method finishes executing.
If you don't need a variable outside the method, it should not be any property of the class. Moreover, accessing local variables is faster.
In a pure design approach I would suggest you to make your choice according to what the attribute/property is supposed to model.
In pure performance terms, having one static attribute is better because memory space won't be allocate with each instance of the class.

How to define constant in class constructor?

Can I define a class constant inside the class constructor function ?
(based on certain conditions)
That goes against the idea of class constants - they should not be dependent on a specific instance. You should use a variable instead.
However, if you insist on doing this, are very adventurous and can install PHP extensions, you can have a look at the runkit extension that allows to modify classes and their constants at runtime. See this doc: http://www.php.net/manual/en/function.runkit-constant-add.php
I don't think you can.
It wouldn't make sense, either - a class constant can be used in a static context, where there is no constructor in the first place.
You'll have to use a variable instead - that's what they're there for.
Try look here:
http://php.net/manual/en/language.oop5.constants.php
http://php.net/manual/en/language.oop5.static.php
Hope this helps.
As far as standard instance constructors go, there is no way to do this, and as others have pointed out, it wouldn't make sense. These constructors are called per created object instance, at the point they are created. There is no guarantee this constructor would get called before some code tried to access the constant. It also doesn't make sense in that the code would get called over and over again each time a new instance was constructed, whereas a const should only get set once.
It would be nice if PHP either offered some kind of static constructor that let you set the value one time for uninitialized constants, or allowed more types of expressions when defining constants. But these are not currently features of PHP. In 2015 an RFC was made that proposed adding static class constructors, but it is, at the time of me writing this answer, still in the draft status, and has not been modified since 2017.
I think the best alternative for now is to not use constants in this kind of scenario, and instead use static methods that return the value you want. This is very simple in that it only uses the PHP language features as is (not requiring any special extensions), these static methods can be called in the standard way, and you don't need to hack the autoloading process to call some kind of initializer function that sets static variables. The method might need to rely on private static variables in order to make sure the same instance is returned every time, if an object instance is being returned. You would need to write the implementation of this method to be constant like in the sense that it will always return the same thing, but takes advantage of being able to do things you can't do with a constant, like return on object instance or rely on complex expressions or function calls. Here is an example:
final class User
{
/** #var DefinitelyPositiveInt|null */ private static $usernameMaxLength;
public static function getUsernameMaxLengthConst(): DefinitelyPositiveInt
{
if ($usernameMaxLength === null) {
$usernameMaxLength = new DefinitelyPositiveInt(40);
}
return $usernameMaxLength;
}
}
$usernameInput.maxLength = User::getUsernameMaxLengthConst();
This is still not a perfect solution because it relies on the programmer to write these in a constant like way when that is desired (always returning the same value). Also, I don't like that the best place to document the fact that it is a const is in the method name, thus making it even longer to call. I also don't like that you now have to call it as a method instead of just accessing a property, which would be syntactically nicer.
This example is essentially an implementation of a singleton, but sometimes the purpose of a singleton is to be a constant rather than just a singleton. What I mean is, you might want the instance to always exist, and it might be an immutable type (none of the properties are public or mutable, only having methods that return new objects/values).
I am sorry to break it to you but it is not possible in vanilla PHP.
I am not very sure about frameworks or extensions but I am sure that it is not possible in vanilla PHP.
I recommend you to use variables instead.
You still can't, but maybe some of these (progressively weirder) ideas (just ideas, not true solutions) will work for you:
(1) You could use a private property, with a public getter method. The property cannot be modified outside the class, such as constants, but unfortunately it is accessed as a method, not as a constant, so the syntax is not the same.
class aClass{
private $const;
function __construct($const){
$this->const=$const;
}
function const(){
return $this->const;
}
}
$var1=new aClass(1);
echo $var1->const(); //Prints 1
(2) If you really want this value to be accessed as constant from outside, you can use define () inside the constructor. Unfortunately it doesn't get tied to the class or object name (as it do when you use const, using for example myClass::myConst). Furthermore, it only works if you create a single instance of the class. The second object you create is going to throw an error for redefining the constant, because is untied.
class otherClass{
function __construct($const){
define('_CONST',$const);
}
function const(){
return _CONST;
}
}
$var2=new otherClass('2');
echo $var2->const(); //Prints 2
echo _CONST; //Prints 2
#$var3=new aClass('3'); //Notice: Constant _CONST already defined
echo _CONST; //Still prints 2!
(3) Perhaps that last problem can be solved by giving variable names to the constants, related to the object to which they belong. This may be a bit weird... but maybe it works for someone.
class onemoreClass{
private $name;
function __construct($const,$name){
$this->name=$name;
$constname=$this->name."_CONST";
define($constname,$const);
}
function const(){
return constant($this->name.'_CONST');
}
}
$name='var4';
$$name=new onemoreClass(4,$name);
echo $var4->const(); //Prints 4
echo var4_CONST; //Prints 4
$name='var5';
$$name=new onemoreClass(5,$name);
echo $var5->const(); //Prints 5
echo var5_CONST; //Prints 5

Categories