Page 3 of 4
Posted: Sun Mar 11, 2007 10:53 pm
by feyd
arborint wrote:But your constructor is not really returning anything -- new is.
Are you agreeing with me?
-------
Here's another potential example Kieran (unrelated to
my above comments.)
Code: Select all
<?php
class foo
{
private $args;
protected function __construct()
{
// do some stuff
list( $this->args ) = func_get_args();
}
public static function makeInstance()
{
return new foo( func_get_args() );
}
public function __toString()
{
return 'hi: ' . implode( ', ', $this->args );
}
public function doStuff()
{
echo 'I\'m inside a method! (' . __FUNCTION__ . '())' . PHP_EOL;
return $this;
}
}
function foo()
{
$args = func_get_args();
return call_user_func_array( array( 'foo', 'makeInstance' ), $args);
}
$foo = foo('a','b','c')->doStuff();
echo $foo;
?>
outputs
Code: Select all
I'm inside a method! (doStuff())
hi: a, b, c
Posted: Mon Mar 12, 2007 1:30 am
by Christopher
feyd wrote:Are you agreeing with me?

Well, I almost always agree with you.

Sorry, I meant to quote Kieran. I edited my post.
Posted: Mon Mar 12, 2007 10:27 am
by Kieran Huggins
I think I've got it now... I was using return as flow control structure and I shouldn't have been -- thanks guys!
Posted: Tue Mar 13, 2007 6:08 am
by Ollie Saunders
return is a great flow control structure!
just use it without a parameter when inside a constructor otherwise you are going to confuse everyone... like you just did
Code: Select all
// this is perfectly legit in my mind:
public function __construct($a)
{
if ($a == 4) {
return;
}
// do stuff
}
Posted: Thu Mar 15, 2007 12:15 pm
by Kieran Huggins
ok - up for comments is the kQuery class itself (partial, but at least working):
I'm developing the data model base class that supports the expected kQuery interface (as well as auto-saving) now.
Comments? Suggestions?
Code: Select all
class kQuery{
/*
METHODS SO FAR:
add() // adds objects that match somehow
attr('name') // returns the value for the "name" attribute in the first object
attr('name','val') // sets 'name' to 'val' for ALL matched objects
size() // returns the number of objects
eq() // shrinks the kQuery object to the numbered object
gt() // shrinks the kQuery object to the numbered object UP
lt() // shrinks the kQuery object UP TO the numbered object
get() // returns a new kQuery object with the object at that position
end() // will break out of the last get() scope change
each('func_name'); // executes a function with the object as an argument
each('echo $this->value'); // creates a lambda function and executes it
each(create_function('$this','echo "this is a lambda function"')); // executes the lambda function
USAGE:
$bob = $k('dataType #id')->attr('name','bob')->attr('age','old');
// this could have been chained above as well... but whatever.
$bob->add('dataType #id2')->attr('group','seniors')->get(1)->attr('name','frank')->end()->attr('favorite food','tapioca');
// caching in the $bob variable is just a handy tool for future reference, but not necessary.
$k('dataType #id','dataType #id2')->attr('group','old fogeys')->each(create_function('','if($this->age <= 60){$this->age = "65"}'))->each('$this->age++;');
(check out those lambda functions in action!)
*/
private $_ = array();
private $__, $__parent;
function __construct(){
// no arguments? return a blank kQuery object
if(func_num_args()==0) return $this;
$a = func_get_args();
call_user_func_array(array($this,'add'),$a);
return $this;
}
public function add(){
$args = func_get_args();
foreach($args as $a){
// object (wrapping the object)
if(is_object($a)){
$this->_[] = $a;
}
// string (query)
if(is_string($a)){
// parse the query
call_user_func(array($this,'query'),$a);
}
}
return $this;
}
public function attr(){
if( func_num_args()==1 ) {
$k = func_get_arg(0);
return $this->_[0]->$k;
}else if( func_num_args()==2 ){
$k = func_get_arg(0);
$v = func_get_arg(1);
foreach((array)$this->_ as $o){
$o->$k = $v;
}
return $this;
}
}
public function size(){
return sizeof($this->_);
}
public function eq(){
$pos = func_get_arg(0);
if(!is_numeric($pos)) return false;
if( isset($this->_[$pos]) ) $this->_ = array($this->_[$pos]);
return $this;
}
public function gt(){
$pos = func_get_arg(0);
if(!is_numeric($pos)) return false;
if( isset($this->_[$pos]) ) $this->_ = array_slice($this->_,$pos);
return $this;
}
public function lt(){
$pos = func_get_arg(0);
if(!is_numeric($pos)) return false;
if( isset($this->_[$pos]) ) $this->_ = array_slice($this->_,0,$pos+1);
return $this;
}
public function get(){ // must be non-destructive
$pos = func_get_arg(0);
if(!is_numeric($pos)) return false;
if( isset($this->_[$pos]) ) $this->__ = new kQuery($this->_[$pos]);
$this->__->__parent = &$this;
return $this->__;
}
public function end(){
if($this->__parent) return $this->__parent;
return false;
}
public function each(){ // object is passed as the only argument
$args = func_get_args();
foreach((array)$this->_ as $o){
echo '<br/>';
foreach($args as $a){
// if it's a lambda function
if(strpos($a,'lambda_')=='1'){
$a($o);
continue;
}
// if it's a string of a function (ends in ; or } )
$a = trim($a);
if(strpos($a,';')==strlen($a)-1 || strpos($a,'}')==strlen($a)-1){
$a = create_function('$this',$a);
$a($o);
continue;
}
// must be the name of a function
call_user_func($a,$o);
}
}
}
/* private methods */
private function query(){
$a = func_get_arg(0);
preg_match('#(\w+)\s?(?:\#(\w+))?\s?(?:(\w*)=?(\w*))?#i',$a,$q);
//outputs:
// [0] => full string
// [1] => ThingType
// [2] => id (if any)
// [3] => attr (if any)
// [4] => val (if any)
if(empty($q[1])) dier(__FILE__.'->'.__LINE__."\n",$q);
// return a blank object of type ThingType
if(empty($q[2]) && empty($q[3]) && empty($q[4])){
$this->_[] = new $q[1];
}
// get by ID
if(!empty($q[2]) && empty($q[3]) && empty($q[4])){
$this->_[] = new $q[1]($q[2]);
}
// STILL TO IMPLEMENT (as I need them):
//
// get by attibute
// get by value
// get by attibute=value
// get by attibute!=value
// get by attibute<=value... (and others)
}
}
$k = create_function('','$args=func_get_args(); return call_user_func_array(array(new kQuery(),"__construct"),$args);');
EDITED to fix the call_user_func() error in the ->add() method...
Posted: Thu Mar 15, 2007 12:21 pm
by Ollie Saunders
Please change your constructor to this...
Code: Select all
function __construct(){
if(func_num_args()) {
$args = func_get_args();
call_user_func_array(array($this,'add'),$args);
}
}
...or we are going to have to have the same discussion all over again.
OK I'm going to carry on reading your code now...back soon.
Posted: Thu Mar 15, 2007 12:31 pm
by Ollie Saunders
kQuery::add() wrote:Code: Select all
if(is_string($a)){
// parse the query
call_user_func_array(array($this,'query'),$a);
}
You've just proven that $a is a string but you are using it as if it is an array.
Code: Select all
private function query(){
$a = func_get_arg(0);
why not
same applies to several other methods.
I'll try and run this when I get home because its pretty intriguing. Also the code is quite confusing:
Code: Select all
private $_ = array();
private $__, $__parent;
What exactly are those storing? I actually loled at this line
Posted: Thu Mar 15, 2007 1:03 pm
by Kieran Huggins
ole wrote:Please change your constructor to this...
Code: Select all
function __construct(){
if(func_num_args()) {
$args = func_get_args();
call_user_func_array(array($this,'add'),$args);
}
}
...or we are going to have to have the same discussion all over again.
OK I'm going to carry on reading your code now...back soon.
translation: "am I gonna have to come down there and slap you silly?"
I need to return the object to make it chainable, and it doesn't seem to break anything.. do you have a chainable alternative in mind?
ole wrote:kQuery::add() wrote:Code: Select all
if(is_string($a)){
// parse the query
call_user_func_array(array($this,'query'),$a);
}
You've just proven that $a is a string but you are using it as if it is an array.
oops... changed to the regular call_user_func();
ole wrote:
Code: Select all
private function query(){
$a = func_get_arg(0);
why not
same applies to several other methods.
Just getting into the habit of accepting variable numbers of arguments.
ole wrote:I'll try and run this when I get home because its pretty intriguing. Also the code is quite confusing:
Code: Select all
private $_ = array();
private $__, $__parent;
What exactly are those storing? I actually loled at this line
yeah.... they are a bit ambiguous. Just made the vars shorter, but I should have expanded them:
$_ is an array of matching data objects
$__ is a single object matched by a non-destructive method ( like get() )
$__parent is the reference to the parent kQuery object from within a non-destructively matched data object
Thanks ole -- your input is greatly appreciated!

Posted: Thu Mar 15, 2007 2:03 pm
by Ollie Saunders
Thanks ole -- your input is greatly appreciated!
I might have been a bit overly critical actually. I dunno. I was a bit annoyed with someone when I wrote that.
I need to return the object to make it chainable, and it doesn't seem to break anything.. do you have a chainable alternative in mind?
Err, OK I take that back. I would then recommend explicitly commenting the reasoning behind it - docblocks on top of each method would be a good idea in general.
Posted: Thu Mar 15, 2007 2:16 pm
by Kieran Huggins
No worries
I've always been terrible about structured commenting - I will start doing that now!
Posted: Tue Apr 17, 2007 5:43 pm
by Luke
any news on this? Seems really cool.
Posted: Tue Apr 17, 2007 9:15 pm
by Kieran Huggins
hmmm.... let's see.
I've broken down the kQuery conceptually into two pieces: the selector/container (the kQuery) and the data object parent (kDO).
Data objects are loaded into the $_SESSION['kDO'] array and then passed around by reference to save memory/duplication as well as preserve "congruity?".
The last session I spent working on it I was wrestling with how to link data objects together, and how to avoid auto-loading the whole chain every time an object is loaded. My general plan was to load objects when the first get/set/method is run on them, thereby not loading unneeded objects.
I still don't feel
completely satisfied with my solution, but as I work it out in my spare time (which has been rather limited lately

) it's all coming together!
Posted: Tue Apr 17, 2007 9:26 pm
by John Cartwright
Keep it it up! I know I am patiently awaiting some results

Posted: Wed Apr 18, 2007 10:31 am
by RobertGonzalez
I am rather interested in seeing this as well.
Posted: Wed Apr 18, 2007 4:15 pm
by Kieran Huggins
wow - I sure hope I don't disappoint you guys with the results! Thanks for the encouragement
