trouble with php object inheritance - php

I am building a page through a series of include files. Many (not all) of the include files are classes of various things that I need stored as objects. For instance, one of my pages is:
class site {
var $siteid;
var $sitename;
function __construct($id, $name) {
$this->siteid = $id;
$this->sitename = $name;
}
function get_siteid(){
return $this->sitename;
}
and then on another page I have:
$site = new site("4","My Site");
So, on a subsequent include page I create another class called "page". While creating this class I need to reference the siteid value instantiated previously for $site, but I can't seem to get at it.
I've tried $site->get_siteid() but I get a message that says "undefined variable."
Strangely, on a regular HTML page later on, I am able to get the site id simply with $site->siteid, but from what I have read this is not a good practice, and this also doesn't work within the page class anyway.
I'm still pretty new to OO coding and so I am sure I am missing something pretty basic here, but have tried a lot of things and cannot seem to make it work.
Thanks in advance. :)

Firstly, since you're using PHP5, use access specifiers when declaring properties and methods:
Change:
var $siteid;
var $sitename;
To:
public $siteid;
public $sitename;
Or make them private or protected if preferred. See the manual for more info on visibility.
I've tried $site->get_site(id) but I
get a message that says "undefined
variable."
There is no method called get_site. There is one called get_siteid but it inexplicably returns the site name. You'll want to straighten that out.
I am able to get the site id simply
with $site->siteid, but from what I
have read this is not a good practice
There's no point in making getters/setters that simply return/set member variables. Just declare the member public and access it directly. Nothing wrong with that.

HTTP is a connectionless protocol. So state based information is not saved between requests.
The object that is instantiated (eg. $site) will not be maintained between pages.
If you have persistent data that you need to store objects you can serialize the objects and store it in a mysql table or a file. Then you can retrieve the serialized object by a using a key and the deserialize it and use it.

Several things
Intentionally or not, you have a typo. Your method is named get_siteid() but you reference $site->get_site(id)
id is not a valid variable, you should be using $id
You're method doesn't receive a parameter but you're sending one
The reason $site->siteid works is because site::$siteid is public. To prevent this, make the variable protected or private.

Related

How best to make PHP static variables not to loose data [duplicate]

