示例#1
0
 public static function define($relationship, $options = null, $relationRef = null, $manyToManyPartial = null)
 {
     // Keep track of relationships that have already previously been processed.
     // Recursion can occur when defining M:M relationships, so this will prevent system hang-ups.
     static $processedRelationships = [];
     if (in_array($relationship, $processedRelationships)) {
         return null;
     }
     $processedRelationships[] = $relationship;
     // Vars
     if ($relationRef === null) {
         $relationRef = self::REF_DEFAULT;
     }
     // If more than one relationship is being defined here (ie. 1:M:1), break it down into
     // single relationships and parse each one separately.
     // Also, the resulting M:M relationship is defined.
     if (substr_count($relationship, ":") > 1) {
         // Extract components
         $components = explode(":", $relationship);
         $mSource = preg_replace("/\\(.+\$/", "", $components[0]);
         $mLink = preg_replace("/\\(.+\$/", "", $components[1]);
         $mTarget = preg_replace("/\\(.+\$/", "", $components[2]);
         $mSourceKey = $mTargetKey = null;
         if (strpos($mSource, ".")) {
             list($mSource, $mSourceKey) = explode(".", $mSource);
         }
         if (strpos($mTarget, ".")) {
             list($mTarget, $mTargetKey) = explode(".", $mTarget);
         }
         $mLinkSourceKey = Inflector::modelName_dbTableName($mSource) . '_id';
         $mLinkTargetKey = Inflector::modelName_dbTableName($mTarget) . '_id';
         if (strpos($mSource, ".") !== false) {
             list($mSource, $mSourceKey) = explode(".", $mSource);
         }
         if (strpos($mTarget, ".") !== false) {
             list($mTarget, $mTargetKey) = explode(".", $mTarget);
         }
         if (strpos($mLink, ".") !== false) {
             list($mLink, $mLinkSourceKey, $mLinkTargetKey) = explode(".", $mLink);
         }
         // Define the resulting M:M relationship
         self::$relationships[$mSource][$mTarget][$relationRef] = new ModelRelation(['modelSource' => $mSource, 'modelTarget' => $mTarget, 'cardinality' => ModelRelation::MANY_TO_MANY, 'modelLink' => $mLink, 'nativeKey' => $mSourceKey, 'foreignKey' => $mTargetKey]);
         if ($mSource != $mTarget) {
             self::$relationships[$mTarget][$mSource][$relationRef] = new ModelRelation(['modelSource' => $mTarget, 'modelTarget' => $mSource, 'cardinality' => ModelRelation::MANY_TO_MANY, 'modelLink' => $mLink, 'nativeKey' => $mSourceKey, 'foreignKey' => $mTargetKey]);
             self::define("{$components[0]}:{$mLink}.{$mLinkSourceKey}(M)", $options, $relationRef, $mTarget);
             self::define("{$mLink}.{$mLinkSourceKey}(M):{$components[0]}", $options, $relationRef, $mTarget);
             self::define("{$mLink}.{$mLinkTargetKey}(M):{$components[2]}", $options, $relationRef, $mSource);
             self::define("{$components[2]}{$mLink}.{$mLinkTargetKey}(M)", $options, $relationRef, $mSource);
         } else {
             self::$relationships[$mSource][$mTarget][self::REF_CHILD] = new ModelRelation(['modelSource' => $mSource, 'modelTarget' => $mTarget, 'cardinality' => ModelRelation::MANY_TO_MANY, 'modelLink' => $mLink, 'reference' => self::REF_CHILD, 'nativeKey' => $mSourceKey, 'foreignKey' => $mTargetKey]);
             self::define("{$components[0]}:{$mLink}.{$mLinkSourceKey}(M)", $options, self::REF_PARENT);
             self::define("{$mLink}.{$mLinkTargetKey}(M):{$components[2]}", $options, self::REF_CHILD);
         }
         //// Define the individual relationships, ie. 1:M and M:1
         /*if($mSource!=$mTarget) {
               self::define("{$components[0]}:{$mLink}.{$mLinkSourceKey}(M)", $options, $relationRef, $mTarget);
               self::define("{$mLink}.{$mLinkSourceKey}(M):{$components[0]}", $options, $relationRef, $mTarget);
               self::define("{$mLink}.{$mLinkTargetKey}(M):{$components[2]}", $options, $relationRef, $mSource);
               self::define("{$components[2]}{$mLink}.{$mLinkTargetKey}(M)", $options, $relationRef, $mSource);
           }
           else {
               if($mLinkSourceKey==$mLinkTargetKey) {
                   $mLinkSourceKey = "src_{$mLinkSourceKey}";
                   $mLinkTargetKey = "tgt_{$mLinkTargetKey}";
               }
               //self::define("{$components[0]}:{$mLink}.{$mLinkSourceKey}(M)", $options, self::REF_PARENT);
               //self::define("{$mLink}.{$mLinkSourceKey}(M):{$components[0]}", $options, self::REF_PARENT);
               //self::define("{$mLink}.{$mLinkTargetKey}(M):{$components[2]}", $options, self::REF_CHILD);
               //self::define("{$components[2]}{$mLink}.{$mLinkTargetKey}(M)", $options, self::REF_CHILD);
           }*/
         // Result
         return null;
     }
     // Extract components of the relationship into an ordered array
     preg_match_all("/([^:]*?)\\((.*?)\\)/", $relationship, $m);
     // $m_all = $m[0];
     $m_model = $m[1];
     $m_card = $m[2];
     $m_key = [null, null];
     $limit = [null, null];
     if (strpos($m_model[0], ".") !== false) {
         list($m_model[0], $m_key[0]) = explode(".", $m_model[0]);
     }
     if (strpos($m_model[1], ".") !== false) {
         list($m_model[1], $m_key[1]) = explode(".", $m_model[1]);
     }
     // Create the ModelRelation instances
     if (!isset(self::$relationships[$m_model[0]][$m_model[1]][$relationRef])) {
         // Extract any limits imposed on the cardinality
         foreach ($m_card as $k => $v) {
             if (strpos($v, ",") !== false) {
                 $limit[$k] = (int) preg_replace("/^.*?,([0-9]+)/", "\$1", $v);
                 $m_card[$k] = preg_replace("/,.*/", "", $v);
             }
         }
         // Find the cardinality between the two Models
         $cardinalityMap = ['1:M' => ModelRelation::ONE_TO_MANY, 'M:1' => ModelRelation::MANY_TO_ONE, 'M:M' => ModelRelation::MANY_TO_MANY, '1:1' => ModelRelation::ONE_TO_ONE];
         $cardinality = $cardinalityMap[strtoupper(implode(":", $m_card))];
         $revCardinality = $cardinalityMap[strtoupper(implode(":", array_reverse($m_card)))];
         // If a M:M cardinality is defined, we need to insert a linking table with an assumed name,
         // and then define the required 1:M:1 relationship.
         // We will assume that no keys have been defined in this M:M relationship, because it doesn't
         // make sense as the Models are not directly related.
         //$linkModel = NULL;
         if ($cardinality == ModelRelation::MANY_TO_MANY) {
             $linkModel = $m_model[0] . $m_model[1];
             $relation = $m_model[0] . '(1):' . $linkModel . '(M):' . $m_model[1] . '(1)';
             self::define($relation, $options, $relationRef);
             return null;
         }
         // If a 1:1 relation is defined, change it to a 1:M,1
         if ($cardinality == self::ONE_TO_ONE) {
             $cardinality = self::ONE_TO_MANY;
             $revCardinality = self::MANY_TO_ONE;
             $limit = [1, 1];
         }
         // For recursive 1:M relationships, make sure that the definition is 1:M, not M:1
         if ($m_model[0] == $m_model[1] && $cardinality == self::MANY_TO_ONE) {
             $m_model = array_reverse($m_model);
             $cardinality = self::ONE_TO_MANY;
             $revCardinality = self::MANY_TO_ONE;
             $limit = array_reverse($limit);
             // Create the "M:1" relationship here (ref: self::REF_CHILD)
             self::$relationships[$m_model[1]][$m_model[0]][self::REF_CHILD] = new ModelRelation(['modelSource' => $m_model[1], 'modelTarget' => $m_model[0], 'cardinality' => $revCardinality, 'modelLink' => $manyToManyPartial, 'reference' => self::REF_CHILD, 'limit' => $limit[0], 'nativeKey' => $m_key[1], 'foreignKey' => $m_key[0], 'options' => $options]);
         } else {
             if ($m_model[0] == $m_model[1] && $cardinality == self::ONE_TO_MANY) {
                 // Create the "M:1" relationship here (ref: self::REF_CHILD)
                 self::$relationships[$m_model[1]][$m_model[0]][self::REF_CHILD] = new ModelRelation(['modelSource' => $m_model[1], 'modelTarget' => $m_model[0], 'cardinality' => $revCardinality, 'modelLink' => $manyToManyPartial, 'reference' => self::REF_CHILD, 'limit' => $limit[0], 'nativeKey' => $m_key[1], 'foreignKey' => $m_key[0], 'options' => $options]);
             }
         }
         // Extract options
         $options = $options === null ? null : explode(",", strtolower($options));
         // Create relationships
         self::$relationships[$m_model[0]][$m_model[1]][$relationRef] = new ModelRelation(['modelSource' => $m_model[0], 'modelTarget' => $m_model[1], 'cardinality' => $cardinality, 'modelLink' => $manyToManyPartial, 'reference' => $relationRef, 'limit' => $limit[1], 'nativeKey' => $m_key[0], 'foreignKey' => $m_key[1], 'options' => $options]);
         if ($m_model[0] != $m_model[1] && $manyToManyPartial === null) {
             self::$relationships[$m_model[1]][$m_model[0]][$relationRef] = new ModelRelation(['modelSource' => $m_model[1], 'modelTarget' => $m_model[0], 'cardinality' => $revCardinality, 'modelLink' => $manyToManyPartial, 'reference' => $relationRef, 'limit' => $limit[0], 'nativeKey' => $m_key[1], 'foreignKey' => $m_key[0], 'options' => $options]);
         }
     }
 }
