Framework  3.9
InnerJoin Class Reference

This class is used to programmatically perform inner join queries across multiple objects. More...

+ Inheritance diagram for InnerJoin:
+ Collaboration diagram for InnerJoin:

Public Member Functions

 InnerJoin ($tag="join")
 Create a new InnerJoin object. More...
 
 generateQuery ($constraints="", $countOnly=false)
 
- Public Member Functions inherited from AbstractJoin
 add ($class)
 Adds a class to the join definition. More...
 
 setFilter ($class, $filter)
 Sets an InclusionFilter or ExclusionFilter on the specified class. More...
 
 constrain ($class, $constraint)
 Sets a query constraint on the given class. More...
 
 excludeKeyFromJoin ($class, $key)
 By default joins are generated following the "most restrictive search" principle. More...
 
 xref ($xref, $xrefFieldMaps=null)
 Adds a cross-reference class to the join definition. More...
 
 pseudo ($class, $items, $indexField)
 Registers a class and indexed array as a pseudo-join item. More...
 
 count ($constraints="", $countExpr=true)
 
 query ($constraints="", $page=-1, $size=-1)
 Performs a query against the database returning an array of JoinResult objects. More...
 
 iteratedQuery ($constraints="")
 Performs a query against the database returning an iterator of JoinResult objects. More...
 
 indexedQuery ($constraints="", $indexBy="")
 Performs a query against the database, returning an array of DataItem objects of the specified class, indexed by a particular field. More...
 
 groupedQuery ($constraints="", $indexBy="")
 Performs a query against the database, returning an array of arrays of DataItem objects of the specified class, grouped by a particular field. More...
 

Additional Inherited Members

- Public Attributes inherited from AbstractJoin
 $classes = array()
 The names of the DataItem classes being joined. More...
 
 $protos = array()
 Prototype instances of the DataItem classes being joined. More...
 
 $xrefs = array()
 Cross-reference classes (i.e. classes that are part of the join, but not the result) More...
 
 $xrefFieldMaps = array()
 Cross-reference field map (to support cross-referencing through fields with differing names) More...
 
 $aliases = array()
 Field aliases for output. More...
 
 $xrefAliases = array()
 Cross-reference table aliases. More...
 
 $constraints = array()
 Class-specific constraints add via the constrain() method. More...
 
 $unique = false
 true to output distinct rows only More...
 
 $tag = "join"
 XML tag name. More...
 
 $excludedKeys = array()
 
 $pseudos = array()
 Pseudo-join lookup tables. More...
 

Detailed Description

This class is used to programmatically perform inner join queries across multiple objects.