Hi i have a strange problem with a WordPress plugin that i am writing, but this isnt about WordPress per se and more to do with PHP so please read on so I can explain. The WordPress plugin is hooked up so that the init() function gets called... this works i can confirm it gets called once.
class MyClass
{
static $i=0;
public static function init()
{
self::$i++;
}
public static function dosomething()
{
echo 'i is = ' . self::$i;
}
}
When callinf dosomething() for the first time from within Wordpress it is ok. I then have another ajax-response.php file which includes the above class and again calls dosomething, which prints the i value = 1.
The problem is the i value when calling via the ajax-response.php script is back to 0?
Its as if it is executing in a totally different memory space and creating a new program, such that static member variables are only shared between same process as opposed to multiple web threads.
Any ideas?
Thanks in advance,
Chris
Its as if it is executing in a totally different memory space and creating a new program, such that static member variables are only shared between same process as opposed to multiple web threads.`
Exactly! :) That's 100% how this works. Each PHP request is a new one, with its own memory. The static keyword is not designed to work around that.
If you want to persist stuff across multiple processes / requests in a web application, you need to use sessions.
Ajax request is another request. That's why there are new variables
You may use session to store values between requests
You might need sessions on this one. Variables are stored in the current instance only, so if you call another script and create an instance of the MyClass class all of its properties will be set to default.
That's correct, you're variables won't stay active between different processes. Each process has it's own copy of the variable. You have many choices here.
You could use store the variable in a session if you want it to be short term storage. If you want to store it indefinitely you should store it in a database or a file.

PHP classes - is it preferable to use normal variables instead of properties?

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

Include vs Extend for data access

This is a design question that has irked me because deep down I know I'm doing it wrong. This is not necessarily just a PHP problem, but I'm working on a PHP project now so that's where I'm coming from.
I'll just give you the scenario:
I have a JSON generation class that is used by a data access script. Basically it's the go-to URL for a website that instantiates the JSONGen class, which in turn looks at a static file and pulls the data that was requested, and sends it back as a JSON object. The file that contains the raw data has it all in array format to allow for easier reading and updating (so one doesn't have to sift through raw JSON data and risk syntax error, etc).
My question is in the accessing of that file.
What I did was to place a require([json file]) outside the class definition. Everything in the [json file] is assigned to one $JSON object.
In the class constructor, I do:
global $JSON;
$this->JSON = $JSON;
(Where $this->JSON is a private class variable).
This gives me access to the JSON from anywhere in the class, which is lovely.
It feels hacky, but I can't find anything anywhere that addresses this specific type of approach.
The problem is that once somebody decides to move the class or whatever, the only way they have of understanding the dependency of this file is in that there's a require statement in the header. Is that just how things work? Or is there a better way to do this?
Should I use extend and put the JSON into a class (THAT sounds really stupid to me), or continue forward with my include? Or should I never, ever include a file in a class like this and rather pass it to the constructor or some other access method?
This specific instance is a small project, and it just doesn't make sense to set up a DB for it. We can add to the file, modify the config, and the whole site updates.... so please don't tell me to switch to a DB- I'm looking for strategies for this specific problem in a more general sense.
Thanks!
Probably going to get downvoted for this one but here it goes...
class JSON_Response {
public static $JSON;
// don't let people make one of these it gives the illusion that there can be more then one
protected function __construct(){}
}
then in your file
JSON_Response::$JSON = $json;
and access if from anywhere as JSON_Response::$JSON;
and if there is anything that you commonly do to the json object (check a flag or something) you can just add a static method to the JSON_Response class.

private methods and variables in PHP usage [duplicate]

This question already has answers here:
What is the difference between public, private, and protected?
(16 answers)
Closed 9 years ago.
I have been thinking about the usage of private variables and methods in php.
I am not going to talk about a class of car or anything like that. I want to talk about an own script.
What is the difference between using public or private for the programmer and the owner of the script.
if the script is a calculator, and I am the only one who will meinten the code in the future. when do I have to use private variables of methods. How this is going to change anything in the script?
Also, If it's about touching the variable ? if anyone tries to change the value, and he couldn't because of the private thing. He will go directly to change it using the setters ?
I need a good example that I can see private methods or variables have good benefits for programmer or the end user.
I was programming some scripts, and a guy told me to not use var in classes. I asked him why ? he said that you have to use public or private .. and asked why ?
Why to use setter if there is a way to change the variable directly?
Why to use getter if there is a way to change the variable directly?
First of all, when you're developing strong-OO classes, you should be exposing as little of the internal semantics of your class as possible (obviously without affecting functionality).
Some variables are only valuable inside the context of the class itself, and would make no sense to a developer using the class. Making the variable public allows anyone using the class to change such a variable at will, despite the fact that they may not know what it's used for. In PHP this can be a particular problem when you don't even have type safety to at least mitigate the damage that can be done.
Consider this: You have a class which wraps around some I/O operations. Let's call it FileReader
class FileReader {
public $_handle;
public function __construct($filepath) {
$this->_handle = fopen($filepath, 'r');
if ($this->_handle === NULL) {
throw new Exception("Unable to open the file for reading");
}
}
// ... the rest of the class
}
Now you can see that the class opens up a handle to a file. By making the $_handle variable public, you've exposed it to any and all people working on your class. They don't need to know about the raw file handle you have open, they just want to use your nice class to perform some read operation. However, it IS public; not only can they see it, but they can change it. This is bad, especially when your other code assumes that the $_handle variable is valid.
$reader = new FileReader();
$reader->_handle = "I hope this doesn't break anything. /trololol";
$reader->someOperation(); // oh no! Our file handle has just been changed to something completely wrong, this is now going to the break the class.
Such ridiculous scenarios can be avoided entirely by making the variable private in the first place. For more (and better) example of what each access modifier does, and when to apply them see this answer.
Now, onto getters and setters. In your question, you seem to assume that all getters and setters are written the following way:
class Foo {
private $_bar;
public function getBar() {
return $this->_bar;
}
public function setBar($newBar) {
$this->_bar = $newBar
}
}
In which case, you're absolutely right there is no difference between that and changing the $_bar variable to be public in the first place.
However, getter and setter methods give you control over how your variables are being set by an external developer, so you can instantly detect when they're going to make a boo-boo and avoid undefined behaviour later on. For example:
class Foo {
private $_bar;
public function getBar() {
return $this->_bar;
}
public function setBar($newBar) {
// Now we're going to ensure that $newBar is always an integer
if (!is_int($newBar)) {
// not an integer, throw out an exception to let the developer know that somewhere is setting invalid input
throw new Exception("Expected an integer value for 'Bar'");
}
$this->_bar = $newBar;
}
}
This is not only making your class far more robust, but also making the life of the developer using your class a hell of a lot easier. Rather than having to debug an extremely weird issue somewhere later on when the class attempts to use the corrupt value of $_bar, they can easily tell from a stack trace where the corrupt value was set from and fix it at the source.
There is plenty of documentation about variable access and getter/setter methods out there, and it applies to a whole range of languages so don't be afraid to look up articles that were based on C++/C#/VB.NET, they all roughly translate to the same material.
The end user doesn't see the code, so there's no (dis)advantage there.
For the programmer, declaring things that aren't needed outside the object as private is just a good programming practice and a protection mechanism. Technically, if you're a perfect programmer, and you don't care about how your code looks, using private will provide you no benefits. However, private members enforce the black box model -- you only care about what the object does, not about how it works (when looking at it from the outside). In the end, if for any reason you (or somebody else) needs/wants to use your code, they'll know what methods and properties to use/invoke in order to get the functionality the object has, without modifying the internal values the object needs to maintain. It may or may not give you any advantage -- it's just about how the code looks like. That's what good programming practices are for, and they are usually followed because experience says they tend to minimize errors.
As for var, it was deprecated. Meaning it could (and will) be removed in the future.
Public, Private and Protected only matter in PHP if they are part of a function, or part of a class.
If you wanted to set a variable once and "lock it" so the value couldn't be changed later you can define it or set it as a const (constant).
public scope to make that variable/function available from anywhere,
other classes and instances of the object.
private scope when you want your variable/function to be visible in
its own class only.
protected scope when you want to make your variable/function visible
in all classes that extend current class including the parent class.
See here: http://php.net/manual/en/language.oop5.visibility.php

JavaScript Objects Sharing Local Variable

So I have a bug in some JavaScript code that has been driving me moderately crazy. I've been trying to mimic classical inheritance in JavaScript (I know, I know, half the posts I read on here say not to twist JavaScript into such a framework, but my application needs to have a client-side heirarchy that maps to the inheritance structure of my server-side php code). And mostly, it looks like everything is working. Here's the function I'm using to extend classes:
Function.prototype.inheritsFrom = function(parentClass) {
//:: Ordinary Classes
if (parentClass.constructor == Function) {
this.prototype = new parentClass();
this.prototype.constructor = this;
this.prototype.parent = parentClass.prototype;
//:: Abstract Classes
} else {
this.prototype = parentClass;
this.prototype.constructor = this;
this.prototype.parent = parentClass;
}
return this;
}
Not my own creation, I found it online, but it works well. The only thing I needed to add was a "super" function to search the prototype chain for parent methods; the parent construct in the aforementioned code doesn't work in every case.
In any case, as I've been ironing out some bugs in my code, I found that one of the methods in my base "class" is accessing/modifying the same variable for all instances created from all of its subclasses. In other words, whenever one instance modifies this variable which should be local to its object context, it in fact modifies some variable that is shared between all instances. Here's the base class:
function DataManipulatorControl() {
//|| Private Members ||//
var that = this;
//|| Properties ||//
//|| Root ID
this.rootID = function(value) {
if (value !== undefined) {
if (_root_id !== null) {
alert('# ' + _root_id);
$('#' + _root_id).prop('js_object', null);
}
_root_id = value;
$('#' + _root_id).prop('js_object', this);
}
return _root_id;
}
var _root_id = null;
// other properties/methods
}
//|| Class: DataManipulatorContainerControl
function DataManipulatorContainerControl() {
//|| Private Members ||//
var that = this;
// subclass properties/methods
}
DataManipulatorContainerControl.inheritsFrom(DataManipulatorControl);
As I mentioned, when I create new instances of these prototypes, I'm finding that changing the rootID for one instance will change it for all. My first thought was that I forgot a "var" somewhere, and that my function was accessing the global context. That doesn't seem to be the case though, so my next thought is that it's using a variable local to the prototype. That doesn't make much sense to me either though, because variables local to the prototype's constructor call shouldn't be accessible outside of it, unless accessed by a method that already has it in scope. Of course, the rootID() function does have it in scope, but I was under the impression that it would be run using the object context of the invoking object, not the prototype.
So, I'm very confused. Any light that can be shed on this issue would evoke much gratitude.
EDIT: The article provided by PRB describes a solution which cleanly solves this issue - mostly. The article notes that you need to also call the parent class' constructor from within the child class constructor to initialize everything correctly. As a result, all of the methods are created fresh, with their own versions of the parent class local variables in closure.
There does seem to be one shortcoming with this approach (aside from efficiency concerns of duplicating functions in every instance). If one tries to call "overridden" functions from the prototype chain in an attempt at super functionality, this problem will resurface. The prototypes are, as before, instances of a single object, and trying to call their versions of a function will cause them to try to access their instance's local variables.
Still the best solution I've seen though, aside from making all the data public :-).
Using this line is probably the issue:
this.prototype = new parentClass();
This means that all instances of the function share the same memory blob defined by parentClass(). This is why when you change the value in one, it affects all of them.
Okay, so I've been thinking about it over some dinner, and I think I might have a handle on what's going on. I think I'm confusing variables available to a function due to a changing object context, and variables available to a function because of closures.
As PRB pointed out, my rootID() function always accesses the blob of memory from the instantiated prototype. _root_id is created as a variable local to the constructor for my base class, so when that base class is instantiated to become a prototype, all subclasses using the prototype's function will as a result be reading from/writing to the one variable created in the constructor.
So while that is a valid way to create a prototype, hiding the object's data using variables local to the constructor will not work correctly in subclasses. Rather, I'll need to read from/write to variables in 'this', so that it changes as the object's context changes. If anyone knows of a better way to handle this - one which obeys data hiding, please feel free to comment; a lot of the developers I work with have no qualms about accessing data members directly instead of through accessors. Makes code hard to maintain :-/.
At any rate, thanks PRB for the clarification!
~ Nate

Categories