示例#2
0
文件: Model.php 项目: Nessworthy/buan
 /**
  * Constructor. Never call this method directly. Instead use:
  *        Buan\Model::create()
  *
  * Prepares the Model by setting a few basic properties:
  *    - The model name
  *    - The database table name
  * - The initial primary key value(s) (if applicable)
  *
  * @param string $modelName Name of the Model you want to create (UpperCamelCaps format)
  */
 public function __construct($modelName = null)
 {
     // Store the Model's name
     // If the $modelName hasn't bee specified then we use the calling class'
     // name as the basis of the model name (basically remove the "Model" suffix)
     $this->modelName = $modelName === null ? preg_replace("/Model\$/", "", get_class($this)) : $modelName;
     // If the model isn't using it's own class, and it hasn't specified a
     // database table to use for storing it, then do some guess work based on
     // suggested conventions (ie. lower_underscored table names)
     if ($this->dbTableName === null) {
         $this->dbTableName = Inflector::modelName_dbTableName($this->modelName);
     }
     // Determine if this Model has a composite PK. This is considered the case
     // if $this->dbTablePrimaryKey has a comma-separated list of field names.
     $this->hasCompositePrimaryKey = strpos($this->getPrimaryKey(), ",") !== false;
     // Ensure the PK field(s) are preset to a NULL value.
     // SQLite requires that auto_increment fields have a NULL value in order
     // to increment correctly.
     if ($this->hasCompositePrimaryKey) {
         $keys = explode(",", $this->getPrimaryKey());
         foreach ($keys as $key) {
             $this->setPrimaryKeyValue($key, null);
         }
     } else {
         $this->setPrimaryKeyValue(null);
     }
 }