The InnerJoin will automatically generate the SQL for the join based on the primary key field names of each object. In order for an object to be successfully joined, it must contain a primary key with the same name as a foreign key in another participating object (or a foreign key that matches another object's primary key).

Results are returned as an array of JoinResult composite objects. The matching row from each object in the join as added as a sub-object of the JoinResult with the field name being the class name of the object.

Definition at line 647 of file join.inc.

Member Function Documentation

◆ generateQuery()

InnerJoin::generateQuery (   $constraints = "",
  $countOnly = false 
)

Reimplemented from AbstractJoin.

Definition at line 658 of file join.inc.

659  {
660  $tables = "";
661  $fields = "";
662  $alias = "";
663  for($i = 0; $i < count($this->classes); ++$i)
664  {
665  $class = $this->classes[$i];
666  $proto =& $this->protos[$class];
667 
668  $alias = "t$i";
669  $this->aliases[$proto->table] = $alias;
670 
671  if (array_key_exists($class, $this->constraints))
672  {
673  $c = $this->constraints[$class];
674 
675  foreach($proto->getFields() as $field => $type)
676  {
677  $c = preg_replace("/([\s\‍(])(".$field.")\\b/", "$1t$i.$2", $c);
678  }
679 
680  $c = "(".preg_replace("/^\\s*(WHERE\\s+|AND\\s+|OR\\s+)/i", "", $c).")";
681 
682  $this->constraints[$class] = $c;
683  }
684 
685  if ($tables) $tables .= ", ";
686  $tables .= "{$proto->table} $alias";
687 
688  $f = $proto->getFieldList($alias);
689  if ($fields && $f) $fields .=", ";
690  $fields .= $f;
691  }
692 
693  for($i = 0; $i < count($this->xrefs); ++$i)
694  {
695  $xref = $this->xrefs[$i];
696 
697  $alias = "x$i";
698  $this->xrefAliases[$xref->table] = $alias;
699 
700  if ($tables) $tables .= ", ";
701  $tables .= "{$xref->table} $alias";
702  }
703 
704  if ($this->unique) $fields = "DISTINCT $fields";
705 
706  $classConstraints = implode(" AND ", array_values($this->constraints));
707 
708  if (strncmp($constraints, "WHERE", 5))
709  {
710  if ($classConstraints) $classConstraints = " AND ".$classConstraints;
711  $constraints = "WHERE 1=1 $classConstraints $constraints";
712  }
713  else
714  {
715  if ($classConstraints) $classConstraints = $classConstraints." AND ";
716  $constraints = preg_replace("/^\\s*WHERE/i", "WHERE $classConstraints", $constraints);
717  }
718 
719  $join = "";
720 
721  // Build Inner Join
722 
723  for($i = 0; $i < count($this->classes) - 1; ++$i)
724  {
725  $c = $this->classes[$i];
726  $p = $this->protos[$c];
727 
728  for ($j = $i+1; $j < count($this->classes); ++$j)
729  {
730  $d = $this->classes[$j];
731  $q = $this->protos[$d];
732 
733  if ($this->excludedKeys[$d][$q->primary_key] ||
734  $this->excludedKeys[$d][$p->primary_key])
735  {
736  continue;
737  }
738 
739  trace($p->primary_key." ".array_key_exists($p->primary_key, $q->getFields()), 5);
740  trace($q->primary_key." ".array_key_exists($q->primary_key, $p->getFields()), 5);
741 
742  if (array_key_exists($p->primary_key, $q->getFields()))
743  {
744  $join .= " AND t$i.{$p->primary_key}=t$j.{$p->primary_key}";
745  }
746  else if (array_key_exists($q->primary_key, $p->getFields()))
747  {
748  $join .= " AND t$i.{$q->primary_key}=t$j.{$q->primary_key}";
749  }
750 
751  }
752 
753  }
754 
755  // Alias main table fields
756 
757  for($i = 0; $i < count($this->classes); ++$i)
758  {
759  $c = $this->classes[$i];
760  $p = $this->protos[$c];
761  foreach($p->getFields() as $field => $type)
762  {
763  $constraints = preg_replace("/([\s\‍(])(".$field.")\\b/", "$1t$i.$2", $constraints);
764  $constraints = preg_replace("/{$c}\.({$field})\\b/", "t$i.$1", $constraints);
765  }
766 
767  foreach($p->calculatedFields as $field => $expr)
768  {
769  foreach($p->getFields() as $f => $type)
770  {
771  $expr = preg_replace("/([\s\‍(])(".$f.")\\b/", "$1t$i.$2", $expr);
772  }
773 
774  $constraints = preg_replace("/([\s\‍(])(".$field.")\\b/", " $expr", $constraints);
775  }
776  }
777 
778  // Handle XRefs
779 
780  foreach($this->xrefs as $xref)
781  {
782  $map = $this->xrefFieldMaps[$xref->table];
783 
784  foreach($this->protos as $p)
785  {
786  $pk = $p->primary_key;
787  $xk = ($map && array_key_exists($pk, $map)) ? $map[$pk] : $pk;
788 
789  if ($xref->hasField($xk))
790  {
791  $xa = $this->xrefAliases[$xref->table];
792  $ta = $this->aliases[$p->table];
793 
794  $join .= " AND $xa.{$xk}=$ta.{$pk}";
795  }
796  }
797  }
798 
799  $matches = array();
800 
801  $orderBy = "";
802  if (preg_match("/^(.*?)(ORDER\\s+BY.*)/i", $constraints, $matches))
803  {
804  $constraints = $matches[1];
805  $orderBy = $matches[2];
806  }
807  else if (preg_match("/^(.*?)(LIMIT.*)/i", $constraints, $matches))
808  {
809  $constraints = $matches[1];
810  $orderBy = $matches[2];
811  }
812 
813  if ($countOnly) $fields = (is_bool($countOnly)) ? "COUNT(1) as result" : "COUNT($countOnly) as result";
814 
815  $query = "SELECT $fields FROM $tables $constraints $join $orderBy";
816 
817  trace("InnerJoin::generateQuery() - $query", 3);
818 
819  return $query;
820  }
$constraints
Class-specific constraints add via the constrain() method.
Definition: join.inc:242
count($constraints="", $countExpr=true)
Definition: join.inc:356
trace($msg, $lvl=3, $callStack=null)
Send output to the trace log.
Definition: functions.inc:1010

◆ InnerJoin()

InnerJoin::InnerJoin (   $tag = "join")

Create a new InnerJoin object.

Definition at line 653 of file join.inc.

654  {
655  $this->tag = $tag;
656  }
$tag
XML tag name.
Definition: join.inc:245

The documentation for this class was generated from the following file: