当前位置: 首页 > 知识库问答 >
问题:

Laravel雄辩找到复合密钥

司空默
2023-03-14

我最近开始使用Laravel 5作为框架。到目前为止,一切都是完全直截了当的,用它工作很好。然而,目前我遇到了一些关于我雄辩模型的麻烦。

数据库表报告具有以下架构:

| id | group_id | score | ... |

group_id是引用表的外键。此表的主键是idgroup_id的组合。id也不会自动增加,因为它是一个外部id,我正在使用它来简化内部处理。

每个外部id可以对我的每个组存在一次,并且对每个组都有不同的分数,因此有复合主键。

访问某个页面时,我希望从外部数据源获取最新记录,并将其与相应的数据库行匹配。如果它们不存在,我想创造它们。

这条路线的当前代码是:

public function showReports ($id)
{
   $group = Group::findOrFail($id);

   foreach ($group->getLatestReports(20) as $reportElement)
   {
       $report = Report::find($reportElement['id']);
       if (is_null($report))
       {
           $report = new Report;
           // Fill values ...
           $report->save();
       }
   }
}

这显然没有达到预期效果,因为它只查找id
::find($reportElement['id'])),而不查找组id。和往常一样,我的问题的答案可能非常简单,但我现在似乎找不到答案。


共有2个答案

盛建德
2023-03-14

您可以创建一个Trait MutiPrimaryKey,然后扩展getKey并查找方法: 1)在应用\类\数据库中创建以下文件MultiPrimaryKey.php

<?php

namespace App\Classes\Database;

use Illuminate\Database\Eloquent\Builder;

trait MultiPrimaryKey {

    protected function setKeysForSaveQuery(Builder $query)
    {
        $keys = $this->getKeyName();
        if(!is_array($keys)){
            return parent::setKeysForSaveQuery($query);
        }

        foreach($keys as $keyName){
            $query->where($keyName, '=', $this->getKeyForSaveQuery($keyName));
        }

        return $query;
    }

    protected function getKeyForSaveQuery($keyName = null)
    {
        if(is_null($keyName)){
            $keyName = $this->getKeyName();
        }

        if (isset($this->original[$keyName])) {
            return $this->original[$keyName];
        }

        return $this->getAttribute($keyName);
    }

    public function getKey()
    {
        $keys = $this->getKeyName();
        if(!is_array($keys)){
            return parent::getKey();
        }

        $pk = [];

        foreach($keys as $keyName){
            $pk[$keyName] = $this->getAttribute($keyName);
        }

        return $pk;
    }

    public function find($id, $columns = ['*'])
    {
        if (is_array($id) || $id instanceof Arrayable) {
            $out = null;
            foreach ($id as $key => $value) {
                //echo "{$key} => {$value} ";
                if ($out == null)
                {
                    $out = $this->where($key, $value);
                }
                else
                {
                    $out = $out->where($key, $value);
                }
            }

            return $out->first($columns);
        }

        return $this->whereKey($id)->first($columns);
    }

}

然后必须为自定义关系初始化:2)在App\Classes\Database中创建以下文件HasMultiPKRelationships.php

<?php

namespace App\Classes\Database;

use App\Classes\Database\Eloquent\Relations\BelongsToMultiPK;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

trait HasMultiPKRelationships {

    public function belongsTo($related, $foreignKey = null, $ownerKey = null, $relation = null)
    {
        if ($relation === null) {
            $relation = $this->guessBelongsToRelation();
        }

        $instance = $this->newRelatedInstance($related);

        if ($foreignKey === null) {
            $foreignKey = Str::snake($relation) . '_' . $instance->getKeyName();
        }

        $ownerKey = $ownerKey ?: $instance->getKeyName();

        if ( is_array($ownerKey))
        {
            return new BelongsToMultiPK($instance->newQuery(), $this, $foreignKey, $ownerKey, $relation);
        }
        else
        {
            return new BelongsTo($instance->newQuery(), $this, $foreignKey, $ownerKey, $relation);
        }
    }
}

然后,您需要在App\Classes\Database\Eloquent\relationship中使用自定义BelongsTo 3)创建以下文件BelongsToMultiPK.php

<?php

namespace App\Classes\Database\Eloquent\Relations;

use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Relations\Concerns\SupportsDefaultModels;

class BelongsToMultiPK extends BelongsTo
{

    public function __construct(Builder $query, Model $child, $foreignKey, $ownerKey, $relation)
    {
        parent::__construct($query, $child, $foreignKey, $ownerKey, $relation);
    }

    public function addConstraints()
    {
        if (static::$constraints) {
            // For belongs to relationships, which are essentially the inverse of has one
            // or has many relationships, we need to actually query on the primary key
            // of the related models matching on the foreign key that's on a parent.
            $table = $this->related->getTable();

            if (! is_array($this->ownerKey) )
            {
                $this->query->where($table.'.'.$this->ownerKey, '=', $this->child->{$this->foreignKey});
            }
            else
            {
                foreach ($this->ownerKey as $key)
                {
                    $this->query->where($table.'.'.$key, '=', $this->child->{$this->foreignKey}[$key]);
                }
            }                   
        }
    }
}
冉俊德
2023-03-14

Model::find仅适用于单列键。您可以向它传递一个数组,但这只会使它查找多行。

您需要将两个链接在一起,其中,以进行查询:

$report = Report::where('id', '=', $reportElement['id'])
                ->where('group_id', '=', $group->id)
                ->first();
 类似资料:
  • 我正在用Laravel 5.2开发一个Web应用程序,但有一个问题我无法解决。 我有一个扩展了雄辩模型的模型,但当我试图输出带有“where”的数据库表时,例如 它返回一个包含许多信息的集合,这些信息此时对我来说无用,比如“守卫”、“键入”...我的表的数据在“属性”下。遵循laravel的指南,我看到每个人都像我一样简单地使用它,然后用

  • 嘿,伙计们,我是拉威尔的新朋友。我有这张桌子 我如何能够获取每个科目的is_correct列计数? 谢谢伙计们!

  • 我有一个搜索功能在我的应用程序,将搜索一个“广泛的”搜索词的几个列或一个定义的列作为用户选择。我还有一个outser语句,用于搜索公司id(多租户应用程序)和分配的subcompany_id,它们都属于用户。 当我搜索时,我得到了所有的结果,它没有使用与用户相关的company_id或subcompany_id。我发现它在语句括号内使用subcompany_id,而不是在括号外。 此代码返回以下查

  • 我有三种模式——博客、帖子、评论。博客有很多帖子,帖子有很多评论 当我写作时 它会给所有的博客发帖子和评论。但我将如何获得那些由管理员用户创建的博客,即评论表中的用户id。在哪里写入

  • 我是新来的拉威尔,我曾在codeigniter工作。我对雄辩的ORM概念着迷。我有一个关于雄辩能力的一般性问题。ORM的功能是什么,我的意思是我们可以获得相关表行的级别。如果你看“http://four.laravel.com/docs/eloquent#relationships 一对一 一对多 多对多 多态关系 在我看来,“一对一”意味着一级。表1表2

  • 在有说服力的ORM上,是否有一种较短的方法在Laravel中插入数据? 目前我正在这样做: 就像你看到的,所有的列都像属性一样命名。 我知道您可以将对象与all()函数和fetch()一起使用。但是我从另一个对象(soap服务器)获取数据。 有没有办法转换这个?也许在模型上?