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
Related
I have a need to call a class which will perform actions but which I know I will not be calling the methods of. This is a PHP application. Does anyone ever just do the following:
require('class.Monkeys.php');
new Monkeys(); //note I didn't assign it to a variable
Yes, that's perfectly valid. However, it is arguably bad form, because the golden rule is that:
Constructors should not do actual work.
A constructor should set up an object so that it is valid and in a "ready state". The constructor should not start to perform work on its own. As such, this would be saner:
$monkeys = new Monkeys;
$monkeys->goWild();
Or, if you prefer and are running a sufficiently advanced PHP version:
(new Monkeys)->goWild();
Well let just say that we have a classname called Monkeys.
File class.Monkeys.php
class Monkeys {
function __construct()
{
$this->doSomething()
}
public function doSomething(){
echo "new Monkeys()->doSomething() was called";
}
public function anotherMethod(){
echo "new Monkeys()->anotherMethod() was called";
}
}
Now you can instantiate the class on runtime without saving it into a variable.
require('class.Monkeys.php');
// you can just instantiate it and the constructur will be called automatically
(new Monkeys());
// or you can instantiate it and call other methods
(new Monkeys())->anotherMethod();
I'm not sure if the garbage collector will delete the instantiated classes or not, but i assume since those classes are not saved into a variable this would not be saved somewhere in the memory and that would be perfect.
This is somewhat a follow up to a previous question - but I've distilled the question down and have the "works" vs. "doesn't work" cases narrowed down much more precisely.
My Goal:
I have a class MyClass that has an instance variable myFunction. Upon creating a MyClass object (instantiating), the constructor assigns the instance variable myFunction with the result of a call to create_function (where the code and args come from a db call).
Once this object of type MyClass is created (and stored as an instance variable of another class elsewhere) I want to be able to call myFunction (the instance variable anonymous function) from "anywhere" that I have the MyClass object.
Experimental Cases -- below is my highly simplified test code to illustrate what works vs. what doesn't (i.e. when the expected functionality breaks)
class MyClass extends AnotherClass {
public $myFunction;
function __construct() {
$functionCode = 'echo "NyanNyanNyan";';
$this->myFunction();
/*Now the following code works as expected if put in here for testing*/
$anonFunc = $this->myFunction;
$anonFunc(); //This call works just fine (echos to page)!
/*And if i make this call, it works too! */
self::TestCallAnon();
}
public function TestCallAnon() {
$anonFunc2 = $this->myFunction;
$anonFunc2();
}
}
However, if I do the following (in another file, it errors saying undefined function () in... within the Apache error log.
//I'm using Yii framework, and this is getting the user
//objects instance variable 'myClass'.
$object = Yii::app()->user->myClass;
$object->TestCallAnon(); // **FAILS**
or
$func = $object->myFunction;
$func(); // ** ALSO FAILS **
In addition, several variations of calls to call_user_func and call_user_func_array don't work.
If anyone is able to offer any insight or help that would be great :).
Thanks in advance!
You can't pass references to functions around in PHP like you can in for instance JavaScript.
call_user_func has limited functionality. You can use it like so:
class MyClass {
function func() {}
static function func() {}
}
function myfunc() {}
$i = new MyClass();
call_user_func("myfunc", $args);
call_user_func(array($i, "func"), $args);
call_user_func(array(MyClass, "staticFunc"), $args);
I ended up solving this issue via a workaround that ended up being a better choice anyways.
In the end I ended up having a static class that had a method to randomly return one of the possible identifiers, and then another method which accepted that identifier to build the anonymous function upon each class.
Slightly less elegant than I would like but it ends up working well.
Thanks to everyone for your efforts.
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'm php coder, trying to get into python world, and it's very hard for me.
Biggest enjoy of static methods in php is automatic builder of instance. No need to declare object, if you needed it once, in every file (or with different constructor params , in one line)
<?php
class Foo {
function __constructor__(){
$this->var = 'blah';
}
public static function aStaticMethod() {
return $this->var;
}
}
echo Foo::aStaticMethod();
?>
we can call constructor from static method don't we? and we can access everything in class as it would be simple method ... we can even have STATIC CONSTRUCTOR in php class and call it like so: Object::construct()->myMethod(); (to pass different params every time)
but not in python???? #staticmethod makes method in class a simple function that doesn't see totally anything ??
class socket(object):
def __init__(self):
self.oclass = otherclass()
print 'test' # does this constructor called at all when calling static method??
#staticmethod
def ping():
return self.oclass.send('PING') # i can't access anything!!!
print Anidb.ping()
I can't access anything from that god damned static method, it's like a standalone function or something like this..??
Maybe I'm using the wrong decorator? Maybe there's something like php offers with static methods in python?
1) Please tell why static methods is isolated
2) Please tell me how to make the same behavior like php static methods have.
3) Please tell me alternative practical use of this, if php static methods behavior is a bad thing
P.s. the goal of all this to write totally less code as much as possible.
P.p.s Heavy commenting of sample code is appreciated
Thank you.
static methods in PHP are not as you believe, they can't access to instance members. No $this! with them.
<?php
class Foo {
public static $var = 'foo ';
function __construct(){
echo 'constructing ';
$this->var = 'blah ';
}
public function aMethod() {
return $this->var;
}
public static function aStaticMethod() {
#return $this->$var; -> you can't do that,
# $this can be accessed only in instance methods, not static
return self::$var;
}
}
$foo = new Foo();
echo $foo->aMethod();
echo Foo::aStaticMethod();
?>
Python has three kind of methods in objects static methods are like functions defined ouside classes, the only use to put them in object is to keep them with the class as helper functions. class methods can access only to variables defined in the class (decorator #classmethod). This is more or less what PHP calls static members or methods. The first parameter of such methods sould be cls, and content of class can be accessed through cls. Normal methods must get self as first parameter and are the only ones to be able to access to instance members.
If you want several objects of the same type you definitely need instances, and the other types are not what you are looking for. If you only have one instance of an object, you could use class methods instead (or PHP static methods).
But in most case you should not bother doing that if you don't know why and just stick with instances of objects and normal methods, doing otherwise is premature optimization and your code is likely to bite you later because of the many restrictions you introduce.
You want classmethod instead. That provides the class as the first argument.
EDIT:
class C(object):
foo = 42
#classmethod
def printfoo(cls):
print cls.foo
C.printfoo()
I see you've already accepted another answer, but I'm not sure that it will work with your code. Specifically, the oclass variable is only created for instances of the class, not for the class itself. You could do it like this:
class socket(object):
oclass = otherclass()
#classmethod
def ping(cls):
return cls.oclass.send('PING')
socket.ping()
However, using your existing code and removing all decorators, you could simply instantiate it and use a method on the same line:
socket().ping()
im looking at the MVC pattern, and I can see in one example on phppatterns they're passing the model by reference - any benefit of doing this over a global var? Am I missing something obvious?
class MyView extends View {
var $model;
function __construct(&$model){
$this->model =& $model;
}
function productTable($rownum=1) {
$rowsperpage='20';
$this->model->listProducts($rownum,$rowsperpage);
while ( $product=$this->model->getProduct() ) {
// Bind data to HTML
}
}
}
Any reason why you would do this as apposed to using a global variable? i.e.
class MyView extends View {
global $model;
function __construct(){ }
function productTable($rownum=1) {
$rowsperpage='20';
$model->listProducts($rownum,$rowsperpage);
while ( $product=$this->model->getProduct() ) {
// Bind data to HTML
}
}
The problem with global variables is that:
They assume that there is only one implementation of model and view.
They assume that there is only one instance of the model and view (you could have several of each in your application).
They hide the interdependency between components; your view is very strongly affected by the model, but not having to explicitly pass a model into your view makes this implicit.
For other reasons why globals and singletons are "evil" (i.e. just really a poor design decision that you should never make), read avoid global variables, environment variables, and singletons.
Yes -- the advantage is that you could change the implementation of the model without having to modify the View.
I'd suggest to use another tutorial, the one you're using is a bit outdated, and isn't PHP 5. That said, you really shouldn't use global variables, that's never the solution!
But I don't really get why you should even wanna pass it by reference, in PHP 5 it's already passed by reference:
class foo {
public $a;
public function __construct($a) {
$this->a = $a;
}
}
$a = new foo(10);
$b = $a;
$a->a = 20;
echo $a->a.' => '.$b->a; // 20 => 20
If you have multiple (similar) model instances, on which you possibly would like to apply the same view, you would need to explicitly pass the model instance. A global variable assumes there could be only one model instance, and thus creates an artificial limitation.
In general not using global variables is better to help you control the scope of your variables.
I won't mention about why that is a bad thing, because it has been already discussed. One thing that I think you should know is that the code provided there is PHP 4 compatible. In PHP 5 by default objects are sent by reference.