Go Back   SitePoint Forums > Forum Index > Program Your Site > PHP > PHP Application Design
Newsletter FAQ Members List Calendar Mark Forums Read

New to SitePoint Forums? Register here for free!

SitePoint Sponsor
 
Reply
 
Thread Tools Display Modes
Old Jan 30, 2004, 13:46   #1
Selkirk
SitePoint Guru
 
Join Date: Nov 2002
Posts: 845
Object composition by Proxy

Standard PHP has a mechanism for specifying a reference to an object and a method to call it:

PHP Code:

$ref = array(&$obj, "methodName");

$params = array("hello", "world");
call_user_object_array($ref, $params);
In PHP 5, the overloading method could be used with this to create a proxy object which re-routed method calls:

PHP Code:

// Untested

class ProxyReference {

    var
$Obj;
    var
$Ref;
    var
$File;
    var
$Class;
    var
$Method;

    function
Proxy($File, $Class, $Method) {
        
$this->File = $File;
        
$this->Class = $Class;
        
$this->Method = $Method;
    }

    function
__call($method, $params, &$return) {
        if (!
is_object($this->Obj)) {
            require_once
$this->File;
            
$this->Obj =& new $this->Class(); //syntax correct?
            
$this->Ref = array(&$this->Obj, $this->Method);
        }
        
call_user_object_array($this->Ref, $params);
    }
}
This ProxyReference class has the feature of not instantiating the object called unless a call is actually made. This is almost like a generic decorator.

This could be used to transparently compose objects:

PHP Code:

class SomeClass {

    var
$Obj
    
function SomeClass($ReferenceObj) {
        
$this->Obj =& $ReferenceObj;
    }

    function
RarelyCalledMethod($Parameter) {
        
$this->Obj->DoSomething($Parameter);
    }
}
So, correct me if I am wrong, but it is possible in PHP5 for the SomeClass Object to be completely unaware of the fact that the object it is using is a proxy for another object. The SomeClass object is complete unaware that the real object it is communicating with has not been loaded.

SomeClass makes a normal method call. The call_user_object_array business is encapsulated in the ProxyReference class.

My question is, Is it possible to do this in PHP 4? If not, how close can you get?

One use I see for this is in creating a GenericDecorator class. This might only be possible in PHP 5. The advantage of a GenericDecorator (performance considerations aside for a moment) is that you could decorate any object without having to declare its entire interface. Only the part you wished to decorate. Thus, when you changed the object being decorated, you might not necessarily have to change the decorator classes. A good dependency limiter, resulting is less code for the same thing.

The use that I am interested in is creating on demand references in PHP 4. I want to minimize the effort involved with invoking an on-demand reference by encapsulating the call as much as possible. In other words, I should not have to copy/paste/modify a block of code like the implementation of the __call method in the ProxyReference object for every method invocation on the object in the RarelyCalledMethod invocation.

The context is creating objects that persist across several HTTP requests. I would like to construct the object as if it were going to persist across several requests. This object is composed of several other objects. Only a small subset of the objects in the assembly will actually be called on each HTTP requests. Over the course of the sequence of requests, most of the objects will be called. Since the object assembly can't persist across requests, I want to limit the cost of re-instantiating it each time, by not actually instantiating the portions of the assembly which are not not used. Yet, I want my construction code to be unaware of which portions of the assembly will or won't be used during each request. (The same construction code should get executed for each request.)

I am not sure if I have been very clear about what I am looking for, but I was hoping for some ideas.
Selkirk is offline   Reply With Quote
Old Jan 30, 2004, 14:57   #2
FelhoBacsi
SitePoint Member
 
Join Date: Dec 2003
Location: ---
Posts: 22
Hi!

Quote:
Originally Posted by Selkirk
My question is, Is it possible to do this in PHP 4? If not, how close can you get?
http://hu.php.net/manual/en/ref.overload.php
This is not good for you?

Felho
FelhoBacsi is offline   Reply With Quote
Old Jan 30, 2004, 15:07   #3
ghurtado
SitePoint Guru
 
ghurtado's Avatar
 
Join Date: Sep 2003
Location: Wixom, Michigan
Posts: 619
If you dont want to use the overloading extension, lastcraft posted this possible implementation for Decorators in PHP4, not too long ago:
http://www.sitepoint.com/forums/show...ight=decorator
ghurtado is offline   Reply With Quote
Old Jan 30, 2004, 15:10   #4
HarryF
SitePoint Wizard
 
Join Date: Nov 2000
Location: Switzerland
Posts: 2,906
Think I can see what you're trying to do and very powerful it would be if it can be done - suddenly it's worth persisting large numbers of objects.

Off the top of my head, one way to do it (and perhaps the only way) is to generate proxy classes (active generation) although a factory will be needed to get references to them. Something like;

PHP Code:

<?php

class ProxyFactory {
    function &
getProxy($Class,$File) {
        
$this->Class = $Class;
        
$this->File = $File;

        
$this->checkProxyExists();

        include_once
$File_Proxy;

        
$ProxyClass = $Class."_Proxy";
        return new
$ProxyClass();
    }

    function
checkProxyExists() {
        
// Something cleverer needed here, to check times / versions
        
if (!file_exists($this->File) ) {
            
$this->generateProxy();
        }
    }

    function
generateProxy() {
        include_once
$this->File;
        
$Methods = get_class_methods($this->Class);

        
// Insert code here the creates class and defines stub methods
    
}
}
?>
PHP Code:

<?php

// Here's the generated proxy code
class SomeClass_Proxy {
    var
$__realInstance = NULL;
    function &
__getRealInstance() {
       include_once
"SomeClass.php";
       if ( !
$this->__realInstance ) {
           
$this->__realInstance = & new SomeClass();
       }
       return
$this->__realInstance;
    }

    function
RarelyCalledMethod() {
       
$args = & func_get_args();
       
$obj =  & $this->__getRealInstance();
       
$ref = array(&$obj,'RarelyCalledMethod');
       return
call_user_func_array($ref,$args);
    }
}
?>
Not 100% sure that meets all the requirements but getting there perhaps. The first time a proxy is ever needed, it will have the overhead of included the real class. After that, it should be a fairly lightweight class and "lazy instantiates" the real class it's proxying for.

One issue might be whether the proxy RarelyUsedMethod should return a reference or copy of the result it gets from calling the real RarelyUsedMethod. For that I don't know.
HarryF is offline   Reply With Quote
Old Jan 30, 2004, 19:05   #5
lastcraft
SitePoint Victim
 
lastcraft's Avatar
 
Join Date: Apr 2003
Location: London
Posts: 2,265
Hi...

Quote:
Originally Posted by Selkirk
My question is, Is it possible to do this in PHP 4? If not, how close can you get?
This works on PHP 4.3.0 (my current home version)...
PHP Code:

<?php

class LazyProxy {
    var
$_wrapped;
    var
$_parameters;
    var
$_class;
    
    function
LazyProxy() {
        
$this->_wrapped = false;
        
$this->_parameters = func_get_args();
        
$this->_class = array_shift($this->_parameters);
    }
    
    function &
_instantiate() {
        
$parameter_names = array();
        for (
$i = 0; $i < count($this->_parameters); $i++) {
            
$parameter_names[$i] = "\$this->_parameters[$i]";
        }
        
$parameter_code = implode(', ', $parameter_names);
        
$code = "\$instance = &new " . $this->_class . "($parameter_code);";
        eval(
$code);
        return
$instance;
    }
    
