Because I noticed it was a pattern I was constantly re-implementing, I made a DataContainer class that overrides __set,__get,__isset,__unset, and implements ArrayAccess, Countable, IteratorAggregate, and Serializable
For example, my View class, which renders PHP templates in an MVC fashion, inherits from DataContainer so that it has overloaded access to the data that gets supplied to the template.
Now, I am finding myself wanting to create a Session class to abstract away from PHP's low-level session handling. It occured to me that this Session class would do just about everything DataContainer does, and in fact, is-a DataContainer - it holds data.
However, if I inherit from DataContainer, then all the overloaded calls go to its private $_data array. Of course, I can override DataContainer's public get($key), public set($key,$val), etc methods, but the only thing I would be doing is renaming $this->_data to $_SESSION.
Is it possible to set a variable as a reference to a special global like $_SESSION?
class Session extends DataContainer {
//singleton stuff
private function __construct() {
$this->_data =& $_SESSION;
}
}
Is it even a good idea to do this? If not, what do you suggest?
Is it possible to set a variable as a
reference to a special global like
$_SESSION?
Yes, $this->_data =& $_SESSION;
Is it even a good idea to do this?
I don't see why not, one could argue that it may be better to pass the data in to the constructor by reference so that it can be used for any array not just session.
Thus, Yes.
edit: as a side point, remember you don't always have a session, sometimes your running on cli etc, personally I have my own session object (just a DataContainer like yours) which I then persist to $_SESSION where needed, or file or.. - ie I save (stateful) session objects in the $_SESSION rather than use the $_SESSION as the session data, if that makes sense..
I sure hope it's good idea, as I use it constantly. Kind of a Decorator, only for a variable-container. Yes, it has worked for for about 3 years now, and I very much like the validating & tracing capabilities it yields on more complex projects. Keep in mind you cannot force any other code to use the container instead of $_SESSION, but a project wide search for that particular string yields fast results when the majority of the code uses other means.
I also make it a Singleton for those moments a projects is not suited for a proper dependancy-injection path, either for size, time or historical reasons. Referencing a Session::instance() is about as easy as the $_SESSION superglobal.
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 have been wondering for a while already how does static variables work regarding memory use and should that even be really considered?
I understand that static variables will only use up one area of memory, doesn't matter how many instances there are of the class itself. So in this sense, it should be wise to use static variables for wise memory consumption too, right? But I've never stumbled across anyone talking about the memory usage of static variables (only that you can share the data with different instances).
For example:
class Something () {
static $DB = null;
__construct ($DB) {
$this->DB = $DB;
}
}
If I would create 10 instances of this class, then it would generate less memory usage, than with non-static $DB-variable, right?
And if it is so, is the effect so small, it doesn't really matter?
and should that even be really considered?
No you shouldn't worry about statics for that reason.
The reason you have to worry about the use of static is the fact that you cannot unit test your code anymore and you have tightly coupled classes and code to Something::DB (i.e. the Something class) and you are working with global state.
Also check out an previous answer by me about how to handle those "global" instances: Which is the best practice to access config inside a function?
In your case, please, rethink your software design. In case of using static variables - you are trying (if its not, so why you need static?) to make something accessible from one place, without recreating it, like using Singleton pattern for making single instance of db object.
But if we are talking about memory usage, so yes, if you will create more objects, so you duplicating the variables - it will take more memory, but there are no real change in memory usage about its static or not.
Yes, a static attribute of a class would be stored in a single instance of memory.
But, that is not a concern in making a decision in having a variable as static. They are used for class level information such as to keep a count of the instances of a class.
Go through the following Stackoverflow post on when to use static variables:
When do I use static variables/functions in php?
You should use
self::$DB
to access static variables (as $this has no meaning in a class wide context)
Should use static for something that all objects of that class share.
You should not use parameters from the constructor to create static variables. Doing so the static variable gets overwritten when you create a new object of that type
I just started to learn object oriented programming today and just by observation noticed that in all examples, member variables are private. Why is that usually the case?
// Class
class Building {
// Object variables/properties
private $number_of_floors = 5; // These buildings have 5 floors
private $color;
// Class constructor
public function __construct($paint) {
$this->color = $paint;
}
public function describe() {
printf('This building has %d floors. It is %s in color.',
$this->number_of_floors,
$this->color
);
}
}
Also, if you declare the member variable to be public, what is the syntax for accessing it outside of the class it was declared in?
And finally, do you have to prepend "public" or "private" to every variable and function inside a class?
EDIT: Thanks all for your answers, can anyone please confirm if you have to prepend "public" or "private" to every variable and function inside a class?
Thanks!
Rule of thumb is to try to hide information as much as possible, sharing it only when absolutely necessary.
Russian coders sometimes say Public Morozov at unnecessarily wide access modifiers, alluding to a story about improper information disclosure and about further punishment caused by that - Pavlik Morozov:
a 13-year old boy who denounced his father to the authorities and was in turn killed by his family...
Private variables can't be accessed from outside, that gives you control.
But if you put them Public then you can access it lke this
$your_object_instance->Your_variable
For example
$building = new Building();
echo $building->number_of_floors;
but you have to put your number_of_floors variable to public, if you want to access private member then you need to implement new method in Building class
public function getNumberOfFloors()
{
return $this->number_of_floors;
}
so your code should look like this
$building = new Building();
echo $building->getNumberofFloors();
It's to make the coding easier for you, and to make you less likely to make mistakes. The idea is that only the class can access its private variables, so no other classes elsewhere in your code can interfere and mess something up by changing the private variables in unexpected ways. Writing code like this, with a bunch of autonomous classes interacting through a small number of strictly controlled public methods, seems to be an easier way to code. Big projects are much easier to understand because they are broken up into bite sized chunks.
Making variables private keeps calling code from depending on the implementation details of your class so you can change the implementation afterward without breaking the calling code.
You can declare more than one variable on the same line and only use private or public once:
private $number_of_floors = 5, $color;
See also PHP docs' "Classes and Objects".
Senad's answer is correct in that it is good programming practice to make variables you do not want exterior methods to access private.
However, the reasoning for it in memory managed/garbage collected languages is that when you maintain a reference to an object, it is not able to be garbage collected, and can cause memory leaks.
Hope this helps!
I really dont know how to answer such question, but i describe u the best as per php manual
The visibility of a property or method can be defined by prefixing the
declaration with the keywords public, protected or private. Class
members declared public can be accessed everywhere. Members declared
protected can be accessed only within the class itself and by
inherited and parent classes. Members declared as private may only be
accessed by the class that defines the member.
Property Visibility
Class properties must be defined as public, private, or protected. If
declared using var, the property will be defined as public.
Methods declared without any explicit visibility keyword are defined as public.
for more information see Visibility
It's to prevent properties from being directly manipulated from the outside and possibly putting the object into an inconsistent state.
One of the fundamentals of OOP is that an object should be responsible for maintaining its own state and keeping it internally consistant, for example not allowing a property that's only meant to hold positive integers from being set to -343.239 or making sure an internal array is structured properly. A sure fire way of doing this is make it impossible for the values of properties to be directly set from the outside. By making the property private, you're preventing outside code from manipulating it directly, forcing it to go through a setter method that you have written for the job. This setter can do checks that the proposed change won't put the object into an inconsistent state and prevent any changes that would.
Most books and examples aimed at beginners tend to use very simple objects so it may not make sense as to why you need to go through all the private properties and getters and setters molarchy, but as the complexity of an object increases, the benefits become increasingly obvious. Unfortunately, complex objects are also not much good as teaching aids for beginners, so this point can be easily lost at first.
In OOP, is it better to use class attributes within class functions, or just pass parameters to them.
class User{
private $user = array();
public function Get_Existing_User($user_id){
//SQL selects user info for existing user
$this->user = mysqli_fetch_assoc();
}
public function Set_User($user_data){
$this->user = (array) $user_data;
}
public function Add_User(){
//insert everything from $this->user into database
}
public function Get_User(){
return $this->user;
}
}
VS
class User{
public function Get_Existing_User($user_id){
//SQL selects user info for existing user
$user = mysqli_fetch_assoc();
return $user;
}
public function Add_User($user_data){
//insert everything from $user_data into database
}
}
Whats the better way to go?
Between your solutions, first is better, but you have to change the names of the functions. 'get' should be used only if function returns something.
The reason it is better is that it doesn't use side effects, side effects always bad as they are invisible to user of the class but change class behavior. So you should try to minimize them or make them obvious as they are in the first case, when they not really 'side'.
But in this particular case, Get_Existing_User and Add_User should be static functions, that return new User object, it is sometimes called as static constructor. The reason why it is much better is that it makes it clear what that functions do, they get something as parameter (user_id of existing user or first_name, last_name and other attributes for a new user) and create an object that represents the user. All database manipulation will be hidden away. Object itself should have properties for name and other attributes and even Save() method to push the changes back. But main idea is that you always work with constructed object, object that already have context and linked to something in the real world (that is, user in the database), not an empty shell that will be filled in as you go.
Some clarification on terminology first:
What you call class functions are more properly called methods. A method is a function on an object instance. Additionally, classes may have methods. These are called class methods or static methods. When you use the term class function, you are thus confusing the meaning.
That settled, there is no worse or better of the two approaches. You would use both, depending on the context. Parameters have a smaller scope, and thus cause less coupling. If everything else is the same, I would therefore say that parameters are preferable to setting an object property.
That said, there are usually other factors that can determine which to pick. You can think of an object as a scope for related variables. If a variable belongs to that scope, it would make sense to assign it to a property.
Class attributes are expected to describe the state of an instance of the class known as an object. As such, the attributes can be used by any function of the class to modify it's state. Function parameters on the other hand may have nothing to do with the current state of the object but can be used to modify it's state.
For example: a user object could be expected to have a user name attribute, a password attribute, and an authenticated attribute. this user object also has a function called authenticate that takes a parameter which describes an authentication method. The parameter is used to modify the state of the user object but would not be held as an attribute of it.
That entirely depends on wether you're going to re-use the data and how you're using the Class.
If you create many individual instances of the Class and each Object represents a unique user, it makes sense to persist the data in a member variable. If you're using the Class as a DAO (data access object) with a lot of one-off operations, it probably doesn't make a lot of sense to persist the data. But even in a DAO, depending on its inner workings, it might make sense to store the data at least temporarily in a member variable if there are many functions involved in a single call (like beforeQuery and afterQuery callbacks or the like).
There's no one-better-way-fits-it-all.
It is important that you choose the method that best suits your situation. Ignoring that not-so-helpful suggestion I encourage you to take a good look at some important principles in Object Oriented Design
Coupling
Cohesion
A strong understanding of these topics will help you assess your situation and code to suit the goals of the project. As your project grows, you'll likely find that you'll want to use methods that have optional parameters to interact with your objects to achieve high cohesion and loose coupling. Then you'll use methods and parameters like an expert.
I recently took my Db initiating code out of the __construct of my Page class and placed it just after I initiate the Page class. I removed it from within the Page class because I want to be able to access it from anywhere (other classes for example). It also takes server, username, password and database arguments to it when initiated, and I don't wish to enter these every time.
Is there a way I can access it from under the Page class now? I've tried a few methods, even global (which I have been told is an awful way to do things) and so far no avail. I am still new to OO, but I am teaching myself as best as I can.
Should I make it a static class? Will this affect the lazy connector to the Db I have setup?
Any help would be much appreciated.
Thank you
[EDIT]
Similar Question: Global or Singleton for database connection?
A global of some sort (Be that global variables, singleton or some other variant) is an improvement over your previous approach, and as such you're on the right track. Generally speaking though, you should try to minimise the scope of program state (For a number of reasons, which I won't get into here). Having a global variable is in conflict with this principle. There are different solutions to this problem, but the most powerful and often overlooked approach, is to use inversion of control; Instead of obtaining a dependency, your class should receive it. For example, let's say you currently have this
class EditUserController {
function saveUser() {
$db = Database::GetInstance();
$db->execute("update users set ...", ...);
}
}
You could change this into:
class EditUserController {
function saveUser($db) {
$db->execute("update users set ...", ...);
}
}
Passing dependencies on the function-parameter level can be a bit unwieldy though, so a compromise could be to pass it on a per-object level:
class EditUserController {
protected $db;
function __construct($db) {
$this->db = $db;
}
function saveUser() {
$this->db->execute("update users set ...", ...);
}
}
This is a fairly common pattern in OO programming. In addition to being more practical than passing in function parameters, it has the additional benefit of separating construction (Where shared dependencies are wired up to each other), from runtime (Where they are used). This makes a lot of things simpler.
Global variables do have a use, and this would be one of them. Unless it's likely that you're going to be needing multiple database connections, (or even still), then I don't see a problem with setting up a global $db object.
An alternative way is to have a static "Factory" class which you can use to get the object. In Joomla 1.5, the way you access the DB object is like this:
$db =& JFactory::getDBO();
the getDBO function checks if the DB object has been created: if it has, return a reference to it, otherwise connect and initialise, and then return it.
This could equally apply to other "could-be-made-global" objects, like the current User object.
The singleton method was created to make sure there was only one instance of any class. But, because people use it as a way to shortcut globalizing, it becomes known as lazy and/or bad programming.