Zen Cart observer

From Wiki @ Karl Jones dot com
Jump to: navigation, search

A Zen Cart observer is an Observer design pattern in implemented in Zen Cart.

See also Zen Cart API.

Auto-load

Source

Zen Cart v1.5.3 supports auto-loaded observers. Built-in functionality helps automate the loading and instantiatian of your class file.

Load point caveat: auto-loaded classes are loaded at point 175, after all other system dependencies are loaded)

Requirements

As pulled from the file /includes/init_includes/init_observers.php:

The file is in the /includes/classes/observers folder and named auto.your_plugin.php.

All files in this directory that start with auto. will be included (loaded).

The file defines a class named zcObserver + the CamelCased filename

Example: a file named auto.your_plugin.php<code> will contain a class named <code>zcObserverYourPlugin.

A myDEBUG*.log file will be generated if a properly-named file is loaded, but the class name doesn’t conform to these rules.

Here’s an example that displays a message in the header, but only on the index (main) page; the file is /includes/classes/observers/auto.test_observer.php:

<?php
// -----
// An example of an auto-loaded observer, based on a feature introduced in Zen Cart v1.5.3.
//
// Displays a header-message *only* on the index page.
//
class zcObserverTestObserver extends base {

  function __construct() {
    $this->attach($this, array('NOTIFY_HEADER_START_INDEX'));
    
  }

  function update (&$class, $eventID, $paramsArray = array()) {
    global $messageStack;
    $messageStack->add ('header', 'The auto-loaded observer is loaded!', 'success');
    
  }
}

Example one

I'm using a fairly plain 1.3.8a and wanted to offer my experience today. I hadn't read this thread at all and went about things slightly differently, though by the looks of things I could have used this navigationHistory object referred to. I'm using a modified approach to that seen on http://www.zen-cart.com/forum/showth...login+redirect, which uses the observer/notify feature (http://www.zen-cart.com/wiki/index.p...Observer_Class) and the fact that includes/modules/pages/login/header_php.php fires a NOTIFY_LOGIN_SUCCESS notification event on successful login.

My situation is that, on entry to a custom tpl_somethingorother_default.php page, I want to ensure the customer is logged on. If I redirect to logon, I want them to come back to the current page after logon.

This is not a global solution, but one designed to be used in a specific module, because it relies on a custom session variable login_redirect being set, though I'm sure it could be adapted.

1/ Create file includes/classes/observers/login.redirector.php:

PHP Code: <?php

  1. see http://www.zen-cart.com/forum/showthread.php?t=135312&highlight=login+redirect

class LoginRedirector extends base {

 function LoginRedirector() {
   global $zco_notifier; 
   $zco_notifier->attach($this, array('NOTIFY_LOGIN_SUCCESS'));
 }
 function update(&$class, $eventID) {
     # If the login_redirect session variable was set, redirect to it.
   if (isset($_SESSION['login_redirect'])) {
       $destination = $_SESSION['login_redirect'];
     unset($_SESSION['login_redirect']);
     zen_redirect($destination);
   }
 }

} ?> 2/ Create file includes/auto_loaders/config.loginRedirect.php (perhaps the numbers 10 and 90 could be improved, I don't care about their values much as they don't depend on the order of any other instantiation):

PHP Code: <?php $autoLoadConfig[10][] = array('autoType'=>'class',

                             'loadFile'=>'observers/login.redirector.php');

$autoLoadConfig[90][] = array('autoType'=>'classInstantiate',

                             'className'=>'LoginRedirector',
                             'objectName'=>'LoginRedirector');

?> 3/ Then, in the module you want to redirect from (this is on entry to my Warranty form's header_php.php. In this flow of logic, I want to ensure the customer is logged in before proceeding):

PHP Code:

 if (!(isset($_SESSION['customer_id']))) {
     $_SESSION['login_redirect'] = zen_href_link (
       FILENAME_WARRANTY_FORM,
       'order_no=' . $_REQUEST['order_no'], 'SSL' );
     zen_redirect(zen_href_link ( FILENAME_LOGIN, , 'SSL' ));
 }  

So as a visitor tries to go to my warranty form, the first time through the template's header_php.php, if the customer_id is not set in the session, it will set a session login_redirect variable recording where to redirect back to after login, and redirect to login. Once login is complete, the observer jumps in, notices the login_redirect session variable, and redirects back to my warranty form.

You could set $_SESSION['login_redirect'] to any URL you like, and redirect to login, and it will redirect to your URL on successful login.

Example two

Observer/notifier "base" class:

QUESTION:

In the API tutorial it is explained that every class that want to make use of observer/notifier system has to extend the "base" class. However I cannot see how this can work. Maybe it is because I am a C++ guru and not a PHP. The problem as I see it is that we get different instances of the "base" class for every instance of observer or notifier class. Therefore the following observerclass will never get the notification from the shopping_cart class.

class myObserver extends base { function myObserver() { $this->attach($this, array('NOTIFIER_CART_ADD_CART_END')); } ... }

If the base class was static or was working on some global variables then it would be different. What have I misunderstood?

REPLY:

The documentation is buggy.

Your c'tor should instead say

$_SESSION['cart']->attach($this, array('NOTIFIER_CART_ADD_CART_END'));

for cart stuff. The cart object maintains a list of observers and calls them when the notify() method is called for the events they have registered for. Similarly, zco_notifier, etc.

See also