Jump to content

Building a base Class


Mahngiel

Recommended Posts

I would like to build a class that maintains several objects that I will be using regularly across other classes.  I've read a few books (several times over) and have a decent understanding on the process.  I'm failing to grasp a few issues which are killing the app. This is what I've done (borrowing tips from frameworks):

 

[*] created a loader to require the classes, open a new instance of it, and then amend it to an array of made classes.

[*] created the base class which owns a static value and method to return said value

 

That works just fine, classes all get loaded as indicated by get_declared_classes, and print_r'ing $this inside the base class.  Now, what I'm trying to figure out is how to access the base's loaded classes from the other loaded classes.  Here's some relevant code.

 

<?php
echo '<pre>';	
class Base {
/* ---------------------------*/
private static $me;	
protected $classes = array();

function __construct(  )
{
	// create reference
	self::$me =&  $this;

	// create array of loaded classes
	$this->classes =& loaded_classes();
	print_r( $this->classes );

	// create superobject, making sure each class is loaded
	foreach ($this->classes as $class)
	{
		$this->$class =& load_class($class);
	}

	print_r($this);	 	
}

public static function &get_me()
{
	return self::$me;
}
}

The dumps for this are:

Array
(
    [db] => db
    [session] => session
    [uri] => uri
    [smarty] => smarty
)
Base Object
(
    [classes:protected] => Array
        (
            [db] => db
            [session] => session
            [uri] => uri
            [smarty] => smarty
        )

    [db] => db Object
        ( ...  )

    [session] => Session Object
        ( ...  )

    [uri] => URI Object
        ( ... )

    [smarty] => Smarty Object
        ( ... )
)

 

In the session object, calling $this only provides the current scope.