    function
__call($method, $parameters, &$result) {
        if (
$this->_wrapped === false) {
            
$this->_wrapped = &$this->_instantiate();
        }
        if (
method_exists($this->_wrapped, $method)) {
            
$result = call_user_func_array(
                    array(
$this->_wrapped, $method),
                    
$parameters);
            return
true;
        }
        return
false;
    }
}
overload('LazyProxy');
?>
Here is the rather messy test case...
PHP Code:

<?php

define
('SIMPLE_TEST', 'simpletest/');
require_once(
SIMPLE_TEST . 'unit_tester.php');
require_once(
SIMPLE_TEST . 'reporter.php');
require_once(
'lazy_proxy.php');

class
Prefixer {
    var
$_prefix;
    
    function
Prefixer($prefix) {
        
$this->_prefix = $prefix;
        
$this->countInstances(true);
    }
    function
prefix($message) {
        return
$this->_prefix . $message;
    }
    function
countInstances($another = false) {
        static
$count = 0;
        if (
$another) {
            
$count++;
        }
        return
$count;
    }
}

class
TestOfLazyProxy extends UnitTestCase {
    function
TestOfLazyProxy() {
        
$this->UnitTestCase();
    }
    function
testProxyWrapsClass() {
        
$start = Prefixer::countInstances();
        
$proxy = &new LazyProxy('Prefixer', 'Hello ');
        
$this->assertEqual($start, Prefixer::countInstances());
        
$this->assertEqual($proxy->prefix('Jeff'), 'Hello Jeff');
        
$this->assertEqual($start + 1, Prefixer::countInstances());
        
$this->assertEqual($proxy->prefix('Harry'), 'Hello Harry');
        
$this->assertEqual($start + 1, Prefixer::countInstances());
    }
}

$test = &new TestOfLazyProxy();
$test->run(new HtmlReporter());
?>
I am dropping references all over the place here. Without proper reflection I have the same problem as with code generation. i.e. func_get_args() copies parameters.

yours, Marcus
lastcraft is offline   Reply With Quote
Old Jan 30, 2004, 21:28   #6
sweatje
eschew sesquipedalians
 
sweatje's Avatar
 
Join Date: Jun 2003
Location: Iowa, USA
Posts: 3,764
Quote:
Originally Posted by lastcraft
I am dropping references all over the place here. Without proper reflection I have the same problem as with code generation. i.e. func_get_args() copies parameters.
Well...it is ugly but the:
PHP Code:

$decorated_object->method( array(&$object) ); 

should be a way around that.
sweatje is offline   Reply With Quote
Old Jan 31, 2004, 02:35   #7
HarryF
SitePoint Wizard
 
Join Date: Nov 2000
Location: Switzerland
Posts: 2,906
Think the problem there is the "overload extension" only became a default part of PHP with 4.3.0 (I think).

Also there was a weird bug with __call() - if you declare it, suddenly your own class methods cease to be able to return values. For example;

PHP Code:

<?php

class Test {
    var
$test;
    function
Test () {
        
$this->test='Hello World';
    }

    function
getTest () {
        return
$this->test;
    }

    function
__call () {

    }
}

// Declare the class as overloaded
overload ("Test");

$test=new Test;

echo (
$test->getTest() ); // This returns nothing
echo ( $test->test ); // This works.
?>
Can't say I'd want to rely on the PHP4 implementation.
HarryF is offline   Reply With Quote
Old Feb 1, 2004, 05:48   #8
HarryF
SitePoint Wizard
 
Join Date: Nov 2000
Location: Switzerland
Posts: 2,906
Before I lose the link, there's a nice article here: An introduction to object prevalence, and Prevayler. Only vaguely related, as implementing it in PHP would probably only be worthwhile if you're using Shared memory.
HarryF is offline   Reply With Quote
Old Feb 2, 2004, 22:55   #9
Selkirk
SitePoint Guru
 
Join Date: Nov 2002
Posts: 845
Well, after some thought, I realized another way to express what I am looking to do. I want to be able to reference a class and have that reference include the information for finding that class. (similar to autoload) This is like in Java where a class name in com.x.x.x.classname format combined with a class path is sufficient for loading that class.

