Zend Framework Plugin System & a little Magento

Not for 'how-to' coding questions but PHP theory instead, this forum is here for those of us who wish to learn about design aspects of programming with PHP.

Moderator: General Moderators

Post Reply
User avatar
DaveTheAve
Forum Contributor
Posts: 385
Joined: Tue Oct 03, 2006 2:25 pm
Location: 127.0.0.1
Contact:

Zend Framework Plugin System & a little Magento

Post by DaveTheAve »

So for as long as I've been using Zend Framework, which was well before it's first stable release, I've been wondering how to develop a plugin system for my Zend Framework project. Perhaps similar to the one used in wordpress. My question is, how would I go about doing this? Do you have any examples or guides for me to study?

One last thing, how does Magento's plugin system works? So hard to understand that code without spending hours clicking through files.
User avatar
Luke
The Ninja Space Mod
Posts: 6424
Joined: Fri Aug 05, 2005 1:53 pm
Location: Paradise, CA

Re: Zend Framework Plugin System & a little Magento

Post by Luke »

Hey Dave! I've actually been working on a plug-in system for my framework as well. My framework is about 95% Zend Framework and 5% my own components. I must admit I haven't gotten very far because the plug-in system was for a piece of software I don't get much time to work on, but basically I am using a sort of observer-type setup for my plug-in system. Here is the gist:

Throughout my application's controllers I have sprinkled various "hooks" which have the ability to inject logic at strategically placed locations. For instance, my Auth controller (login/logout) looks something like this:

Code: Select all

<?php
class FrontEnd_AuthController extends Visi_Controller_Action {

        $rules = with(new Q_Rule_Set())
            ->add(new Q_Rule_NotNull(), array('username','password'), 'This is a required field');
        if ($this->getRequest()->isPost()) {
            $post = $this->getRequest()->getPost();
            if ($rules->validate($post)) {
                $auth = Zend_Auth::getInstance();
                $secretKey = $this->_config->security->secretKey;
                $authAdapter = new Zend_Auth_Adapter_DbTable(
                    $this->getModel('user')->getAdapter(),
                    $this->getModel('user')->info(Visi_Db_Table::NAME),
                    'username',
                    'password',
                    "SHA1(CONCAT(salt, '$', ?, '$', '" . $secretKey . "')) AND active = 1"
                );
                $authAdapter->setIdentity($post['username'])
                            ->setCredential($post['password']);
                $result = $auth->authenticate($authAdapter);
                if ($result->isValid()) {
                    $storage = $auth->getStorage();
                    $storage->write($authAdapter->getResultRowObject());
                    $message = 'You are now logged in as ' . $result->getIdentity();
                    $event = new Visi_Event('login_success', array('user' => $authAdapter->getResultRowObject()));
                    $this->_eventManager->triggerEvent($event);
                    $this->flashAway($message, 'success', 'home');
                } else {
                    $this->flashAway('Invalid login', 'error', 'login');
                }
            } else {
                $this->flash('You must fill out the form correctly');
                $errors = $rules->getErrors();
                Visi_View_Helper_FormError::setErrors($errors);
            }
        }

}
As you can see, I have an event manager that allows me to "trigger" events at places I may need to inject logic. I have found that this type of setup allows me the most flexibility. I don't have access to the actual code right now, so I don't have an example of what my plugin and event classes actually look like, but when I get home I will grab them and post them for you to take a look at. I must say though that event-driven applications are extremely fun to work with. At least in my experience so far :) I have implemented a ton of things as plugins that would normally have gone into my controllers and cluttered them up. Things such as e-mails that go out to an admin when a user registers or logging in a database of certain actions. So basically I get to keep my controllers extremely specific to a particular action. Anything that could be considered a "side-effect" goes into a plugin. More later...
josh
DevNet Master
Posts: 4872
Joined: Wed Feb 11, 2004 3:23 pm
Location: Palm beach, Florida

Re: Zend Framework Plugin System & a little Magento

Post by josh »

Magento modules are PHP+XML
http://alanstorm.com/magento_config

I try to use as little of their XML "language" as possible, its an uphill battle with Magento. Most of the time what you're doing will conflict with someone else's third party extension, because both of you will have had to physically modify some template file.

Extension developers also have the ability to say "hey don't use the regular product/view.phtml use my-hidden/view.phtml". So suddenly changes to product/view.phtml don't take affect because someone overrides the whole system to use a different template. Sometimes this is necessary because what you want to do involves modifying view code, which isn't extensible.. because Magento puts business logic in the view, and allows "conflicts" when two extensions override the same file, it can cause some big headaches...

Magneto also has the event system Luke mentions, but in practice I find most of the time there are not hooks in place for what you need to do, unless it is really simple. Also Magento has a lot of hooks in abstract code so it may fire an event 1,000 times... 999x for the objects you don't care about, and only 1x for the object you do care about, but you have to "listen" to all 1,000 events or none. All or nothing with it's event system.
User avatar
DaveTheAve
Forum Contributor
Posts: 385
Joined: Tue Oct 03, 2006 2:25 pm
Location: 127.0.0.1
Contact:

Re: Zend Framework Plugin System & a little Magento

Post by DaveTheAve »

Luke, I must say, I am looking forward to see the rest of your plugin system. Looks to be what I'm looking for, but what criteria do you use to decide when to place a hook? I don't want too many for performance reasons, but I also don't wish to have too few and lack plugin functionality.

Also, how do you handle plugins that require another tab on a tabbed UI, ie: wordpress's settings panel. Do you just appended the tab or do you offer a weighted tab system? I can see the former causing inconveniences but I also see the latter being exploited by plugin writers who think their plugin is the best.
User avatar
DaveTheAve
Forum Contributor
Posts: 385
Joined: Tue Oct 03, 2006 2:25 pm
Location: 127.0.0.1
Contact:

Re: Zend Framework Plugin System & a little Magento

Post by DaveTheAve »

Quote from my PM to Luke:
What i'm currently trying to figure out is if I want version 1 to just have the bear-bones of the concept or if I want to make it plugin-based from the get go. As you were saying you really enjoyed using plugins instead of the traditional methoud.

My ultimate goal is to have the project entirely plugin based, for instance when the user wants to upload a file, it'll search for a file-system plugin (could be a few I want to use, traditional filesystem using the same server, Google's cloud, Amazon cloud, etc.) and call the plugin that is active and make calls to it based on the interface that file-system plugins use. Of-course there will be multiple interfaces for system functionality and plugins that don't use interfaces at all.

Kind of how any part of the android system can be replaced or modified with applications (in my case plugins).
josh
DevNet Master
Posts: 4872
Joined: Wed Feb 11, 2004 3:23 pm
Location: Palm beach, Florida

Re: Zend Framework Plugin System & a little Magento

Post by josh »

DaveTheAve wrote:Kind of how any part of the android system can be replaced or modified with applications (in my case plugins).
That's the factory pattern. All objects get created thru a factory instead of instantiated directly. http://msdn.microsoft.com/en-us/library/ee817667.aspx
Post Reply