now i have class
class test{
var $var_test = 'test';
}
how i can get it
i think
$t = new test();
echo $t->var_test;
is this true
Have you tried it?
But yes, that is true. (It would be better to declare the member with public if you're going to access it from outside the class.)
If your variable is public, yes. Be sure to use proper visibility for your variables and methods.
Typically, you'll want to use get() and set() methods to handle data within the class itself. These keeps people's grubby hands off of your data :) Generally these will return the value from within the class ( return $this->val; ) so nobody is directly able to access the variable.
If you are wondering if
$t = new test();
echo $t->var_test;
is correct, then the answer is yes. I guess that you made the question because you are having problems with code you developed, and you want to understand why it is not working. If that is the case, then you should report the exact code you are using.
As side note, the code you are wrote is for PHP4; PHP5 uses a different syntax for class declaration, even though it is able to parse PHP4 classes.
Related
Is it possible to prevent variables from being overwritten in PHP? I am making a system that has some reserved variables and I don't want them to be replaced with something else after a certain point. It is possible? If not, what can I do to approach something close to this?
Some of these vars are instantiated classes so I can't define them as constants.
Take a look at this question. Also the information about constants in the PHP manual may be helpful.
Yes, they're called constants.
If you cannot use them, assuming you're running the latest PHP version, you can use namespaces, using namespaces, you can have 2 variables of the same name, on different namespaces. So that you don't have collisions.
The best you can do (that I am aware of) in this case is make them private variables inside the class. Then you have to use getters and setters to assign the values, or a construct. That way, someone else's code is less likely to collide with yours.
It's impossible to find out how it is the easiest in your situations, as there is no code available at all, but on of the better options would probably be is
hide them in a class as private member vars.
expose them through getters.
If needed, make them static
Maybe you can implement something like frozen state, and if class is frozen, can't be modified:
class Test
{
private $variable;
private $frozen = false;
public function freeze() {
$this->frozen = true;
}
public function setVariable($value) {
if ($this->frozen)
throw new Exception("...");
$this->variable = $value;
}
}
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
I was reading an article about Data Encapsulation in PHP, and the author explained in such a way that it made me to wonder if this is really possible? here is what he said.
The primary purpose of encapsulation
(scope) is to ensure that you write
code that can't be broken. This
applies to scope in general, so let me
use a simpler example of a local
variable inside a function:
function xyz ($x) {
$y = 1;
while ($y <= 10) {
$array[] = $y * $x;
$y++;
}
return $array;
}
The purpose of this function is to
pass a number and return an array. The
example code is pretty basic. In order
for function xyz() to be dependable,
you need to be guaranteed that it does
the exact same thing every time. So
what if someone had the ability to
from the outside change that initial
value of $y or $array? Or even $x? If
you were able to do that from outside
of the function, you could no longer
guarantee what that function is
returning.
Now this made me wonder can i really change the value of local variable sitting inside the function without using any argument as demonstrated above ?? if it is possible how do i do it?
thank you..
For this example you wouldn't be able to change any of the variables, because they're all declared inside of the function.
But if you had a class with a public class variable, you could change that outside of the class if you wanted to. (That's bad form and might screw a lot of things up, though.)
Unless you add a magic setter method ( __set($key,$value) ), and configure it in such a way that you can access that internal member, then no. You can change the key when you make the function if you're using some form of factory, but if you haven't made it public, there's no other way.
The only visible exception would be with a singleton factory: you could make a new instance of your singleton method with different parameters (changing it everywhere else), but I doubt you'd be likely to do that with a method.
I am working on a website with php/mysql.
I have 3 files config.php, utils.php and member.php. code of the files are as below,
config.php - $objPath->docrootlibs is fine, I am sure there is no problem with this.
/* Other library files & their object */
require($objPath->docrootlibs.'/utils.php');
$objUtils = new utils();
require($objPath->docrootlibs.'/member.php');
$objMember = new member();
utils.php
class utils{
function getCurrentDateTimeForMySQL(){
return date("Y-m-d H:i:s");
}
}
members.php
class member{
var $userid;
var $username;
function __construct(){
$this->lastactivity = $objUtils->getCurrentDateTimeForMySQL();
}
}
Now when I am including the config.php inside a page home.php with simple php include statement and running that page then it gives me following error.
Notice: Undefined variable: objUtils in D:\wamp\www\site\libs\member.php on line 17
Fatal error: Call to a member function getCurrentDateTimeForMySQL() on a non-object in D:\wamp\www\site\libs\member.php on line 17
Line numbers in error above are different, I just copied the specific part from the code here.
I am not understanding why its giving error, because objects of utils class is defined on config page before including the member class. It should detect that object.
Please check and help me to understand and correct this error.
Thanks!
One Solution
Unlike JavaScript PHP will not bubble up through scopes, which means
public function __construct(){
$this->lastactivity = $objUtils->getCurrentDateTimeForMySQL();
}
does not know what $objUtils is, because there is no such object defined in the local scope. This means, you have to make the object available inside that scope. The cleanest and most maintainable way to do that is to inject the utils instance to the member instance, e.g.
public function __construct($utils){
$this->lastactivity = $utils->getCurrentDateTimeForMySQL();
}
However, since you seem to be using that value on construction only anyway, there is no reason why your member instance has to know how to use the utils object. So why not just insert the actual value right from the start, e.g.
public function __construct($lastActivity){
$this->lastactivity = $lastActivity;
}
// then do
$utils = new utils();
$member = new member($utils->getCurrentDateTimeForMySQL());
On globals
You definitely do not want to use the global keyword or static methods. Both couple back to the global scope. This means you can no longer use the member class without the global scope. This makes maintaining, reusing, refactoring and testing harder. OOP is about encapsulation and by reaching out from the class to the global scope you are breaking that encapsulation. Use Dependency Injection as shown above instead.
Apart from that, using globals will also make your code harder to read. A developer looking at the ctor signature of member is likely to assume there is nothing else to do than just call new member. That's a lie, because she also has to setup the utils instance. In other words, you are hiding dependencies. The developer has to look at the actual code to understand what's going on. Thus, make dependencies explicit.
Some more resources:
http://c2.com/cgi/wiki?GlobalVariablesAreBad
http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/
EDITs after comments
If you really need that utils object, inject the instance and assign it to a property inside the member instance in the ctor. Then you can access it with $this->utils->foo() from anywhere else inside the member instance.
However, Utility classes are almost always a sign of bad design. It is much more likely that they should be broken apart and divided into/onto other objects. Try to find out the reponsibilities. Maybe Member should not use Utils, but Utils should be something else that uses Members.
Out of curiosity, why do you need a utility method for MySql anyway? If you use a Timestamp column in MySql for lastActivity, it will automatically update whenever the row is updated. I am assuming you are setting the lastActivity and then store the member data?
Regarding performance: you should not bother about performance. Write readable and maintainable code first and foremost. If you think your performance is not good enough, profile the application with XDebug to see what is really making an impact.
As another comment states, use dependency injection. Insert the utilities object into the constructor. Do not introduce variables over the global scope, especially between different files. This gets very confusing and creates a mandatory order of some file includes.
class member {
...
public function __construct(utils $objUtils) {
$this->objUtils = $objUtils;
...
}
}
In calling code:
$member = new member(new utils);
As an aside, I find it humorous that you have a macro with a name that is longer than the operation it performs.
As another aside, do you need a utilities class? Can the utilities just be functions?
It sounds like config.php is in the global scope. You need to use the global keyword when using $objUtils
function __construct(){
global $objUtils;
$this->lastactivity = $objUtils->getCurrentDateTimeForMySQL();
}
Since your getCurrentDateForMySQL doesn't depend on anything else inside your utils object, why not make it a static function? That way you can turn your member() method into:
function __construct(){
$this->lastactivity = utils::getCurrentDateTimeForMySQL();
}
I have a class that I am using all over the place in my code. It contains settings and other core functionality. Here's what I'm doing right now to use the class.
$settings = new Settings();
$settings->loadSettings();
Then, when I need to the code in some random function in another class, I do something like this:
function abc() {
global $settings;
$variable = $settings->a;
}
I'm sick and tired of randomly calling global $settings all over the place to pull in that settings object. I don't want to use the $_GLOBALS array (I don't know why, I just don't want to).
I'm thinking I want to switch to have a static class variable called $settings inside of settings. The code would look like this:
Settings::$settings = new Settings();
Settings::$settings->loadSettings();
Then, whenever I want to use it, I never have to worry about sucking it in via the global operator:
function abc() {
$variable = Settings::$settings->a;
}
Good idea or bad idea?
Well it's probably an improvement on globals, because it solves all the ugly scoping issues that globals cause. Getting rid of the global operator is generally a good thing! What you are doing is not dissimilar to the singleton pattern, though it's considerably simpler. (See the "Singleton" section at http://php.net/manual/en/language.oop5.patterns.php for more information on the pattern.) Your solution is almost certainly fine for your purposes.
On the other hand, there may be better ways of achieving the same thing that decouple your code more. That is to say, each class becomes more capable of being used in another project without significant recoding. One way to do this would be to "inject" the settings object into each class:
class ABC {
private $settings;
public function __construct($settings) {
$this->settings = $settings;
}
public function someMethod() {
$variable = $this->settings->a;
}
}
This would be more work, but may improve the re-usability of your code. You could then, for example, write a different settings class for every project but use the same ABC class.
This process, where you "inject" an object into another object that depends on it, is called dependency injection. There are other, more complex ways of doing this, including complex containers. See http://fabien.potencier.org/article/11/what-is-dependency-injection for an interesting set of tutorials on the subject. They're probably incidental to your current needs, but may help either now or in the future.
It seems you are looking for a Singleton. Basically the idea is to have a class which has a public static method getInstance() which returns an instance of the class itself. The first time you call the method, it stores the instance in a private property, and all later time it returns the stored instance. In this way, whenever you call Settings::getInstance(), you are guaranteed to have a copy of the same object. Then you can store settings in this object.