I need to have a solution that works in PHP 4.1 or better.

Here is what I have so far:

PHP Code:

function ResolveReference(&$Reference) {

    if (!
is_object($Reference) && !is_null($Reference)) {
        if (
is_string($Reference)) {
            if (
is_integer($Pos = strpos($Reference, ':'))) {
                
$File = substr($Reference, 0, $Pos);
                
$Class = substr($Reference, $Pos + 1);
                require_once
$File;
            } else {
                
$Class = $Reference;
            }
        }
        
$Reference = new $Class();  // =& doesn't work here.  Why?
    
}
}

class
SomeClass {
    var
$Ref;
    function
registerReference(&$Ref) {
        
$this->Ref =& $Ref;
    }
    function
someMethod() {
        
ResolveReference($this->Ref);
        
$this->Ref->someOtherMethod();
    }
}
To Create a SomeClass and use a SomeOtherClass with it:

PHP Code:

$Some =& new SomeClass();


// Alternatives
$Some->RegisterReference('SomeOtherClass');
$Some->RegisterReference('/path/file.php:SomeOtherClass');  
$Some->RegisterReference(new SomeOtherClass());
I have tested the ResolveReference function, not the SomeClass part of this.

The advantage of this method is that I can pass an object or a PHP 4.3+ LazyProxy, or a simple classname, or a classname with a file specification.

The disadvantage is that the ResolveReference helper function has to be called on any variable holding a reference before that reference can be used.

I love to find a better way to do this.

Next up, I would like to expand the concept of the reference to include parameters to the constructor. The problem I have is that there is no call_user_function_array equivalent that can create an object. Unless I am missing something.

Here is what I want to do. (Not sure which syntax is best, yet)

PHP Code:

class SomeOtherClass {

    
SomeOtherClass($templateFile) {
    ...
    }
}

$Some =& new SomeClass();

// Alternatives
$Some->RegisterReference(array('SomeOtherClass', 'template.html'));
$Some->RegisterReference(array('SomeOtherClass', array('template.html')));
Selkirk is offline   Reply With Quote
Old Feb 3, 2004, 02:52   #10
HarryF
SitePoint Wizard
 
Join Date: Nov 2000
Location: Switzerland
Posts: 2,906
On the second problem; passing a variable number of arguments to a constructor, here's a tip off from the PHP manual under eval();

PHP Code:

<?php

function classFactory($classname)
{
   
$code = "return new {$classname}(";
   if (
func_num_args() > 1) {
       
$params = array_slice(func_get_args(),1);
       
$c = count($params);
       for(
$i=0;$i<$c;++$i) {
           if (
$i>0) {
               
$code .= ',';
           }
           
$code .= '$params[' . $i . ']';
       }
   }
   
$code .= ');';
   return eval(
$code);
}

class
Foo
{
   function
Foo($arg1,$arg2,$arg3)
   {
       echo
"I am Foo, I expect 3 arguments...\n";
       echo
"arg1 = $arg1\n";
       echo
"arg2 = $arg2\n";
       echo
"arg3 = $arg3\n\n";
   }
}

class
Bar
{
   function
Bar($arg1)
   {
       echo
"I am Bar, I expect 1 argument...\n";
       echo
"arg1 = $arg1\n\n";
   }
}

$myFoo = classFactory('Foo',100,'moose',array(1,2,3));
$myBar = classFactory('Bar',4564);
?>
[/php]
HarryF is offline   Reply With Quote
Old Feb 3, 2004, 07:04   #11
lastcraft
SitePoint Victim
 
lastcraft's Avatar
 
Join Date: Apr 2003
Location: London
Posts: 2,265
Hi...

Quote:
Originally Posted by HarryF
On the second problem; passing a variable number of arguments to a constructor, here's a tip off from the PHP manual
I used that in the LazyProxy::_instantiate() method above .

