Php Activerecord关联:创建新对象(查找类)

Php Activerecord关联:创建新对象(查找类),php,phpactiverecord,Php,Phpactiverecord,我有一个带有关系的模型,我想实例化一个关系类型的新对象 示例:一个人有一个公司,我有一个人对象:现在我 要创建公司对象 companyobject的类是在关系中定义的,因此我认为我不需要“知道”该类,但我应该能够要求person对象为我提供company类型的新实例?但我不知道怎么做 我认为,这是与相同的问题,但我使用的是,而不是ruby 这背后的原因是:我有一个抽象的超类person,两个孩子与一种类型的公司对象有他们自己的关系。我需要能够在抽象的person中实例化正确的类 解决方法是直接

我有一个带有关系的模型,我想实例化一个关系类型的新对象

示例:一个人有一个公司,我有一个人对象:现在我 要创建公司对象

companyobject的类是在关系中定义的,因此我认为我不需要“知道”该类,但我应该能够要求person对象为我提供company类型的新实例?但我不知道怎么做

我认为,这是与相同的问题,但我使用的是,而不是ruby


这背后的原因是:我有一个抽象的超类
person
,两个孩子与一种类型的公司对象有他们自己的关系。我需要能够在抽象的person中实例化正确的类

解决方法是直接从
static$has\u one
数组中获取它:

$class   = $this::$has_one[1]['class_name'];
$company = new $class;
当然,通过在数组中搜索关联名称可以消除硬编码的数字,但这仍然非常难看


如果有人知道这是如何在Ruby中实现的,以及phpactiverecord实现的不同之处,我可能会从中得到一些想法


一些测试表明,尽管“在数组中搜索我的类名”看起来有点奇怪,但它对性能没有任何影响,而且在使用中它的功能已经足够了

我目前正在使用下面的解决方案。相反,这是一个实际的解决方案 我在问题中提到的
$has_one[1]
黑客。如果有 phpactiverecord中的方法我会觉得非常愚蠢 叶利夫女士。但请证明我很傻,这样我就不用用这个了 解决方案:D

我很傻。下面的功能是通过create_associationname调用实现的,由@Bogdan_D回答


增加了两个功能。您可能应该将它们添加到
\ActiveRecord\Model
类中。在我的例子中,在我们的类和那个模型之间有一个类,它包含像这样的额外功能,所以我把它放在那里

