PHP Object Oriented Web Application - php

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.

Related

What is the best way to use many different instances of objects insider another PHP class?

I have a class called Page, which loads a PHP file for the current page, containing all the HTML (template file). In my template file, I want to use instances of other objects, that is initialized outside the Page class (ex. User, PDO or other classes). My problem is, how I do this the smartest way.
In my page class i have a method called get_page() which loads my template file (containing all the code for my GUI.
public function get_page() {
// Load theme template
...
$template_file = ABSPATH_THEME . 'tpl.' . $result['template_file'] . '.php';
if(file_exists($template_file)) {
$page = require_once($template_file);
return $page;
}
}
As you see the template file are loaded inside my Page class, and therefore will it not access instances of classes initialized outside my Page class.
I can come up with different solutions:
1) I pass all instances of the different classes to my class Page, when constructing my page. I think this is the right way, but can be very complex if I need 5, 10 or 20 different objects in my design.
2) Find a way to include the template file outside the Page class, but triggered from the get_page() function - have no clue how to do this, and if it is a good solution?
Can you please tell me what is best, and if there are some better ways to do it?
You can just include classes on the top of your php
eg. /CLASSPATH/ClassName.php
And then you can create an entity for that class once and use it everywhere
eg. $entity = new ClassName();
I think your best bet will be to pass them in as arguments, depending on what you need you may want to make them properties.
Edit: This is assuming that by "using instances of other objects" you mean that you need to use objects that have already been instantiated elsewhere.
If by "istances of other classes" you mean other generical objects (you mention PDO and user which are goos examples of this) I would store these in the $_SESSION array (or in $_GLOBAL array, $_SESSION being the best option in most cases).
Then you can access them just by using $_SESSION['PDO']->... and the like
One of the most popular method to handle php application rooting is to implement MVC design patern, or use an MVC Framework. Google 'MVC php' for details, good luck.
Take a look at the functions get_defined_vars and extract. Using these you can export variables from one scope to another.
A silly example could be: A function A transfer locally defined variable to a function B.
function A()
{
$var1 = "1";
$var2 = "2";
// etc
$data = get_defined_vars();
B($data);
}
function B($data)
{
extract($data);
// somescript.php can use $var1, $var2, etc if B is call from A.
require("somescript.php");
}
A();
The best practice is to use a ServiceLocator or an InversionOfControll-Container to retrieve class instances without violation of DI-Principle. For your template file you can create view helper objects to have direct access to other objects.

How to build a PHP Dependency Injection Container

