Activerecord-association:创建新对象(查找类)

时间:2012-02-14 16:25:51

标签: php phpactiverecord

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

  

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

companyobject的类是在关系中定义的,所以我认为我不应该'知道'那个类,但我应该能够让person-object为我提供一个新的类型实例公司?但我不知道如何。

这是 - 我认为 - 与New model object through an association相同的问题,但我使用的是PHPActiveRecord,而不是红宝石。

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

解决方法是直接从static $has_one数组中获取它:

$class   = $this::$has_one[1]['class_name'];
$company = new $class;

当然可以通过在数组中搜索关联名来消除硬编码的数字,但这仍然非常难看。

<小时/> 如果有人知道如何在Ruby中实现它,以及phpactiverecord实现如何不同,我可能从那里得到一些想法?

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

3 个答案:

答案 0 :(得分:4)

您还可以在关系类中使用build_association()
使用它的最简单方法是通过模型的__call,即如果你的关系类似于$person->company,那么你可以用$company = $person->build_company()

实例化公司。 请注意,这也不会使对象之间的“连接”($person->company不会被设置)。
或者,您可以使用build_company()代替create_company()保存新记录并将其链接到$ person

答案 1 :(得分:0)

  

我目前正在使用以下解决方案。相反,这是一个实际的解决方案   我在问题中提到的$has_one[1]黑客攻击。如果有的话   在phpactiverecord中的方法我会觉得非常愚蠢的暴露   msyelf。但请,请证明我很傻,所以我不需要使用它   解决方案:D

     我很傻。以下功能由create_associationname调用实现,由@Bogdan_D

回答

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

这是两个功能:

  • public function findClassByAssociation($associationName)
    • 使用您要查找的关联名称调用。
    • 检查三个静态变量(has_manybelongs_tohas_one)以获取关联
    • 如果找到关联,则
    • 调用findClassFromArray
    • 来自个人/公司示例:$person->findClassByAssociation('company');
  • private function 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;
}

答案 2 :(得分:0)

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

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;
     }
}

要使用此功能,如果您有一个人物对象并且想要一个由“公司”关系定义的对象,请使用:

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