Jeff, can you express what you want as a test case? It sounds like a fun problem, but I am not exactly sure I understand everything.

yours, Marcus
lastcraft is offline   Reply With Quote
Old Feb 3, 2004, 09:57   #12
Selkirk
SitePoint Guru
 
Join Date: Nov 2002
Posts: 845
I am prejudiced against eval.

Here is my Test case for the ResolveReference Function:

PHP Code:

class UnaffectedObject {

    var
$testVar = 'default';
}

class
DeclaredInSameFile {
    var
$testVar = 'default';
    function
DeclaredInSameFile($Var = 'constructionDefault') {
        
$this->testVar = $Var;
    }
}

class
ReferenceTestCase extends UnitTestCase {
    function
ReferenceTestCase($name = 'ReferenceTestCase') {
        
$this->UnitTestCase($name);
    }

    function
testNullReference() {
        
$Ref = NULL;
        
ResolveReference($Ref);
        
$this->assertNull($Ref);
    }

    function
testObjectUnaffected() {
        
$Ref =& new UnaffectedObject();
        
$Obj =& $Ref;
        
$Obj->testVar = 'Changed';
        
ResolveReference($Ref);
        
$this->assertIsA($Ref, 'UnaffectedObject');
        
$this->assertIdentical($Ref, $Obj);
        
$this->assertEqual($Ref->testVar, 'Changed');
    }

    function
testClassDeclaredInSameFile() {
        
$Ref = 'DeclaredInSameFile';
        
ResolveReference($Ref);
        
$this->assertIsA($Ref, 'DeclaredInSameFile');
    }

    function
testLoadClassFile() {
        
$this->assertFalse(class_exists('LoadedReferenceClass'));
        
$Ref = dirname(__FILE__) . '/reference.inc.php:LoadedReferenceClass';
        
ResolveReference($Ref);
        
$this->assertIsA($Ref, 'LoadedReferenceClass');
        
$this->assertTrue(class_exists('LoadedReferenceClass'));
    }
    
    function
testConstructor() {
        
$Ref = array('DeclaredInSameFile', 'ConstructionParameter');
        
ResolveReference($Ref);
        
$this->assertIsA($Ref, 'DeclaredInSameFile');
        
$this->assertEqual($Ref->testVar, 'ConstructionParameter');
    }
    
}
Here is Reference.inc.php (part of the test case):

PHP Code:

class LoadedReferenceClass {

    var
$testVar = 'default';
}
Selkirk is offline   Reply With Quote
Old Feb 3, 2004, 10:25   #13
Resolution
SitePoint Zealot
 
Join Date: Feb 2003
Location: Virginia
Posts: 143
Ok. As promised, Ghost.

PHP Code:

 <?php 
class Ghost
{
private $object;
private $filterList = array();
private $observerList = array(); //Exercise for you
private $decoratorList = array(); //Exercise for you

function Ghost($objectName)
{
  
$this -> object = new $objectName();
}

function
__call($function, $args)
{
  
$data = $this -> object -> $function ($args);
  
  foreach (
$this -> filterList[$function] as $objName => $obj)
  {
   echo
"<BR>I am a filter named ".$obj -> filter($objName);
   
$data = $obj -> filter($data);
  }
  return
$data;
}

function
addFilter($function, $obj)
{
  
$this -> filterList[$function][get_class($obj)] = $obj;
}
}
//End Ghost class


class Secret
{
private $secret = "Cows really CAN jump over the moon!";

function
getSecret()
{
  return
$this -> secret;
}
}
//End Secret class


class ItalicFilter
{
function
filter($data)
{
  return (
"<I> $data </I>");
}
}
//End ItalicFilter class


class BoldFilter
{
function
filter($data)
{
  return(
"<B> $data </B>");
}
}
//End BoldFilter class