I've recently learned about the advantages of using Dependency Injection (DI) in my PHP application. However, I'm still unsure how to create my container for the dependencies, or whether I should be using DI at all for the online forum that I'm building.
The following code is my version of the DI container I have made based on the example I learned from here .
class ioc {
var $db;
var $session;
var $user_id;
static function newUser(static::$db, static::$user_id) {
$user = new User($db, $user_id);
return $user;
}
static function newLogin(static::$db, static::$session) {
$login = new Login($db, $session);
return $login;
}
}
$user = ioc::newUser();
$login = ioc::newLogin();
I have a few questions:
1) Where should I instantiate my injected dependencies, such as $database, $session, etc? Would it be outside the container class, or inside the container's constructor.
2) What if I need to create a multiple instances of the User class inside other classes? I can't inject the previously instantiated $user object because that instance is already being used. However, creating the multiple User instances inside of another class would violate the rules of DI. For example:
class Users {
function __construct($db, $user_id) {
$this->db = $db;
$this->user_id = $user_id;
}
function create_friends_list() {
$st = $this->$db->prepare("SELECT user_id FROM friends WHERE user_id = $this->user_id");
$st->execute();
while($row = $st->fetch()) {
$friend = ioc::newUser($row['user_id']);
$friend->get_user_name();
$friend->get_profile_picture();
}
}
}
3) I'm wondering if I should even adopt DI, knowing that I have to rewrite all of my previous code. I've previously been relying on global variables that I instantiate in my initialize.php, which is included in all my files.
It seems to me that DI creates a lot of overhead and there are situations where it is unusable (as in my #2 example). The following site is from a developer who cites many good reasons not to use DI. Does his arguments have any merit? Or am I just using DI wrong?
check this link.
Where should I instantiate my injected dependencies, such as $database, $session, etc? Would it be outside the container class, or inside the container's constructor.
Ideally your database connection and session would be bootstrapped in. Proper DI requires an instance of a base object for which everything is registered into. So taking your IOC class as an example you need to make an instance of it ($ioc = new IOC();) then you need some kind of service provider class say
$ioc->register('database', new DatabaseServiceProvider($host, $user, $pass))
Now every time you want a connection to the database you just need to pass in $ioc->get('database'); a very rough example but I think you can see the idea is basically to store everything inside a registry and nothing is statically binded meaning you can create another instance of $ioc with totally different settings making it easy to create connections to say a different database for testing purposes.
What if I need to create a multiple instances of the User class inside other classes? I can't inject the previously instantiated $user object because that instance is already being used. However, creating the multiple User instances inside of another class would violate the rules of DI.
This is a common issue and there are multiple different solutions. Firstly your DI should show the difference between logged in user and just a user. You would probably want to register your logged in user but not just any user. make your user class just normal and use
$ioc->register('login-user', User::fetch($ioc->get('database'), $user_id));
so now $ioc->get('login-user') returns your logged in user. You can then use User->fetchAll($ioc->get('database')); to get all your users.
I'm wondering if I should even adopt DI, knowing that I have to rewrite all of my previous code. I've previously been relying on global variables that I instantiate in my initialize.php, which is included in all my files.
If you need to rewrite all your code to use DI you shouldn't probably do it. Maybe look into making a new project and work in some of your old code if you have the time. If your codebase is large I would recommend looking into breaking it down into smaller projects and using RESTFUL apis for getting and saving data. Good examples of writing APIs would be for putting your forum search into its own application /search/name?partial-name=bob would return all users with the word bob in it. you could build it up and make it better over time and use it in your main forum
I hope you understand my answers but if you need any more info let me know.
I was going to write this a comment, but it grew too long. I am not an expert so I will just give my point of view from what I've learned through few years practicing and here in SO. Feel free to use or question any part of my answer (or none).
1.- Outside. What does the container do? The answer should be a single thing. It shouldn't have to be responsible to initialize the classes, connect to the database, handle the session and other things. Each class does one thing only.
class ioc
{
public $db;
// Only pass here the things that the class REALLY needs
static public function set($var, $val)
{
return $this->$var = $val;
}
static function newDB($user, $pass)
{
return new PDO('mysql:host=localhost;dbname=test', $user, $pass);
}
static function newUser($user_id)
{
return new User($db, $user_id);
}
static function newLogin($session)
{
return new Login($this->db, $session);
}
}
if (ioc::set('db',ioc::newDB($user, $pass)))
{
$user = ioc::newUser($user_id);
$login = ioc::newLogin($session);
}
2.- You shouldn't do $friend = ioc::newUser($row['user_id']); inside your class. There you are assuming that there's a class called ioc with a method called newUser(), while each class should be able to act on it's own, not based on [possibly] other existing classes. This is called tight coupling. Basically, that's why you shouldn't use global variables either. Anything used within a class should be passed to it, not assumed in the global scope. Even if you know it's there and your code works, it makes the class not reusable for other projects and much harder to test. I will not extend myself (PUN?) but put a great video I discovered here in SO so you can dig more: The Clean Code Talks - Don't Look For Things.
I'm not sure about how the class User behaves, but this is how I'd do it (not necessary right):
// Allow me to change the name to Friends to avoid confusions
class Friends
{
function __construct($db)
{
$this->db = $db;
}
function create_friends_list($user_id)
{
if (!empty(id))
{
// Protect it from injection if your $user_id MIGHT come from a $_POST or whatever
$st = $this->$db->prepare("SELECT user_id FROM friends WHERE user_id = ?");
$st->execute(array($user_id));
$AllData = $st->fetchAll()
return $AllData;
}
else return null;
}
// Pass the $friend object
function get_friend_data($friend)
{
$FriendData = array ('Name' => $friend->get_user_name(), 'Picture' => $friend->get_profile_picture());
return $FriendData;
}
}
$User = ioc::newUser($user_id);
$Friends = new Friends($db);
$AllFriendsIDs = array();
if ($AllFriendsIDs = $Friends->create_friends_list($User->get('user_id')))
foreach ($AllFriendsIDs as $Friend)
{
// OPTION 1. Return the name, id and whatever in an array for the user object passed.
$FriendData = $Friends->get_friend_data(ioc::newUser($Friend['user_id']));
// Do anything you want with $FriendData
// OPTION 2. Ditch the get_friend_data and work with it here directly. You're already in a loop.
// Create the object (User) Friend.
$Friend = ioc::newUser($Friend['user_id']);
$Friend->get_user_name();
$Friend->get_profile_picture();
}
I didn't test it, so it has probably some small bugs.
3.- If you are learning while coding, you will have to rewrite MANY things. Try to do somethings right from the beginning so you don't need to rewrite everything, but only the classes/methods and adopting some conventions for all your code. For example, never echo from within the function/method, always return and echo from outside. I'd say that yes, it's worth it. It's bad that you have to loose 1 or 2 hours just rewriting something, but if it has to be done, do it.
PS, sorry, I changed your bracket style everywhere.
EDIT
Reading other answers, while you shouldn't connect to the database with your ioc object, it should be perfeclty fine create a new object with it. Edited above to see what I mean.
Instead of globals in your init.php define your objects like:
ioc::register('user', function() {
return new User();
});
And inisde your create_friends_list method use:
ioc::get('user')->newUser($user_id);
This is a really plain implementation. Check out:
http://net.tutsplus.com/tutorials/php/dependency-injection-huh/?search_index=2
or
http://net.tutsplus.com/tutorials/php/dependency-injection-in-php/?search_index=1
for more information.
The question you asked has one very important catch, which I asked about in a comment. Any time you examine the possibility of pausing forward progress in order to go back and accomplish a less than trivial re-factoring of existing classes, you have to really think about the payoff.
You replied:
It seems a bit complex (and very different) and more work than it's worth to implement at this point. I'm just trying to hack out something real quick and see if it gains traction.
Remember that you have the following things to do if you want to implement an DI with an IoC container properly:
Implement the IoC container and registry at bootstrap
Modify all existing classes that have dependencies to allow setter injection, while not depending on the IoC container itself
Re-writing / Re-structuring of your tests as needed
A note on the second bullet which reflects my own personal view and preference, developing with DI in mind can be hard and you want the full reward it can give. One of the biggest rewards is completely decoupled objects, you don't get the complete part of that if everything still depends on an IoC container.
That's a lot of work, especially if you haven't been considering the pattern until now. Sure, you'll have clear benefits, such as lots of re-usable and easily testable objects when you're done. But, as with all re-factoring, nothing new would be accomplished in the context of adding or finishing new functionality and features. Is difficulty testing or tight coupling getting in the way of that? That's something you'd have to weigh.
What I suggest you do instead is keep the pattern in mind as you write new code. Provide setter methods to inject dependencies, which can be utilized manually or through an IoC container. However, have your classes continue to create them just in time if none have been injected and avoid composition in a constructor.
At that point you'll have a collection of classes that lend much better to inversion of control, if that's a pattern you want to pursue in the future. If it works well for you and it's something you really want to incorporate into your design decisions, you can easily re-factor to remove the JIT logic later.
In conclusion, I'm afraid that the only thing you'll end up with if you try implementing it completely, and properly right now is a mess. You can change how you write classes now going forward, but I wouldn't go back and try to implement it across the board.

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

Should I remove static function from my code?

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();
}

PHP - Where is the best place to initiate a database class?

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.

Categories