Can Anyone Explain What "dependency Injection " In Layman's Terms ?

Discussion in 'PHP' started by eritrea1, Feb 15, 2013.

  1. #1
    I looked up some sites on What dependency injection is, unfortunately none were able to give me something equivalently, you can understand as in the case of... sql injection.

    Usually, I only declare the connection resource as global
    $conn = new PDO('mysql:host=localhost;dbname=dbb', 'root', 'test');
    Code (markup):
    And I call the object from inside my methods
    
     
     
    class Counter{
       function RowCounter($row){
           global $conn;
           $stmt = $conn->prepare('SELECT * FROM name');
       }
    }
     
    
    Code (markup):
    Now I fail to understand in simple terms how using the above method or even sending the connection object inside a function argument is in any way bad at all.


    Is there any simple and clear answer to this one, and how It should be achieved? thanks!
     
    eritrea1, Feb 15, 2013 IP
  2. deathshadow

    deathshadow Acclaimed Member

    Messages:
    9,732
    Likes Received:
    1,999
    Best Answers:
    253
    Trophy Points:
    515
    #2
    In the simplest of terms, it just means making a property of the object that's a reference to something the object needs... This can be done by having said object initialize an instance of another object itself... or by passing the object said value on startup.

    In PHP this is a REALLY good idea because it can be used to narrow the scope from which something like, well... let's use your example. The database connection in your example code is GLOBAL -- that means any code, anywhere, at any time can access it. Being a scripting language one of the most common attacks is a 'code elevation' -- tricking some code sent as user data or as a user upload into being run as part of the system. While elevations can be avoided by not dynamically including files, sanitizing values used to dynamically include files, and not using functions like eval(), there are no guarantees you won't miss something.

    Let's say your counter class instead of grabbing conn from the global scope made a copy by reference:

    class Counter{
    
    	private $db;
    	
    	function __construct($db) {
    		$this->db = $db;
    	}
    	
      function RowCounter($row) {
    		$stmt = $this->db->prepare('SELECT * FROM name');
    	}
    
    }
    Code (markup):
    It's 'copy' of the database connection is only available to itself inside it's own scope... If you then had a startup function:

    function main() {
    	$db = new PDO('mysql:host=localhost;dbname=dbb', 'root', 'test');
    	$counter = new counter($db);
    	// initialize any other objects that need the database connection here
    }
    Code (markup):
    The database connection is local to main and local to the object -- meaning any code run outside that function or outside the authorized object cannot access the database. This limits the number of places a code elevation hack could gain access to the database.

    I use this method in a lot of the code I write -- even when using singletons having a connect($db) method restricts the scope, reducing the odds of a code elevation doing anything nasty to the database and instead only allowing what operations you give to the class.

    Much of this I talk about in an article I wrote on another site recently:
    http://techtalkin.com/Thread-Securing-your-PHP-taking-it-further-than-most

    Putting your connection in global scope is about as dangerous as putting the hostname, username or password in global scope. (or even worse, DEFINE's like wordpress does). It should be declared in a local scope, and passed only to those elements that should be allowed access to it.

    -- edit --

    Oh, a similar vulnerability in PHP is that when you include/require a file, it is treated just like a cut/paste into the location you call it from -- this means that any local variables or properties are passed to that file; basically if you include from inside a function or object, it's variables or properties might as well be globals... not the most secure situation.

    The fix is really stupid, but it works:

    function safeInclude($fileName) { include($fileName); }

    Passing to a new function breaks the current scope, so if you are doing a non-static path include (like say, multiple themes, request based libraries, etc) the current scope won't be passed to the load.
     
    deathshadow, Feb 15, 2013 IP