Mahngiel Posted August 7, 2012 Share Posted August 7, 2012 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? Quote Link to comment https://forums.phpfreaks.com/topic/266775-building-a-base-class/ Share on other sites More sharing options...
KevinM1 Posted August 7, 2012 Share Posted August 7, 2012 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? Quote Link to comment https://forums.phpfreaks.com/topic/266775-building-a-base-class/#findComment-1367538 Share on other sites More sharing options...
Mahngiel Posted August 7, 2012 Author Share Posted August 7, 2012 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. Quote Link to comment https://forums.phpfreaks.com/topic/266775-building-a-base-class/#findComment-1367540 Share on other sites More sharing options...
KevinM1 Posted August 7, 2012 Share Posted August 7, 2012 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: Quote Link to comment https://forums.phpfreaks.com/topic/266775-building-a-base-class/#findComment-1367556 Share on other sites More sharing options...
ignace Posted August 7, 2012 Share Posted August 7, 2012 Talking about said author, try: http://twittee.org/ and (my favourite, I have yet to find a package by fabpot that I don't like ) http://pimple.sensiolabs.org/ Quote Link to comment https://forums.phpfreaks.com/topic/266775-building-a-base-class/#findComment-1367592 Share on other sites More sharing options...
KevinM1 Posted August 7, 2012 Share Posted August 7, 2012 I have yet to find a package by fabpot that I don't like Hehe, fabpot. 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. Quote Link to comment https://forums.phpfreaks.com/topic/266775-building-a-base-class/#findComment-1367618 Share on other sites More sharing options...
Mahngiel Posted August 7, 2012 Author Share Posted August 7, 2012 So, if I understand correctly, instead of loading on large class to grant access to objects, I should instead build a chain that passes the required objects between each other during preload that I would want to use later. Quote Link to comment https://forums.phpfreaks.com/topic/266775-building-a-base-class/#findComment-1367633 Share on other sites More sharing options...
KevinM1 Posted August 7, 2012 Share Posted August 7, 2012 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; Quote Link to comment https://forums.phpfreaks.com/topic/266775-building-a-base-class/#findComment-1367640 Share on other sites More sharing options...
Mahngiel Posted August 7, 2012 Author Share Posted August 7, 2012 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. Quote Link to comment https://forums.phpfreaks.com/topic/266775-building-a-base-class/#findComment-1367644 Share on other sites More sharing options...
KevinM1 Posted August 7, 2012 Share Posted August 7, 2012 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. Quote Link to comment https://forums.phpfreaks.com/topic/266775-building-a-base-class/#findComment-1367656 Share on other sites More sharing options...
Mahngiel Posted August 8, 2012 Author Share Posted August 8, 2012 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? Quote Link to comment https://forums.phpfreaks.com/topic/266775-building-a-base-class/#findComment-1367659 Share on other sites More sharing options...
KevinM1 Posted August 8, 2012 Share Posted August 8, 2012 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. Quote Link to comment https://forums.phpfreaks.com/topic/266775-building-a-base-class/#findComment-1367683 Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.