$test = new Ghost('Secret');
$test -> addFilter("getSecret", new BoldFilter);
$test -> addFilter("getSecret", new ItalicFilter);
echo (
"<BR>".$test -> getSecret());
?>

The neat thing about this "proxy"/"factory" pattern I call Ghost is that it can be very flexable. The class objects that were passed in can be lazy loaded or added as objects. One could also add observers and decorators just as easily!

This class might proove to be a great test root as well since Secret has no idea its being shadowed - though I would suggest adding a few safe guards in case the output is error code or not of same type as expected to be output. I would also suggest adding an interface to the Filters.. Ok, you could see that one right?

Anyhow, its strange I got this idea/concept while reading this post. I read up on Slots and Signals , AOP and AspectJ - took a nap woke up a few hours later with the idea you now see before you.

So, does this solution seem to help or did I just make yet another wheel?

Cheers,
Res
Resolution is offline   Reply With Quote
Old Feb 3, 2004, 10:28   #14
Resolution
SitePoint Zealot
 
Join Date: Feb 2003
Location: Virginia
Posts: 143
Here's the output...

Quote:
I am a filter named boldfilter
I am a filter named italicfilter
Cows really CAN jump over the moon!
Resolution is offline   Reply With Quote
Old Feb 3, 2004, 11:17   #15
Selkirk
SitePoint Guru
 
Join Date: Nov 2002
Posts: 845
Upon further testing, I've run into an unfortunate snag.

Earlier I had a list of alternative ways to call my RegisterReference function:

PHP Code:

// Alternatives

$Some->RegisterReference('SomeOtherClass');
$Some->RegisterReference('/path/file.php:SomeOtherClass');  
$Some->RegisterReference(new SomeOtherClass());
It turns out that this cannot work based on my definition of RegisterReference:

PHP Code:

    function registerReference(&$Ref) {

        
$this->Ref =& $Ref;
    }
Since the RegisterReference takes has a reference parameter, you cannot pass a constant value to this function.

It seems that I am forced to choose between taking a constant and loosing the ability to pass an already instantiated object (or Proxy Object) OR taking only an object and loosing the simplicity of being able to pass in a class name as a string. (which has some backward compatibillity issues for my purposes.)

Here is an example of how I wanted to use this capability in WACT:
PHP Code:

require '../configure.inc.php';

require_once
WACT_ROOT . '/controller/formpage.inc.php';

define('LOCAL_PATH', dirname(__FILE__));

$Form = new FormPage();
$Form->registerView(LOCAL_PATH . '/formview.inc.php:CategoryFormView');
$Form->registerValidator(LOCAL_PATH . '/validator.inc.php:CategoryValidator');
$Form->registerSubmitAction('preview', WACT_ROOT . '/controller/noaction.inc.php:NoAction');
$Form->registerSubmitAction('add', LOCAL_PATH . '/add.inc.php:AddCategory', PRE_VALID);
$Form->registerDefaultSubmitAction(LOCAL_PATH . '/add.inc.php:AddCategory', PRE_VALID);
$Form->Run();
I also wanted to be able to support something like this alternative usage of the same thing (or the ability to mix and match from either style):

PHP Code:

require '../configure.inc.php';

require_once
WACT_ROOT . '/controller/formpage.inc.php';

require
'formview.inc.php';
require
'validator.inc.php';
require
'add.inc.php';

require
WACT_ROOT . '/controller/noaction.inc.php';

$Form = new FormPage();
$Form->registerView(new CategoryFormView());
$Form->registerValidator(new CategoryValidator());
$Form->registerSubmitAction('preview', new NoAction());
$Form->registerSubmitAction('add',new AddCategory(), PRE_VALID);
$Form->registerDefaultSubmitAction(new AddCategory(), PRE_VALID);
$Form->Run();
However, it seems that I can only have one or the other because of the reference parameter on the register functions. I don't like to remove the reference because then any objects that get passed in will get cloned, potentially leading to subtle bugs. I would almost rather remove the capability to pass in objects altogether.
Selkirk is offline   Reply With Quote
Old Feb 3, 2004, 11:37   #16
sweatje
eschew sesquipedalians
 
