检查实体是不是在外部表中被引用并获取实体

Posted

技术标签:

【中文标题】检查实体是不是在外部表中被引用并获取实体【英文标题】:Check whether entity is referenced in a foreign table and get it entities检查实体是否在外部表中被引用并获取实体 【发布时间】:2016-12-23 17:52:27 【问题描述】:

有没有办法检查一个实体是否在外部表中被引用(检查外键关系是否存在)并从这些相关的外部表中获取实体或 id?

情况如下:我有一堆实体要删除。但其中一些可以在其他表中引用。我正在以一种通用的方式工作,所以我不知道我正在使用哪个模型,也不知道它有什么链接。我想要的是过滤这些无法删除的实体,并从与我正在工作的模型关联的外部表中获取实体或 ID,以便在处理后显示它们。

代码基本上是这样的:

public function removeEntities($table_alias, $data)
    $data = $this->checkData($data); //do some work...
    $table_object = TableRegistry::get($table_alias);

    // here I'd like to get the entities or ids from tables related to $table_object that can't be deleted
    $data = $this->check_relationship($table_object, $data);

    $table_object->deleteAll(["common_index IN" => $data["to_delete"]]); //remove the guys that are related to nobody
    return $data["cant_delete"]; //return the foreign entities/ids which are related to entities from $table_object

如果我不清楚,请在 cmets 帮助我。我很难提出这个问题。


假设我正在使用Companies,我必须删除其中一些:

我有一个要删除的公司列表,但我可以只删除与WorkersClients 无关的公司。另外,我想检索链接的WorkersClients

【问题讨论】:

您可能想查看information_schema 【参考方案1】:

这是我为此编写的函数:

    /**
     * Use model associations to determine whether a record can be deleted.
     *
     * @param mixed $id The id of the record to delete
     * @param array $ignore Optional list of models to ignore
     * @param array $ignoreDeep Optional list of models to ignore IF they themselves have no dependencies
     * @return mixed Text list of dependencies found, or false if none
     */
    public function dependencies($id, array $ignore = [], array $ignoreDeep = []) 
            if ($id === null) 
                    return false;
            

            $dependencies = [];
            $associations = $this->associations();

            foreach ($associations->type('BelongsToMany') as $association) 
                    $class = $association->name();
                    $foreign_key = $association->foreignKey();
                    $through = $association->junction()->alias();
                    $dependent = $association->junction()->find()->where(["$through.$foreign_key" => $id]);

                    $association_conditions = $association->conditions();
                    if (!empty($association_conditions)) 
                            $dependent->andWhere($association_conditions);
                    

                    if (in_array($class, $ignoreDeep) || array_key_exists($class, $ignoreDeep)) 
                            foreach ($dependent->extract($association->targetForeignKey())->toArray() as $deepId) 
                                    if (array_key_exists($class, $ignoreDeep)) 
                                            $deep = $association->dependencies($deepId, $ignoreDeep[$class]);
                                     else 
                                            $deep = $association->dependencies($deepId);
                                    
                                    if ($deep) 
                                            $dependencies[] = __('0 1 (with 2)', __(Inflector::delimit(Inflector::singularize($class), ' ')), $deepId, $deep);
                                    
                            
                     else if (!in_array($class, $ignore)) 
                            if ($dependent->count() > 0) 
                                    $dependencies[] = $dependent->count() . ' ' . __(Inflector::delimit($class, ' '));
                            
                    

                    // BelongsToMany associations also create HasMany associations for the join tables.
                    // Ignore them when we get there.
                    $ignore[] = $through;
            

            foreach ($associations->type('HasMany') as $association) 
                    $class = $association->name();
                    $foreign_key = $association->foreignKey();
                    $dependent = $association->target()->find()->where(["$class.$foreign_key" => $id]);

                    $association_conditions = $association->conditions();
                    if (!empty($association_conditions)) 
                            $dependent->ansWhere($association_conditions);
                    

                    if (in_array($class, $ignoreDeep) || array_key_exists($class, $ignoreDeep)) 
                            foreach ($dependent->extract($association->primaryKey())->toArray() as $deepId) 
                                    if (array_key_exists($class, $ignoreDeep)) 
                                            $deep = $association->dependencies($deepId, $ignoreDeep[$class]);
                                     else 
                                            $deep = $association->dependencies($deepId);
                                    
                                    if ($deep) 
                                            $dependencies[] = __('0 1 (with 2)', __(Inflector::delimit(Inflector::singularize($class), ' ')), $deepId, $deep);
                                    
                            
                     else if (!in_array($class, $ignore)) 
                            if ($dependent->count() > 0) 
                                    $dependencies[] = $dependent->count() . ' ' . __(Inflector::delimit($class, ' '));
                            
                    
            

            if (!empty($dependencies)) 
                    return implode(', ', $dependencies);
            
            return false;
    

【讨论】:

以上是关于检查实体是不是在外部表中被引用并获取实体的主要内容,如果未能解决你的问题,请参考以下文章

用于向表中添加新行的存储过程,它检查值以验证它们在外部表上的值

Redshift Spectrum 是不是允许您在外部表上添加列

使用外键发布新实体会导致创建另一个外部实体而不是引用现有实体

从一个表中选择所有元素,并检查它们是不是与另一个表匹配

Greenplum:获取通过外部表处理的文件名

在 hive 的外部表中创建分区