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
Related
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 doing a class "Container" to hold all my model/service instances, the class is a singleton.
Consider the following code portion (from a CodeIgniter project):
public function getReviewModel()
{
static $loaded = false;
if (!$loaded)
{
$this->load->model('review_model');
$loaded = true;
}
return $this->review_model;
}
I am wondering if is still ok to use static inside method like this or should I use only class property (I mean about performance and coding standard) ?
In your example, nothing prevents the programmer to instanciate the class more than once (with dire results), so it is rather a confusing bit of code.
Static variables have their uses, be them local to a function or defined at class level.
Especially in PHP scripts, when the output is often a single piece of data that can conveniently be handled as a class defining only static properties and methods.
That would be a true, foolproof singleton class.
Since mistaking a static variable for a dynamic one is a common pitfall, I tend to favor static class variables to avoid the confusion (i.e. the self::$... syntax makes them stand out clearly).
General consensus as far as statics are concerned in PHP is: Avoid, if at all possible. And yes, 99% of the time, it is possible to avoid statics.
Singletons should be avoided 100% of the time. For reasons you can find here and virtually everywhere else on the web. Singletons are like communism: sounds like a nice idea, but when put in to practice, it turns out there's one or two things you didn't anticipate.
A Singletons' main purpouse is to retain state, but PHP itself is stateless, so come the next request, the singleton needs to be re-initialized anyway.
If I write getters like yours, I tend to create them in a lazy-load kind of way:
class Example
{
private $reviewModel = null;//create property
public function getReviewModel()
{
if ($this->reviewModel === null)
{//load once the method is called, the first time
$this->reviewModel = $this->load->model('review_model');
}
return $this->reviewModel;
}
}
This basically does the same thing, without using statics. Because I'm using a property, I still retain the instance, so if the getReviewModel method is called again, the load->model call is skipped, just as it would be using a static.
However, since you're asking about performance as well as coding standards: statics are marginally slower than instance properties: Each instance has a HashTable containing for its properties, and a pointer to its definition. Statics reside in the latter, because they are shared by all instances, therefore a static property requires extra lookup work:
instance -> HashTable -> property
instance -> definition -> HashTable -> property
This isn't the full story, check answer + links here, but basically: the route to a static propery is longer.
As for coding standards: They exist, though still unofficial, most major players subscribe to them, and so should you: PHP-FIG
Things like $this->_protectedProperty; don't comply with the PSR-2 standard, for example, which states, quite unequivocally:
Property names SHOULD NOT be prefixed with a single underscore to indicate protected or private visibility.
I'm pretty proficient with PHP, outside of OOP - which I am just now starting to jump in to.
I've been watching videos and reading tutorials, but they are all still pretty confusing...
If I have
FILE 1 (class.time.php)
class Time {
function GetTime(){
$time = date('H:i:s');
printf($time);
}
}
and then in a nother php page I've got
FILE 2 (page.php)
I can do
include('class.time.php');
and then anywhere in this page I can then do
$time = new Time; //Calling the class and setting the class to a variable
$time->GetTime(); //This is BASICALLY saying (run the 'GetTime' function in the 'Time Class'
My main question is, is the comment above (This is BASICALLY saying.....) correct? or is there a better way to think of it?
regarding method calls
I would make one correction to your statement, hinting a little more accurately at what Object Orientation is all about. Your comment reads:
run the 'GetTime' function in the 'Time Class'
Which is only kinda accurate, and expounding on it may clarify OOP for you. For the purposes of this post, I might rephrase it this way:
run the 'GetTime' method (which is defined in the Time class) bound to the object stored in $time
See the difference? You aren't just calling a function from a class, you are saying "get the processing instructions from the class, but bind those instructions to this specific object and then execute.
It may sound like mincing words, but it's critical to understanding encapsulation. Objects of a class share their method definitions, but they do not share data.
You can think of an object as essentially a set of two things:
A block of memory holding it's own, personal data
A pointer to a set of methods with special access to that data
(the "special" nature of the methods' relationship to the data is either implicit or explicit, it's up to you)
The distinction is readily evident when you start using "member variables" (sometimes called "object properties", "instance variables (aka ivars)", or similar names). Consider this sample code:
class Person {
public $name;
public printName() {
echo $this->name;
}
}
$me = new Person();
$you = new Person();
$me->name = "Chris";
$you->name = "Alex";
$me->printName(); // "Chris"
$you->printName(); // "Alex"
This highlights the fact that each object has it's own memory for instance variables. They share the definition of those variables, as well as the blocks of code written to process those variables.
The special variable $this is of particular interest to my overall intention with this answer: the same variable in the same method definition actually points to a different object depending on which object you call the method on.
regarding new
Now to the previous line, where your comment reads (in regard to $time = new Time):
Calling the class and setting the class to a variable
The way I would phrase it is:
Make an instance of this class, and allow me to access the instance through $time
That word, instance will be a big concept to get solid before moving on. You don't call a class, you call a method, and you don't (in PHP at least) set the value of variables to be a class, you set them to point to instances of the class. Sometimes people use the words instance and object interchangeably, which is fine. But you should not use them interchangeably with the word class.
Let's get technical:
When you use the new operator, technically you are telling PHP to do two things:
grab some fresh memory, exactly enough to store all the member variables defined in the class
call a special method on that new object to allow me to initialize my object
So if you call new twice, you grab enough memory for 2 objects, and so on. PHP uses your class definition to figure out how much memory to allocate for you, and find the special method to call.
That special method is called __construct, and is guaranteed to be called when your objects are created, with that special $this variable pointing to your shiny new memory. Here's a sample of how you might use it:
class Foo {
private $createdTime;
public function __construct() {
$this->createdTime = time();
}
}
$myFoo = new Foo;
Even though you don't see it, __construct() was called and the value of $createdTime was initialized.
Yes, basically your assumption is correct (apart from syntax errors).
However thats not a very good OO design.
Have a look at this, it give some good examples of OO design: http://www.math-cs.gordon.edu/courses/cs211/ATMExample/
That is correct, but the syntax should be:
$time = new Time();
$time->GetTime();
(don't forget the parentheses, otherwise you are referring to class properties)
Also, it is a good idea to declare your methods as public, protected, or private. If you are going to call the GetTime method from outside the class, it would need to be public.
Since in this case "get time" will never change and accepts no parameters, you would do best to put this into a static method, since it's a waste to instantiate a class in this situation
eg:
class Time {
static public function GetTime(){
$time = date('H:i:s');
printf($time);
}
}
Time::GetTime(); // gets the time, no need to do $time = new Time();
In my opinion you are doing it correct, but for using a simple built-in date function, using it via class would probably just over complicate it.
Following is an excellent article for learning OOP in PHP
PHP OOP for beginners
My code is located here: https://github.com/maniator/SmallFry
Should I make it so that that the App class does not have to use static functions but at the same time be able to set and set variables for the app from anywhere?
Or should I keep it how it is now with App::get and App::set methods?
What are the advantages and disadvantages of both?
How would I accomplish that 1st task if I was to undertake it?
Related Question
Sample code:
//DEFAULT TEMPLATE
App::set('APP_NAME', 'SmallVC');
//END DEFAULT TEMPLAT
//
//DEFAULT TEMPLATE
App::set('DEFAULT_TEMPLATE', 'default');
//END DEFAULT TEMPLATE
//DEFAULT TITLE
App::set('DEFAULT_TITLE', 'Small-VC');
//END DEFAULT TITLE
//LOGIN SEED
App::set('LOGIN_SEED', "lijfg98u5;jfd7hyf");
//END LOGIN SEED
App::set('DEFAULT_CONTROLLER', 'AppController');
if(App::get('view')){
$template_file = $cwd.'/../view/'.App::get('view').'/'.App::get('method').'.stp';
if(is_file($template_file)){
include $template_file;
}
else {
include $cwd.'/../view/missingview.stp'; //no such view error
}
}
else {
App::set('template', 'blank');
include $cwd.'/../view/missingfunction.stp'; //no such function error
}
I think you have a feeling that static is bad. What I am posting may seem fairly crazy as it is a massive change. At the very least hopefully it presents a different idea of the world.
Miško Hevery wrote static methods are a death to testability.
I like testing, so for that reason I don't use them. So, how else can we solve the problem? I like to solve it using what I think is a type of dependency injection. Martin Fowler has a good but complicated article on it here.
For each object at construction I pass the objects that are required for them to operate. From your code I would make AppController become:
class AppController
{
protected $setup;
public function __construct(array $setup = array())
{
$setup += array('App' => NULL, 'Database' => NULL);
if (!$setup['App'] instanceof App)
{
if (NULL !== $setup['App'])
{
throw new InvalidArgumentException('Not an App.');
}
$setup['App'] = new App();
}
// Same for Database.
// Avoid doing any more in the constructor if possible.
$this->setup = $setup;
}
public function otherFunction()
{
echo $this->setup['App']->get('view');
}
}
The dependancies default to values that are most likely (your default constructions in the if statements). So, normally you don't need to pass a setup. However, when you are testing or want different functionality you can pass in mocks or different classes (that derive from the right base class). You can use interfaces as an option too.
Edit The more pure form of dependency injection involves further change. It requires that you pass always pass required objects rather than letting the class default one when the object isn't passed. I have been through a similar change in my codebase of +20K LOC. Having implemented it, I see many benefits to going the whole way. Objects encapsulation is greatly improved. It makes you feel like you have real objects rather than every bit of code relying on something else.
Throwing exceptions when you don't inject all of the dependencies causes you to fix things quickly. With a good system wide exception handler set with set_exception_handler in some bootstrap code you will easily see your exceptions and can fix each one quickly. The code then becomes simpler in the AppController with the check in the constructor becoming:
if (!$setup['App'] instanceof App)
{
throw new InvalidArgumentException('Not an App.');
}
With every class you then write all objects would be constructed upon initialisation. Also, with each construction of an object you would pass down the dependencies that are required (or let the default ones you provide) be instantiated. (You will notice when you forget to do this because you will have to rewrite your code to take out dependencies before you can test it.)
It seems like a lot of work, but the classes reflect the real world closer and testing becomes a breeze. You can also see the dependencies you have in your code easily in the constructor.
Well, if it was me, I would have the end goal of injecting the App dependency into any class (or class tree) that needs it. That way in testing or reusing the code you can inject whatever you want.
Note I said reuse there. That's because it's hard to re-use code that has static calls in it. That's because it's tied to the global state so you can't really "change" the state for a subrequest (or whatever you want to do).
Now, on to the question at hand. It appears that you have a legacy codebase, which will complicate things. The way I would approach it is as follows:
Create a non-static version of the app class (name it something different for now) that does nothing but proxy its get/set calls to the real app class. So, for example:
class AppProxy {
public function set($value) {
return App::set($value);
}
}
For now, all it has to do is proxy. Once we finish getting all the code talking to the proxy instead of the static app, we'll make it actually function. But until then, this will keep the application running. That way you can take your time implementing these steps and don't need to do it all in one big sweep.
Pick a main class (one that does a lot for the application, or is important) that you easily control the instantiation of. Preferably one that you instantiate in only one place (in the bootstrap is the easiest). Change that class to use Dependency Injection via the constructor to get the "appproxy".
a. Test this!
Pick another class tree to work on, based on what you think will be most important and easiest.
a. Test!!!
If you have more calls to App::, Go to #3
Change the existing App class to be non-static.
a. Test!!!!!!!!!!
Remove the AppProxy and replace with App in the dependency injectors. If you did it right, you should only have one place to change to make this switch.
Pat yourself on the back and go get a drink, cause you're done.
The reason that I segmented it out like this is that once a step is completed (any step), you can still ship working software. So this conversion could take literally months (depending on the size of your codebase) without interrupting business as usual...
Now, once you're done, you do get some significant benefits:
Easy to test since you can just create a new App object to inject (or mock it as needed).
Side effects are easier to see since the App object is required wherever it could be changed.
It's easier to componentize libraries this way since their side effects are localized/
It's easier to override (polymorphism) the core app class if it's injected than if it's static.
I could go on, but I think it's pretty easy to find resources on why statics are generally bad. So that's the approach I would use to migrate away from a static class to an instance...
If you don't want to have static functions but global access from everywhere WITHOUT passing the object to the places where it is actually needed then you pretty much can only use one thing:
A global variable
So you are not really better of doing that. But that is the only thing i can think of that would fulfill your requirements.
If you App object is something like an application config a first possible step would be to pass it to the objects that need it:
class Login {
public function __construct() {
$this->_login_seed = App::get('LOGIN_SEED');
self::$_ms = Database::getConnection();
}
changes into:
class Login {
public function __construct(App $app) {
$this->_login_seed = $app->get('LOGIN_SEED');
self::$_ms = Database::getConnection();
}
I have a class called "Layout" for the layout of the page, another class called "User" for the user.
Every page I create, I instantiate a new Layout.
When a user logs in, there is a new User instantiated.
How do I get an instance of the layout class to know about the instantiated user? I could also save the entire instance of the User in a session variable. I assume that's a bad idea though. What are the best practices for this?
class User
{
var $userid;
var $email;
var $username;
function User($user)
{
$this->userid = $this->getUid($user);
$this->email = $this->getEmail($user);
$this->username = $user;
}
function getUid($u)
{
...
}
function getEmail($u)
{
...
}
}
class Layout
{
var $var1;
var $var2;
var $var3;
function Layout()
{
//defaults...
}
function function1()
{
echo "something";
}
function function2()
{
echo "some other stuff";
}
function function3()
{
echo "something else";
}
}
so in index.php, for example, i would do the following:
include "user.php"
include "layout.php"
$homelayout = new Layout();
$homelayout->function1();
$homelayout->function2();
$homelayout->function3();
now let's say that in login.php someone logged in:
include "layout.php"
include "user.php"
if(userAuthSuccess)
{
$currentUser = new User($_POST['username']);
}
what is the best way to gain access to $currentUser and it's member variables such as $currentUser->email, etc. from all php files from here on out, as long as the user hasn't logged out?
I think the best remedy to the solution stated above is going for a concept called Dependency Injection, whereby you write an extra class, that will inject the dependency (An Object in this case) to the requesting class. Most of the modern developers will adhere to using this technique of injecting dependencies into their applications as this will enable:
Loosely coupled programs - As the dependency is injected by a third class, there is no need to hard code the dependency in the logic of the program.
Maintainable code - This is that feature of the OOP paradigm that allures the most. This is especially true when referring to large scale programs.
Memory Management - As a developer, you are free to manage the memory to your specification requirements.
Since there will be only one User for every request and thus for every run of your program, this would be a case to make "User" a Singleton class as described here:
http://php.net/manual/en/language.oop5.patterns.php
That would provide the one way for other classes to refer to the current user without the chance of accessing the wrong instance since there is only one.
DISCLAIMER:
Yes, I know that Singeltons are often used at the wrong places for the wrong purpose and some people tend to blame this problem on the pattern instead of the people who misused it for some smelly code.
This however is a perfectly good use case for the Singelton pattern.
"Globalizing" something by putting it in a session variable or cookie for the sole purpose of globalizing it is a very bad habit to get into, and it leads to tightly coupled libraries that rely on an arbitrary variable being set outside the class. Session variables in general are good to stay away from for other reasons, too.
The best way to get a variable into any class is to pass it as an argument. Do you have a method in your Layout class that renders (outputs) it? You may want to add a $data argument to that method that takes an associative array of data usable in the layout.
I'd personally use a registry class (Singleton) and register the user there for the Layout to access. That way, you only need to pass an instance of the registry to the Layout.
The User class is not integral to the Layout's construction - since it should only be concerned with the Layout, so I wouldn't pass that in the constructor.
Another method would be to use a Controller to orchestrate these interactions between Views and Models. Whenever a new Controller is created, buffer it's output. Then, at render time, unbuffer the contents and assign them to properties (or a property array) of the view, which can then render them. You probably don't need an actual Model class to be passed to the View/Layout - just it's output.
Use a registry pattern. No need to make it a singleton, everyone is throwing that word around.
include "layout.php"
include "user.php"
if(userAuthSuccess)
{
$data['currentUser'] = new User($_POST['username']);
}
$data['nav'] = new nav('home');
$homelayout = new Layout( $data );
Now $homelayout can access $data (which contains all the variables you put into it) via the data array.