sweatje's Avatar
 
Join Date: Jun 2003
Location: Iowa, USA
Posts: 3,764
Here was a thread on using the array(&$obj) wrapper to allow for either a constant (simple string declaration) or a object by ref. It was not pretty, but it did seem functional
sweatje is offline   Reply With Quote
Old Feb 3, 2004, 12:40   #17
Widow Maker
Non-Member
 
Join Date: Jan 2004
Location: Planet Earth
Posts: 1,807
Do you mean the following, where by PHP throws up an error ?

PHP Code:



$hello
= &new Hello( 'Hello World' );
...

class
Hello {
function
Hello( &$variable ) {
... }
}
Just wondering really, as if this is the case, does the function you mention in the link actually work okay ?

Thanks.
Widow Maker is offline   Reply With Quote
Old Feb 4, 2004, 04:44   #18
sweatje
eschew sesquipedalians
 
sweatje's Avatar
 
Join Date: Jun 2003
Location: Iowa, USA
Posts: 3,764
Quote:
Originally Posted by Widow Maker
Just wondering really, as if this is the case, does the function you mention in the link actually work okay?
In instances where I have needed it, it has worked fine. Consider:
PHP Code:

class foo {

  var
$p;
  function
foo ($parm) {
    
$this->p = $parm;
  }
}

class
bar {
  var
$foo;
  function
bar ($foo_in) {
    if (!
$foo =& obj_from_envelope($foo_in)) {
      
$foo =& new foo($foo_in);
    }
    
$this->foo =& $foo;
  }
}
Now for bar, I can pass either a string to use as the parameter for creating a new foo, or an array containing a reference to an already created foo.

HTH
sweatje is offline   Reply With Quote
Old Feb 4, 2004, 20:38   #19
Selkirk
SitePoint Guru
 
Join Date: Nov 2002
Posts: 845
Thanks for finding that, sweatje. The envelope technique has eased my mind a bit about removing the reference from the parameter. There is no perfect solution in PHP 4, but at this this should be forward compatible with PHP 5.

I ran across this related blog entry today and now I wish I had used the same title for this thread:

Lazy Evaluation and Object Composition
Selkirk is offline   Reply With Quote
Old Feb 5, 2004, 09:19   #20
Widow Maker
Non-Member
 
Join Date: Jan 2004
Location: Planet Earth
Posts: 1,807
So it works then ? That is really cool - Okay for me to use the function SweatJe - Sure to find a use for it
Widow Maker is offline   Reply With Quote
Old Feb 5, 2004, 09:45   #21
sweatje
eschew sesquipedalians
 
sweatje's Avatar
 
Join Date: Jun 2003
Location: Iowa, USA
Posts: 3,764
Quote:
Originally Posted by Widow Maker
Okay for me to use the function SweatJe
I pretty much consider anything I put up on the boards fair game. Perhaps you could leave in a comment of
Code:
 * @author    Jason E. Sweat
in the function doc block, and I would be interested in hearing about any use in a open source project.
sweatje is offline   Reply With Quote
Old Feb 5, 2004, 11:02   #22
Widow Maker
Non-Member
 
Join Date: Jan 2004
Location: Planet Earth
Posts: 1,807
No problem
Widow Maker is offline   Reply With Quote
Reply

Bookmarks

« Previous Thread | Next Thread »

Thread Tools
Display Modes

 
Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Sponsored Links
 
Forum Jump


All times are GMT -7. The time now is 17:21.


Powered by vBulletin® Version 3.7.1
Copyright ©2000 - 2009, Jelsoft Enterprises Ltd.
Copyright 1998-2009, SitePoint Pty Ltd. All Rights Reserved