Is it possible to get the variable name used to reference an instantiated class from within the class? here's an example of what i mean:
class Test {
function getName(){
//some code here to get the name '$test1' in this example
}
}
$test1 = new Test
It's not a must for this to be possible, but it'd help for a project i'm working on.
You can use the variable $this to reference the object from within itself.
If you want to find the actual name of the variable $test1, it's going to be more difficult (maybe impossible, since the class has no way to know how it is being used in the global scope). But probably not worth it. Most of the time I've seen questions like that asked, people suggest that there's a design flaw and the application should depend on something other than variable names.
You could most likely do it using debug_backtrace(), however this sort of hack is extremely bad practice.
Related
Sometimes I see this in others coding...
$object->Something_1->Something_2;
I understand pointing and object to a function or variable as such...
$object->Something_1;
$object->Something_1();
But I don't understand how the multiple object pointers strung together work. I haven't been able to find anything online to explain this, so maybe my terms searched are wrong, but would somebody explain or point me to an article where I can learn this?
I don't know what is required to implement such usage and would like to, to see if it's something I can benefit from in my coding.
This:
$object->Something_1->Something_2();
is pretty much the same as this:
$temp = $object->Something_1;
$temp->Something_2();
All it means is that Something_1 is itself an object which also has members, in this case the method Something_2. There's nothing special about the syntax. Anything which resolves to an object can have its members invoked with ->. So $object resolves to an object, and in this case so does $object->Something_1.
Your original code sample can be rewritten as: $invoice->sender->getName();
In this code the variable $sender has been defined as public (in the class, that was used to instantiate the $invoice object). This means, that the object's encapsulation is broken. The code also expects, that $sender will actually contain an object.
You could improve the encapsulation, by using a getter instead of directly accessing the variable: $invoice->getSender()->getName();
But this approach is also considered to be a code smell. It would also make the debugging quite annoying and often lead to violations of Law of Demeter.
Such chaining is considered to be a bad practice. I would strong recommend avoid it.
The only exception, that is commonly seen, is chaining of setters, when working with domain entities. In this case, it would be quite common to see code like this:
$invoice
->setSender('John Doe')
->setReceivedOn(time())
->setOrder($data);
To achieve it, the methods would be defined kinda like this:
public function setSender($sender) {
$this->sender = $sender;
return $this;
}
This particular usecase is not as bad as others, since the class is not actually changing between -> chain's links (which is what make the debugging of the first two examples into a nightmare). But I personally would still avoid this approach, since setters should not return anything and getters should not change state of an object.
TL;DR: don't adopt this style of code.
Basically, this happens when one object, stores one or more other objects as properties.
For example:
class Car
{
public string $name;
public Engine $engine;
}
class Engine
{
public $someProp;
}
if you have a car in a variable, you could access the property of the engine like so:
$car->engine->someProp;
(assuming that the car is initialised and so is the engine in the car)
For my latest website I’ve been trying to use classes. Mainly to teach myself more about OOP and learn through experience.
Whenever I needed a ‘variable’ within my class I created a property, for instance:
class someClass
{
var $valueToUseHere; // Only used internally - can I just use a variable?
public function doStuff()
{
$this->valueToUseHere = 60;
// Do more stuff here...
}
}
It is only now when I’ve been looking more into the code and trying to do some optimisation that I’ve noticed that my functions and classes are passing around some large objects. A lot of that bulk could be stripped away if I made all the properties that are only used inside the class into normal variables.
Are properties only used for variables that are needed outside the class and is it then acceptable to just use ‘normal’ variables within the class itself ?
Sorry if this question illustrates a lack of understanding on the subject. Unfortunately, this is where my learning is up to at this point. I’ve done some searching around “class properties vs variables” etc but not found a comprehensive answer to this.
Many thanks
It's somewhat vague what you're asking, but if valueToUseHere is not used outside of doStuff, then don't make it a property!
class someClass {
public function doStuff() {
$valueToUseHere = 60;
// Do more stuff here...
}
}
If there's no reason to share that value with other methods of the class or with the outside world, then there's no reason to clutter up your object with all sorts of properties. Not only may this cause tricky bugs with preserved state, it also forces you to be unnecessarily careful with your variable names across all object methods.
Actually class properties are variables as well. Basically you have three options:
Global variable, available everywhere, but not recommended because all parts of your code may depend on such a varialbe, changes can easily break stuff everywhere.
Class property (Note: you should define a visibility - public/protected/private) these properties are bound to the object instance and should be used for any state that the object needs to keep for further processing. Usually those might be used in more than one metohd of your class.
Variables inside a method like just
public function doStuff()
{
$valueToUseHere = 60;
// Do more stuff here...
}
The variable is just available inside the method and is thrown away at the end of the method execution.
That depends on your needs. If you are going to simply hold a value in a variable it's the best to keep it's simplicity and not define functions for setting or getting it's value. But sometimes you may need to have more controls on a variable in your class. For example you have defined an integer variable and you want it's values to be always between 10 and 1000 and also it should not be in 100,200,300,..,900. So here there is a good reason to set your variable access to private and create a public function to check what is required before setting a new value. Or in another example you may want to call another function or change another depended variable in your class exactly after this variable changed. Or if you want to make a variable read-only or write-only always you can define properties for controlling the variable value.
In brief you may prefer to use:
Properties: When you want to have control about get and set values
Variables: When you want to set or use a variable as its nature
I am having a hard time finding an answer to this, I am sure it's there in front of me but I cant put it together.
//Global Variables
global $GLOBAL;
$GLOBAL['myPluginPath'] = dirname( __FILE__ );
//Main Object
class My_Class {
public function __construct() {
// Initialize Settings
require_once $GLOBAL['myPluginPath'] . '/settings.php';
$My_Settings = new My_Settings();
}
}
I want to use a variable so my code feels more organized, I feel I can read my code better when paths are defined this way and it makes it easier to change the variables so that it applys throughout the whole code if needed.
I can get the variables to work by writing this inside my methods.
public function WhatEverFunc() {
global $GLOBAL
require_once $GLOBAL['myPluginPath'] . '/settings.php';
}
The primary question here, I am wondering if this is bad practice, if not is there a better way then having to define global $GLOBAL inside each method. If however it is bad practice can you show me good practice?
There is a one other thing I am really curious about. Inside the main __construct you see I don't use global $GLOBAL because it works without it, but inside that require_once file is another class which has methods that must use global $GLOBAL inside of them. Hope someone can explain that.
Some are saying this is bad practice, I think. I read there is a singleton pattern(bad practice) and a global pattern. Not sure what I did above constitutes, I am just a little lost from what I should do here with what I am trying to achieve.
An object really should have everything needed for it to perform any function it is designed to. If not, the data should be passed via a param to it.
Part of the whole point of objects versus procedural code is that objects can be re-used over and over and in many places.
Lets use this example of why using Globals and OOP is a bad idea:
Lets say you have a great front-end bit of code, and you write it all through objects. Sometime down the track, you need to create additional reporting on the data in your site. You start to code and realize that you can re-use your classes from the front to achieve almost everything you need - but alas your code contains numerous references to globals that are only visible in the front end if called from a certain script.
That's basically just made your objects rather un-reusable.
Although it's probably not the best practise, but I often write a quick class that grabs a hold of various $GET, $_POST and other variables which might be considered "Globals" such as URL params and the like, then in my code, I either pass this information directly to the objects/functions as needed or indeed pass the entire object (rarely).
Using this approach, I am always perfectly ready to re-use objects knowing EXACTLY what they need to function as they are all required in params.
Why don't you use $GLOBALS? You don't even need to use global keyword.
The primary question here, I am wondering if this is bad practice
Well, I believe most people would say having a global state is bad practice because it is harder to manage or doing unit test. Most people would suggest you to use "dependency injection" which instead of depend on global state, you need to inject what the class need directly.
From your code it seems that you're just looking for a way to resolve your class names into file names. For that purpose it's better to use auto loaders. It takes the formality of how your classes map to file names away from the bulk of your code so that you can concentrate on actual development.
Organizing your plugins can be done by using namespaces.
Second, in most cases you don't want to instantiate classes inside the constructor because it leads to coupling, and too much coupling can stifle your project later; instead, inject the dependency:
class My_Class
{
private $settings;
public function __construct(My_Settings $settings) {
$this->settings = $settings;
}
}
To call it:
$c = new My_Class(new My_Settings());
Use this example to solve your problem
The global keyword doesn't work the way you think it does. It does not make a variable have global scope. All it does is specify to the function that you call it in that you want to use the variable in the outer scope.
For example:
$a="test";
function something() {
global $a;
echo $a; //Outputs: test
}
If you want to make a variable global so that it can be accessed from within a class, you need to use the $GLOBALS superglobal.
My question is very simple, I saw this code in a class:
class controller_activity {
function __construct($args) {
//the variable template is not defined or what happen??
$this->template = new Template('activity');
}
.......
Usually I see the declaration of variables in a class like "public $template" or similar, but this case, is the same that if I define those variables as usual?, can I add variables in this way directly?, without defining them before?, is it recomendable?
is the same that if I define those variables as usual?,
No, the definition is missing. get_object_vars will show them, but get_class_vars won't.
can I add variables in this way directly?,
Yes, that is possible. They will be publicly visible.
without defining them before?,
Yes, without defining them before. They will be publicly visible.
is it recomendable?
That depends. Normally not, but there are exceptions to this rule.
I think the reason why this code works is because the $this->template assignment is happening in the __construct() which happens pretty much immediately on class instantiation. So this could be seen as a sloppy—but fudgable—way of doing variable assignment. But it doesn’t help for readability or debugging later on. So the answer is yes, you can do this. Is it a "best practice?" 100% no.
While not recommended, PHP and it's non-constraining (weakly typed) use of variables means that it is possible to declare class vars on the fly.
I've done it by accident on a number of occasions, but then gone back and defined them properly. By default they will have the public access method (the same behavior as not including an access method at the head of the class, i.e. $var = 0 versus private $var = 0).
Again, this is not recommended. I haven't tested for it specifically, but I would imagine that they throw a Notice error. The other issue is that doing this makes code harder to follow, either for yourself later on or another developer trying to work with your class.
The code you posted will work without a problem.
In PHP you can use undeclared variables. In other languages (like Java), you can't use undeclared variables. It's simply a matter of style, but I personally don't like using them.
Note that the template var, if undeclared as in your example, has public visibility
I have recently learnt about namespaces in PHP, and was wondering, would it be bad practice to do this?
<?php
namespace String; // string helper functions
function match($string1, $string2)
{
$string1 = trim($string1);
$string2 = trim($string2);
if (strcasecmp($string1, $string2) == 0) // are equal
{
return true;
} else {
return false;
}
}
?>
Before I had this as a static method to a String class, but this always seemed wrong to me... Which is the better alternative? I have a desire to categorise my helper functions, and want to know which is the better way to do it.
Edit
So how do I then access the match function if I have declared it in a namespace? How do I stop the namespace declaration, say if I include a file beneath it which declared a new namespace, would it automatically stop references to the first? And how do I go about returning to global namespace?
I'd put it in a namespace. A class is a describes a type in php, and though you maybe operating over a type with a similar name, it's not the same type, strictly speaking. A namespace is just a way to logically group things, which is what you're using a class to do anyways. The only thing you lose is extensibility, but as you said, it's only a collection of static methods.
If they're all string-related functions, there's nothing wrong with making them static methods.
A namespace would be the better choice if you've got a bunch of global functions and/or variables which you don't want cluttering up global scope, but which wouldn't make sense in a class. (I've got a class in my own code which would be a lot better suited to a namespace).
It's good practice to stick everything in some sort of container if there's any chance your code will get reused elsewhere, so you don't scribble on other people's global vars...
As for your edit there:
Namespaces are tied to the file they're defined in, IIRC. Not sure how this affects included files from there but I'd guess they aren't inherited.
You can call the global scope by saying ::trim().
Because namespaces are so new to php, people have been doing for a long time what you did - create a class, add static methods, and use the class as if it were a namespace. It looks to me as if you are thinking about it properly.
You would use classes to categorized some sort of functions on a certain dat. Like let say you have a Student class which will hold student information and student age and student ID number;and alose there some sort of methods that return and set these data.
Moreover, you would use namespace to categorized the Classes;let say now you have another class which handle the University registration for those students and alose the other classes for managing courses. Personaly, I would put all these classes under a category (i.e. namespace) called University.
Thus, it is not even a bad practice, also it gives you more readability in your code. And that would be more underestandable for other programmers if you are working in a group.
So personally I strongly suggest you use those in your project wherever you think it is proper to use it.
Ideally, it would be best to put functions in a namespace. If you depend on autoloading though, which only works for classes, you need to put them in one or more classes.