I'm creating a web app in PHP5. So far, I have two "global" variables: $input and $sql. $input is the validated and sanitized input from $_GET, $_POST and $_COOKIE. $sql is an instance of my mysql(i) class.
These two are needed in almost every other class. This could be relatively easily achieved by passing them as parameters to the __construct function of each class. But that seems ... clumsy. Along with more class specific parameters and potential future global vars, it makes for unwieldy function calls.
The easy and, as I understand it, noobie alternative would be using the global keyword. I don't want to do that. I get the downsides of globals, although in my scenario (small app) they wouldn't matter much. But it's also clumsy to explicitely label them global before using them again.
A more elegant way I suppose: I have a webapp class from which I extend all other classes. This webapp class holds common functions I need in more than one other class but that do not warrant for a seperate class.
If I store $input and $sql as static variables in this webapp master class, they'd be accessible in all subclasses.
But I understand that static variables are as much frowned upon, if not more, than global variables.
Is that true?
I guess I'm one of these people who overthink everything, but I like elegant code and this looks elegant to my (amateur) eyes.
So far, I have two "global" variables
Yuck! Globals are bad. :-)
$input is the validated and sanitized input from $_GET, $_POST and $_COOKIE
Why do you make that global. Simply sanitize / normalize / whatever when you really are going to use it.
$sql is an instance of my mysql(i) class.
Again: no need to make that global. Use dependency injection.
The easy and, as I understand it, noobie alternative would be using the global keyword. I don't want to do that.
You are right: you don't want to do that.
A more elegant way I suppose: I have a webapp class from which I extend all other classes.
That also doesn't sound really correct. A class has a specific function (/ responsibility).
But I understand that static variables are as much frowned upon
Static stuff are just globals with a different name.
If you do want to make your life easier you could implement a dependency injection container.
http://php.net/manual/en/language.oop5.patterns.php
This link describes the singleton pattern which is the oo-way which provides a single global instance of a class. I'm sure this is elegant enough seeing you will otherwise being subclassing for the sake of subclassing, and not requiring them to pass as a parameter.
This is what i would do :)
Personally I would employ the singleton in this example. Singletons can be frowned upon however when used in the right situation they are perfectly fine.
I would create your "WebApp" class as a singleton, this means where ever you need those variables you simple access the "WebApp".
If you have never used a singletone before, here is an example:
class WebApp
{
private static $instance = null;
private $post_data = array();
private function WebApp(){}
public static function instance(){
if(!isset(WebApp::$instance))
WebApp::$instance = new WebApp();
return WebApp::$instance;
}
}
print_r(WebApp::instance()->post_data);
Related
I am having a hard time finding an answer to this, I am sure it's there in front of me but I cant put it together.
//Global Variables
global $GLOBAL;
$GLOBAL['myPluginPath'] = dirname( __FILE__ );
//Main Object
class My_Class {
public function __construct() {
// Initialize Settings
require_once $GLOBAL['myPluginPath'] . '/settings.php';
$My_Settings = new My_Settings();
}
}
I want to use a variable so my code feels more organized, I feel I can read my code better when paths are defined this way and it makes it easier to change the variables so that it applys throughout the whole code if needed.
I can get the variables to work by writing this inside my methods.
public function WhatEverFunc() {
global $GLOBAL
require_once $GLOBAL['myPluginPath'] . '/settings.php';
}
The primary question here, I am wondering if this is bad practice, if not is there a better way then having to define global $GLOBAL inside each method. If however it is bad practice can you show me good practice?
There is a one other thing I am really curious about. Inside the main __construct you see I don't use global $GLOBAL because it works without it, but inside that require_once file is another class which has methods that must use global $GLOBAL inside of them. Hope someone can explain that.
Some are saying this is bad practice, I think. I read there is a singleton pattern(bad practice) and a global pattern. Not sure what I did above constitutes, I am just a little lost from what I should do here with what I am trying to achieve.
An object really should have everything needed for it to perform any function it is designed to. If not, the data should be passed via a param to it.
Part of the whole point of objects versus procedural code is that objects can be re-used over and over and in many places.
Lets use this example of why using Globals and OOP is a bad idea:
Lets say you have a great front-end bit of code, and you write it all through objects. Sometime down the track, you need to create additional reporting on the data in your site. You start to code and realize that you can re-use your classes from the front to achieve almost everything you need - but alas your code contains numerous references to globals that are only visible in the front end if called from a certain script.
That's basically just made your objects rather un-reusable.
Although it's probably not the best practise, but I often write a quick class that grabs a hold of various $GET, $_POST and other variables which might be considered "Globals" such as URL params and the like, then in my code, I either pass this information directly to the objects/functions as needed or indeed pass the entire object (rarely).
Using this approach, I am always perfectly ready to re-use objects knowing EXACTLY what they need to function as they are all required in params.
Why don't you use $GLOBALS? You don't even need to use global keyword.
The primary question here, I am wondering if this is bad practice
Well, I believe most people would say having a global state is bad practice because it is harder to manage or doing unit test. Most people would suggest you to use "dependency injection" which instead of depend on global state, you need to inject what the class need directly.
From your code it seems that you're just looking for a way to resolve your class names into file names. For that purpose it's better to use auto loaders. It takes the formality of how your classes map to file names away from the bulk of your code so that you can concentrate on actual development.
Organizing your plugins can be done by using namespaces.
Second, in most cases you don't want to instantiate classes inside the constructor because it leads to coupling, and too much coupling can stifle your project later; instead, inject the dependency:
class My_Class
{
private $settings;
public function __construct(My_Settings $settings) {
$this->settings = $settings;
}
}
To call it:
$c = new My_Class(new My_Settings());
Use this example to solve your problem
The global keyword doesn't work the way you think it does. It does not make a variable have global scope. All it does is specify to the function that you call it in that you want to use the variable in the outer scope.
For example:
$a="test";
function something() {
global $a;
echo $a; //Outputs: test
}
If you want to make a variable global so that it can be accessed from within a class, you need to use the $GLOBALS superglobal.
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
Generally when creating a PHP class I would do something as such
class Foo
{
public function Foo(){}
public function RandomFunction(){};
}
global $foo;
$foo = new Foo();
$foo->RandomFunction();
I have noticed that on the web people are frowning upon the global vars for classes but without it I would not be able to access the class inside other functions.
Now an alternative to this would be using static classes as such:
class Foo
{
static public function RandomFunction(){}
}
Foo::RandomFunction();
My Question is this, is this the best alternative to global vars for classes? Or is there a better way to go about it all together?
In good OO practice, if a class needs to access an instance of another class, you pass object in as a parameter and then access it's properties and methods from there.
If you have a well designed object model the code should be relatively clean and logical, however if you aren't planning on creating a strict OO application, you probably shouldn't worry about your classes being in global scope or not.
Think of your object like a bicycle. You own your bicycle, and can loan it to whomever you wish. They can use it and return it to you, and you will be able to keep track of who did what to your bike, and when.
If your bike is generally available to anyone in the world, however, your job of monitoring and controlling access to it will become exponentially more difficult. You will be hard-pressed to keep track of who is using your bike, when they are using it, and how they are (ab)using it.
Passing your objects (rather than declaring them globally) allows you to maintain stricter controls on your object and the data it contains.
I just want to tell you that I am newbie to OOP and it is quite hard to me, but here is my code:
class functions
{
function safe_query($string)
{
$string = mysql_escape_string(htmlspecialchars($string));
return $string;
}
}
class info
{
public $text;
function infos($value)
{
echo functions::safe_query($value);
}
}
Is there any way to make this sentence : echo functions::safe_query($value); prettier? I can use extends, than I could write echo $this->safe_query($value);, but is it a best way? Thank you.
edit: and maybe I even can to not use class functions and just make separate file of functions and include that?
Yes, just define your function outside of a class definition.
function safe_query($string){
return mysql_escape_string(htmlspecialchars($string));
}
Then call it like this
safe_query($string);
Using a functional class is perfectly fine, but it may not the best way to design your application.
For instance, you might have a generic 'string' or 'data' class with static methods like this (implementation missing, obviously):
class strfunc{
public static function truncate($string, $chars);
public static function find_prefix($array);
public static function strip_prefix($string);
public static function to_slug($string); #strtolower + preg_replace
etc.
}
The point of a class like this is to provide you with a collection of generic, algorithmic solutions that you will reuse in different parts of your application. Declaring methods like these as static obviates their functional nature, and means they aren't attached to any particular set of data.
On the other hand, some behaviors, like escaping data for a query, are more specific to a particular set of data. It would probably be more appropriate to write something like this, in that case:
class db_wrapper{
public function __construct($params); #connect to db
public function escape($string);
public function query($sql);
public function get_results();
}
In this case, you can see that all of the methods are related to a database object. You might later use this object as part of another object that needs to access the database.
The essence of OOP is to keep both the data and its relevant behavior (methods) in one place, called an object. Having behavior and data in the same place makes it easier to control data by making sure that the behavior attached to the data is the only behavior allowed to change it (this is called encapsulation).
Further, having the data and behavior in one place means that you can easily pass that object (data and behavior) around to different parts of your application, increasing code reuse. This takes the form of composition and inheritance.
If you're interested in a book, The Object-Oriented Thought Process makes for a decent read. Or you can check out the free Building Skills in Object-Oriented Design from SO's S.Lott. (Tip: PHP syntax is more similar to Java than Python.)
Functions outside a class litter the global namespace, and it's an open invitation to slide back to procedural programming. Since you're moving to the OOP mindset, functions::safe_query($value); is definitely prettier (and cleaner) than a function declared outside a class. refrain from using define() too. but having a functions class that's a mix of unrelated methods isn't the best approach either.
Is there any way to make this sentence
: echo functions::safe_query($value);
prettier?
Not really. IMO having a functions class serves no purpose, simply make it a global function (if it's not part of a more logical class, such as Database) so you can do safe_query($value); instead.
and maybe I even can to not use class
functions and just make separate file
of functions and include that?
Create files for logical blocks of code, not for what type of code it is. Don't create a file for "functions", create a file for "database related code".
Starting with OOP can be a real challenge. One of the things I did was looking at how things were done in the Zend Framework. Not only read the manual (http://www.framework.zend.com/manual/en/zend.filter.input.html, but also look at the source code. It will take some effort but it pays of.
Looking at the context of your question and the code example you posted, I would advice you to look at some basic patterns, including a simple form of MVC, and the principles they are based upon.
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.