The Little Guy Posted May 2, 2011 Share Posted May 2, 2011 I am making a project (which I would like to distribute), and I want to load core libraries into main class. Example Main Class: class Main{ public function loadCore(){ // Load core libraries } } $_main = new Main(); $_main->loadCore(); Once loadCore is run, I would like to load all the files in /root/core/net and /root/core/xml (which I have already done). Next I want to make them easily accessible, but I am not sure of an easy way to access them. I want to make it easy for beginner programmers (and advanced programmers). maybe so they have to do something like this: require_once 'root/Main.php'; // Automatically creates an instance $_main->http->someFunction(); // or $_main->net->http->someFunction(); // or $_main->someFunction(); The example structure: +- root | +- core | | +- net | | | +- Http.php | | | +- Other.php | | | +- Other2.php | | +- xml | | | +- Xml.php | | | +- Other.php | | | +- Other2.php | +- plugins +- Main.php Basically I am just looking for some input on how I could make this SUPER easy to use. The less work the programmer has to do the better. Any thoughts? Quote Link to comment https://forums.phpfreaks.com/topic/235363-core-libraries/ Share on other sites More sharing options...
requinix Posted May 2, 2011 Share Posted May 2, 2011 I'd suggest making use of the magic methods. Specifically __get, though __call and __set could be useful to you as well. No need for any loadCore() methods. Quote Link to comment https://forums.phpfreaks.com/topic/235363-core-libraries/#findComment-1209563 Share on other sites More sharing options...
The Little Guy Posted May 2, 2011 Author Share Posted May 2, 2011 The problem with that, is the possibility of methods that are name the same thing in two different classes.... I just got an idea of how I could do it though, not its not a 100% solid idea, but it may work. Any other suggestions would be appreciated! Quote Link to comment https://forums.phpfreaks.com/topic/235363-core-libraries/#findComment-1209586 Share on other sites More sharing options...
requinix Posted May 2, 2011 Share Posted May 2, 2011 ... It doesn't matter what the names are in different classes. Because they're in different classes. They won't conflict. Quote Link to comment https://forums.phpfreaks.com/topic/235363-core-libraries/#findComment-1209604 Share on other sites More sharing options...
The Little Guy Posted May 2, 2011 Author Share Posted May 2, 2011 class Main{ public function __call(){ // Call the function } } class A{ public function somthing(){ // Do some stuff } } class B{ public function somthing(){ // Do some stuff } } $mc = new Main(); $mc->something(); Which one does it call? Quote Link to comment https://forums.phpfreaks.com/topic/235363-core-libraries/#findComment-1209607 Share on other sites More sharing options...
gizmola Posted May 2, 2011 Share Posted May 2, 2011 Hey TLG, I think what you're looking for is: autoload If you want to look at an implementation http://framework.zend.com/manual/en/zend.loader.html and the features they have as well as the thought process that was used might give you some ideas. Quote Link to comment https://forums.phpfreaks.com/topic/235363-core-libraries/#findComment-1209609 Share on other sites More sharing options...
requinix Posted May 2, 2011 Share Posted May 2, 2011 Here's a real quick example of what I'm talking about. Real quick. If I were doing it seriously then it would be a little different. class Main { private $_tree = array( "net" => array( "http" => 'root/core/net/Http.php$Net_HttpClass', "other" => 'root/core/net/Other.php$Net_OtherClass' ), "xml" => array( "xml" => 'root/core/xml/Xml.php$Xml_XmlClass', "other" => 'root/core/xml/Other.php$Xml_OtherClass' ) ); private $_traversal = null; public function __get($name) { if ($this->_traversal == null) $this->_traversal = new MainTraversal($this->_tree); return $this->_traversal->$name; } } class MainTraversal { private $_tree = array(); public function __construct(array $tree) { $this->_tree = $tree; } public function __get($name) { if (isset($this->_tree[$name])) { if (is_string($this->_tree[$name])) { list($file, $class) = explode('$', $this->_tree[$name]); if (!class_exists($class)) require_once($file); return new $class(); } else { return new MainTraversal($this->_tree[$name]); } } else { return null; } } } If you want that serious version I'll do it for you, by the way. I like this kind of stuff. Quote Link to comment https://forums.phpfreaks.com/topic/235363-core-libraries/#findComment-1209611 Share on other sites More sharing options...
The Little Guy Posted May 2, 2011 Author Share Posted May 2, 2011 @requinix I will give your code a try when I get time later today. Currently this is what I have to load main items for this library: public function loadCore(){ foreach(glob($this->location."/core/*/*") as $coreFile){ $info = (object)pathinfo($coreFile); require_once $coreFile; $pos = strrpos($info->dirname, "/"); $coreMedia = substr($info->dirname, $pos + 1); $this->loadedFiles['core'][$coreMedia]['path'][] = $coreFile; $this->loadedFiles['core'][$coreMedia]['files'][] = $info->basename; } } At the moment it doesn't create instances or linking of any kind to make it so the methods in the class are usable. @gizmola I am not sure if that is what I am looking for... I use it, but I am not sure if I want it for this issue. Quote Link to comment https://forums.phpfreaks.com/topic/235363-core-libraries/#findComment-1209617 Share on other sites More sharing options...
gizmola Posted May 2, 2011 Share Posted May 2, 2011 Typically the reason you're loading this core stuff in is because it is going to be used. In terms of structuring code, the autoloader implementation often depends on a class name convention. You have code that could be handled by the autoloader, which is not only pointless, but a bad idea in most cases, because you don't want to load code that you're never going to use. So the main thing I see missing is that this core code should be used to create some objects that become part of your api. The naming of these objects as well as their visibility is a lot more important than the mechanics of how they got loaded. Quote Link to comment https://forums.phpfreaks.com/topic/235363-core-libraries/#findComment-1209623 Share on other sites More sharing options...
The Little Guy Posted May 2, 2011 Author Share Posted May 2, 2011 I don't want members that use this to have to do this: $inst = new MyClass(); Mainly for Ease of use. With my plugins, all I do is this: $plugins = "Mysql,Twitter"; require_once "dir/Main.php"; This will then ONLY load the Mysql and Twitter plugins, and none of the other ones. or, I can do: $disablePlugins = true; require_once "dir/Main.php"; Which will then not load any of the plugins. Quote Link to comment https://forums.phpfreaks.com/topic/235363-core-libraries/#findComment-1209640 Share on other sites More sharing options...
requinix Posted May 3, 2011 Share Posted May 3, 2011 With all due respect to your users, you have to let go of their hands at some point. If they're mucking around with PHP code then there's nothing wrong with expecting them to know how to muck around with PHP. You're talking about members... Who are these people? What are they doing with your code? Quote Link to comment https://forums.phpfreaks.com/topic/235363-core-libraries/#findComment-1209723 Share on other sites More sharing options...
The Little Guy Posted May 3, 2011 Author Share Posted May 3, 2011 oops, I didn't mean members. Basically I am making a library that will build pages quickly, just like jQuery makes javascript easy. Quote Link to comment https://forums.phpfreaks.com/topic/235363-core-libraries/#findComment-1209932 Share on other sites More sharing options...
requinix Posted May 3, 2011 Share Posted May 3, 2011 Okay. But still: who's the target demographic? If they have any (or should be expected to have any) PHP experience then introducing complex syntaxes for simple tasks will only mean they have to learn more stuff just to use your code. Quote Link to comment https://forums.phpfreaks.com/topic/235363-core-libraries/#findComment-1209937 Share on other sites More sharing options...
The Little Guy Posted May 3, 2011 Author Share Posted May 3, 2011 That is why I don't want to use a complex syntax for a simple task. Example: $main->drawCalendar(); And BOOM! you have a full blown calendar on your page. Quote Link to comment https://forums.phpfreaks.com/topic/235363-core-libraries/#findComment-1209939 Share on other sites More sharing options...
requinix Posted May 3, 2011 Share Posted May 3, 2011 To be specific, I'm talking about the difference between $_main->foo->bar->drawCalendar(); // and $foobar = new Foo_Bar(); $foobar->drawCalendar(); As a PHP developer I prefer the second version because I know what's going on. It's simple. It's stuff I've done before. The first version is doing some kind of trickery to get, well, something, and I won't know what it is unless I look through your code or manual or documentation. But to someone with... less than sufficient programming experience, the first is easier for them to learn. Which is why I'm wondering about your audience. Quote Link to comment https://forums.phpfreaks.com/topic/235363-core-libraries/#findComment-1209946 Share on other sites More sharing options...
The Little Guy Posted May 3, 2011 Author Share Posted May 3, 2011 My audience is everyone from beginner to advanced. Quote Link to comment https://forums.phpfreaks.com/topic/235363-core-libraries/#findComment-1209948 Share on other sites More sharing options...
ignace Posted May 3, 2011 Share Posted May 3, 2011 You can't serve the entire market (from beginner to advanced). Advanced users for example require functionality that reaches far beyond what beginners will ever need (ORM, DBAL, SOAP Client/Server, ..). Advanced users will also most likely use an IDE with type hinting of which it can't benefit if a large portion of your code is hidden behind magic methods like __call(), __set() and __get(). Both Symfony as CodeIgniter (Zend for it's action and view helpers) use this approach which I find annoying since I don't get a nice listing of available methods/properties. Quote Link to comment https://forums.phpfreaks.com/topic/235363-core-libraries/#findComment-1210014 Share on other sites More sharing options...
The Little Guy Posted May 3, 2011 Author Share Posted May 3, 2011 OK, based off what you said with IDE hinting, here is how I load plugins, it works, but in my IDE it doesn't do hinting. It creates the instance in the foreach loop. What do you think of this method of loading? public function loadPlugins($loadPlugins = null){ if(is_string($loadPlugins)){ $loadPlugins = explode(",", $loadPlugins); } $ini = $this->allpluginSettings(); if($loadPlugins == null){ foreach($ini as $sectionClass => $section){ require_once $this->location."/plugins/".$section['root']."/".$section['fileName']; $this->$section['instanceName'] = new $sectionClass(); $this->loadedFiles['plugins'][$section['root']]['path'][] = $this->location."/plugins/".$section['root']."/".$section['fileName']; $this->loadedFiles['plugins'][$section['root']]['files'][] = $section['fileName']; } } } I then can call the class like this: $myClass->example->someMethod(); Example INI file: [ExampleClass] root = Example fileName = ExampleClass.inc.php instanceName = example sessionRef = exmple [Mysql] root = Mysql fileName = Mysql.inc.php instanceName = mysql sessionRef = mysql Quote Link to comment https://forums.phpfreaks.com/topic/235363-core-libraries/#findComment-1210028 Share on other sites More sharing options...
ignace Posted May 3, 2011 Share Posted May 3, 2011 public function loadPlugins($loadPlugins = null){ if(is_string($loadPlugins)){ $loadPlugins = explode(",", $loadPlugins); } $ini = $this->allpluginSettings(); if($loadPlugins == null){ foreach($ini as $sectionClass => $section){ require_once $this->location."/plugins/".$section['root']."/".$section['fileName']; $this->$section['instanceName'] = new $sectionClass(); $this->loadedFiles['plugins'][$section['root']]['path'][] = $this->location."/plugins/".$section['root']."/".$section['fileName']; $this->loadedFiles['plugins'][$section['root']]['files'][] = $section['fileName']; } } } This code, while an initial draft, isn't reusable nor properly tested: 1. You assume that any passed string is CSV 2. Once $loadPlugins != NULL you don't use it anywhere besides explode() it when it's a string which in turn isn't used anywhere. 3. $this->allpluginSettings() is called while the returned value is only used when $loadPlugins == NULL 4. Files are loaded through the require_once mechanism instead of a generic loader class 5. It's assumed the require_once will ALWAYS point to a file, and it will ALWAYS contain a class, so that $this->$section['instanceName'] = new $sectionClass(); never fails. 6. Exceptions/Error's aren't caught. 7. Using deep nesting $this->loadedFiles['plugins'][$section['root']]['files'] instead of using an object to represent the data structure. $myClass->example->someMethod(); still has the problem of no type-hinting unless you specify phpDoc @property comments on the class but since you are aiming for a plugin architecture this is not an option. No type-hinting is not only an IDE problem, it will also be hard for beginners to actually be able to understand why tutorials tell them stuff like: $o = new SomeObject(); while your framework loads it on-the-fly under a different name. If you want to teach beginners something, teach them how to program OO properly instead of showing them magic tricks. MyCoolFramework::create('User')->username('ignace')->password('foobarbaz')->authenticateSession()->setProfileAvatar(new Avatar('bar.png'))->save(); May look cool, but programming isn't about creating giant one-liners. Quote Link to comment https://forums.phpfreaks.com/topic/235363-core-libraries/#findComment-1210062 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.