<?php
class Session {
public static $session;
// ----------------------------------------------------------------------
public function __construct(  )
{
	$this->session = $_SESSION;
	$this->user = $this->get_user();
	print_r($this);
}

 

Only gives current scope

Session Object
(
    [session] => Array
        (
            [tracking] => Array
                (
                    [language_path] => /home/dev/language/english
                )
        )
    [user] => 
)

 

If I add $BASE = Base::get_me(); into the constructor of the Session class, i fatal error with 'class Base not found'.  What have I missed in order to have access to the super global with all the loaded classes?

Link to comment
Share on other sites

First, you don't need to assign by reference (=&) if you're using PHP 5+.

 

Second, this kind of thing, on the surface, looks like an exercise in coupling unrelated classes/objects together, which is a Bad Idea in OOP.  What are you actually trying to do?

Link to comment
Share on other sites

What are you actually trying to do?

 

The db, session, uri, and smarty classes are going to be used throughout the application, and all rely on each other to handle their jobs.  What I wanted to do was simplify the job of having to create new instances and passing them around depending on where the user was.

 

And example that works:

<?php
// need this first
$db = new db();

// this requires the db wrapper 
$session = new Session( $db );

$smarty = new Smarty();

$pageID = $_GET['page'];

// send requisite data to uri function to validate everything so the template can be utilized.
uri( $sesion, $smarty, $db, $pageID );

 

and instead, create a preloader that automates the process where the objects are accessible inside of the classes.

Link to comment
Share on other sites

The biggest problem, from a design aspect, is that you're trying to mesh different layers of your app into one.  The db is deep in the back end for data persistence, while routing, sessions, and smarty (especially) are a part of the presentation side.  Simply put, they shouldn't be contained by a general purpose super object.  And, really, the idea of a super object is essentially antithetical to OOP in general anyway.

 

Creating your app environment (the classes you'll need) is the job of a bootstrap, which should only be concerned with setting up/instantiating these kinds of things and not their eventual interactions.  From there, you'll need to separate your code into tiers.  One of the unfortunate things about PHP frameworks is either that they suck, or don't really illustrate how MVC is supposed to work beyond canned examples.

 

MVC is a presentational pattern.  In non-trivial apps, the M really refers to what is known as view models, which are simple DTOs (Data Transfer Objects) that contain POD (Plain Old Data) and whatever getters and setters are necessary to access it.  The DTOs do what their name infers - they transfer data from the back end to the user, and then back again.  The real brains of the app lies below MVC, in the domain, which is where the application logic actually happens.

 

MVC is really just a skin on top of a domain.  It's supposed to handle the user interaction component, but not much else.  More importantly, this means that MVC is really just the front facing layer of a non-trivial app.  Below it is the domain, and below that the DAL (Data Access Layer: domain <-> database).

 

The resistance and confusion you're experiencing is to be expected because, like I said earlier, you're trying to mash layers together.

 

All that said, if classes rely on external dependencies in order to work, that's a clear sign of needing to implement Dependency Injection.  Creating Singleton-esque classes is exactly the wrong way to go.  Here's a great link by one of the creators of Symfony that explains what DI is, and how to use it:

Link to comment
Share on other sites

I have yet to find a package by fabpot that I don't like ;)

 

Hehe, fabpot. :D

 

Yeah, everything I've seen from him/Sensiolabs looks really good.  Even Twig, and I'm not a fan of template engines.  I need to find a project to actually use Symfony on.

Link to comment
Share on other sites

Pretty much.  Remember that in PHP 5+, objects are passed by reference by default, so if you instantiate a $database object upon request, and then pass it to other objects, those secondary objects will all be using that one lone $database object.  That's one of (the many) reasons why doing the opposite - a Singleton-like super object that contains other objects - is pointless.  You don't need Godzilla in order for things to talk with one another.

 

If you've looked at some of the DI stuff me and ignace linked to, you might be thinking that a DI container is a super object.  It's not.  It's merely a mapper that says, "An object of class X depends on an object of class Y... okay, I'll link them when a new X is made."

 

It takes a little while to get used to, especially if you're trying to roll your own.  That's one of the reasons why I like to use a solid framework - DI is usually baked right in, and if not, it's usually not hard to find a separate component that can plug right in. 

 

Ultimately, it's all about setting up object requirements before you instantiate, and having the object work more or less out of the box when you call new X;

Link to comment
Share on other sites

It takes a little while to get used to, especially if you're trying to roll your own.  That's one of the reasons why I like to use a solid framework - DI is usually baked right in, and if not, it's usually not hard to find a separate component that can plug right in. 

 

I didn't want to, I'm comfortable in a framework environment where I didn't have to completely understand the mechanics, only that it worked.  It has been my introduction into the concepts as I have no formal training, just my own use study.  However, I received a project written over 10 years ago in procedural PHP, zero documentation, and everything relying on global.

 

I figured this would be a great opportunity to get to understand the core foundational principals of Classes and OOP.  Initially I used typing / DI to pass the objects (as demonstrated in that book you keep linking to, Kevin), but after taking a look at the core of codeigniter I got the impression you could create a massive singleton-esque class where everything lies within on giant body.

 

I appreciate the pointers and will take a fresh look at how I want to accomplish my goals.

Link to comment
Share on other sites

I'm not a big fan of CodeIgniter or Kohana.  I used to be, but after I saw how they worked under the hood, I decided that they had some serious flaws.  Symfony is nice, because it's as complex or simple as you want it to be.  Each component of the framework is it's own standalone bundle, so you can decide to exclude whatever doesn't fit what you want to do.  From what I've been able to see in its GitHub repository, it's pretty solidly built, too.

 

But, back to design, the only time a super class really makes sense is if you're trying to create a Facade, where you have many different objects that interact with each other in one application layer (like, say, the domain) and want to hide the inner workings of that layer behind an interface.  Even then, the Facade's job is simply to act as the gatekeeper and delegate to the actual objects that do stuff.

Link to comment
Share on other sites

With being a professional yourself, and notwithstanding the benefits of learning to build a foundation... given that the code needs to be rewritten anyway (i'm afraid to update from php 5.2 to break this legacy application) should I stick to a framework?

Link to comment
Share on other sites

If getting it out the door is a priority, I'd say yes, especially if there's money awaiting you upon completion.  Frameworks = RAD (Rapid Application Development) = getting paid more often.  Ultimately, that's why they exist.  And, really, using a framework can be as valuable as digging through its code.  There's something to be said for actually putting it through its paces and finding where the edge cases are.  At the very least, you'll gain practical experience and insight into common pitfalls.

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.