这是两个功能:

  • 公共函数findClassByAssociation($associationName)
    • 使用您要查找的关联的名称调用
    • 检查关联的三个静态变量(
      有多个
      属于
      有一个
    • 如果找到关联,则调用findClassFromArray
    • 从个人/公司示例:
      $person->findClassByAssociation('company')
  • 私有函数findClassFromArray($associationName,$associationArray)
    • 只是一个尝试匹配名称的辅助函数
资料来源:

/**
 * Find the classname of an explicitly defined 
 * association (has_one, has_many, belongs_to). 
 * Unsure if this works for standard associations 
 * without specific mention of the class_name, but I suppose it doesn't!
 * @todo Check if works without an explicitly set 'class_name', if not: is this even possible (namespacing?)
 * @todo Support for 'through' associations.
 * @param String $associationName the association you want to find the class for
 * @return mixed String|false if an association is found, return the class name (with namespace!), else return false
 * @see findClassFromArray 
 */
public function findClassByAssociation($associationName){
    //$class = $this::$has_one[1]['class_name'];
    $that = get_called_class();
    if(isset($that::$has_many)){
        $cl = $this->findClassFromArray($associationName,$that::$has_many);
        if($cl){return $cl;}
    }
    if(isset($that::$belongs_to)){
        $cl = $this->findClassFromArray($associationName,$that::$belongs_to);
        if($cl){return $cl;}
    }
    if(isset($that::$has_one)){
        $cl = $this->findClassFromArray($associationName,$that::$has_one);
        if($cl){return $cl;}
    }
    return false;
}

/**
 * Find a class in a php-activerecord "association-array". It probably should have a specifically defined class name!
 * @todo check if works without explicitly set 'class_name', and if not find it like standard
 * @param String $associationName 
 * @param Array[] $associationArray phpactiverecord array with associations (like has_many)
 * @return mixed String|false if an association is found, return the class name, else return false
 * @see findClassFromArray
 */
private function findClassFromArray($associationName,$associationArray){
    if(is_array($associationArray)){
        foreach($associationArray as $association){
            if($association['0'] === $associationName){
                return $association['class_name'];
            }
        }
    }
    return false;
}
我目前正在使用下面的解决方案。相反,这是一个实际的解决方案 我在问题中提到的
$has_one[1]
黑客。如果有 phpactiverecord中的方法我会觉得非常愚蠢 叶利夫女士。但请证明我很傻,这样我就不用用这个了 解决方案:D

我很傻。下面的功能是通过create_associationname调用实现的,由@Bogdan_D回答


增加了两个功能。您可能应该将它们添加到
\ActiveRecord\Model
类中。在我的例子中,在我们的类和那个模型之间有一个类,它包含像这样的额外功能,所以我把它放在那里

这是两个功能:

  • 公共函数findClassByAssociation($associationName)
    • 使用您要查找的关联的名称调用
    • 检查关联的三个静态变量(
      有多个
      属于
      有一个
    • 如果找到关联,则调用findClassFromArray
    • 从个人/公司示例:
      $person->findClassByAssociation('company')
  • 私有函数findClassFromArray($associationName,$associationArray)
    • 只是一个尝试匹配名称的辅助函数
资料来源:

/**
 * Find the classname of an explicitly defined 
 * association (has_one, has_many, belongs_to). 
 * Unsure if this works for standard associations 
 * without specific mention of the class_name, but I suppose it doesn't!
 * @todo Check if works without an explicitly set 'class_name', if not: is this even possible (namespacing?)
 * @todo Support for 'through' associations.
 * @param String $associationName the association you want to find the class for
 * @return mixed String|false if an association is found, return the class name (with namespace!), else return false
 * @see findClassFromArray 
 */
public function findClassByAssociation($associationName){
    //$class = $this::$has_one[1]['class_name'];
    $that = get_called_class();
    if(isset($that::$has_many)){
        $cl = $this->findClassFromArray($associationName,$that::$has_many);
        if($cl){return $cl;}
    }
    if(isset($that::$belongs_to)){
        $cl = $this->findClassFromArray($associationName,$that::$belongs_to);
        if($cl){return $cl;}
    }
    if(isset($that::$has_one)){
        $cl = $this->findClassFromArray($associationName,$that::$has_one);
        if($cl){return $cl;}
    }
    return false;
}

/**
 * Find a class in a php-activerecord "association-array". It probably should have a specifically defined class name!
 * @todo check if works without explicitly set 'class_name', and if not find it like standard
 * @param String $associationName 
 * @param Array[] $associationArray phpactiverecord array with associations (like has_many)
 * @return mixed String|false if an association is found, return the class name, else return false
 * @see findClassFromArray
 */
private function findClassFromArray($associationName,$associationArray){
    if(is_array($associationArray)){
        foreach($associationArray as $association){
            if($association['0'] === $associationName){
                return $association['class_name'];
            }
        }
    }
    return false;
}

在PHPActiveRecord中,您可以访问关系数组。关系应该有一个名称,您需要知道您想要的关系/关联的名称。它不需要是类名,但是您要关联的模型的类名应该在关系中明确指出。这只是一个基本示例,没有错误检查或关系数据库详细信息,如链接表或外键列名:

class Person extends ActiveRecord\Model {
    static $belongs_to = array(
                       array('company',
                                 'class_name' => 'SomeCompanyClass')
                                 );
    //general function get a classname from a relationship
    public static function getClassNameFromRelationship($relationshipName)       
       foreach(self::$belongs_to as $relationship){
          //the first element in all relationships is it's name
          if($relationship[0] == $relationshipName){
             $className = null;
                if(isset($relationship['class_name'])){
                  $className = $relationship['class_name'];
                }else{
                  // if no classname specified explicitly,
                  // assume the clasename is the relationship name
                  // with first letter capitalized
                  $className = ucfirst($relationship);
                }
                return $className               
            }
        }   
        return null;
     }
}
要使用此函数,如果您有一个person对象,并且希望使用“company”关系定义的对象,请使用:

$className = $person::getClassNameFromRelationship('company');
$company = new $className();

在PHPActiveRecord中,您可以访问关系数组。关系应该有一个名称,您需要知道您想要的关系/关联的名称。它不需要是类名,但是您要关联的模型的类名应该在关系中明确指出。这只是一个基本示例,没有错误检查或关系数据库详细信息,如链接表或外键列名:

class Person extends ActiveRecord\Model {
    static $belongs_to = array(
                       array('company',
                                 'class_name' => 'SomeCompanyClass')
                                 );
    //general function get a classname from a relationship
    public static function getClassNameFromRelationship($relationshipName)       
       foreach(self::$belongs_to as $relationship){
          //the first element in all relationships is it's name
          if($relationship[0] == $relationshipName){
             $className = null;
                if(isset($relationship['class_name'])){
                  $className = $relationship['class_name'];
                }else{
                  // if no classname specified explicitly,
                  // assume the clasename is the relationship name
                  // with first letter capitalized
                  $className = ucfirst($relationship);
                }
                return $className               
            }
        }   
        return null;
     }
}
要使用此函数,如果您有一个person对象,并且希望使用“company”关系定义的对象,请使用:

$className = $person::getClassNameFromRelationship('company');
$company = new $className();

您还可以在关系类中使用
build\u association()

最简单的使用方法是通过模型的u调用,即如果您的关系类似于
$person->company
,那么您可以使用
$company=$person->build_ucompany()实例化该公司
请注意,这也不会在对象之间建立“连接”(
$person->company
将不会被设置)

或者,您可以使用
create_company()
,而不是
build_company()
,这将保存新记录并将其链接到$person

您还可以在关系类中使用
build_association()

最简单的使用方法是通过模型的调用,即