Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 拉威尔与关系_Php_Arrays_Laravel - Fatal编程技术网

Php 拉威尔与关系

Php 拉威尔与关系,php,arrays,laravel,Php,Arrays,Laravel,我正在制作一个调查网站,用户可以从0到10提供答案。 我在试验类型转换将所有问题和答案存储在一行中 这是数据库中“分数”字段的外观 {"5":8,"6":8} 这是意料之中的。“5”和“6”是问题的ID,8是用户提供的分数 我想知道是否有可能询问答案,但包括与问题的关系。我希望看到以下结果 {"5" => {"question: ...", "answer: ..."} 所以我的问题是:是否有可能对数组施放,但在Laravel中包含关系?或者我需要循环数组并获取每行的问题数据 谢谢大家

我正在制作一个调查网站,用户可以从0到10提供答案。 我在试验类型转换将所有问题和答案存储在一行中

这是数据库中“分数”字段的外观

{"5":8,"6":8}
这是意料之中的。“5”和“6”是问题的ID,8是用户提供的分数

我想知道是否有可能询问答案,但包括与问题的关系。我希望看到以下结果

{"5" => {"question: ...", "answer: ..."}
所以我的问题是:是否有可能对数组施放,但在Laravel中包含关系?或者我需要循环数组并获取每行的问题数据


谢谢大家!

您可以使用自定义访问器和变异器执行任何操作,但我不建议将关系存储在数据库中。您不希望在其中引用可能独立更改的整个对象,因此请将其保留为ids,并在从db获取分数后装饰输出

public function getScoresAttribute($value)
{
    // if using casts to array, this should already be done
    $scores = json_decode($value, true);

    $questions = Question::whereIn('id', array_keys($scores))->get();
    $rs = [];

    $questions->each(function($q) use ($rs, $scores) {
        $rs[$q->id] = [
            'question' => $q->toArray(),
            'answer'   => $scores[$q->id],
        ];
    });

    return $rs;
}
现在,您可以执行以下操作:

dd($survey->scores);

你会得到修饰过的数据。

@Robert你的答案是我以前的解决方案。现在,我有了一个新的解决方案!这是我的答案

我们需要为Foo模型创建一个新特性。首先在laravel的“应用”文件夹下创建“关系”和“关系”文件夹。“关系”文件夹位于“关系”文件夹内

这个答案只是支持一维数组关系。您可以编辑此“完美…”

    <?php

    namespace App\Models;

    use App\Relations\HasBarRelations;
    use Illuminate\Database\Eloquent\Model;
    use App\Models\Bar;

    class Foo extends Model
    {
        use HasBarRelations; // Trait

        protected $table = "foo";
        protected $fillable = ["bar"];

        protected $casts = [
            "bar" => "array" // Array cast
        ];

        public function bar()
        {
            return $this->belongsToBar(Bar::class, "id", "bar"); // Relationship
        }
    }

“app/Relations/Relations”最后,这是完整的文件夹路径结构

这是“app/Models/Foo.php”模型文件源。

    <?php

    namespace App\Models;

    use App\Relations\HasBarRelations;
    use Illuminate\Database\Eloquent\Model;
    use App\Models\Bar;

    class Foo extends Model
    {
        use HasBarRelations; // Trait

        protected $table = "foo";
        protected $fillable = ["bar"];

        protected $casts = [
            "bar" => "array" // Array cast
        ];

        public function bar()
        {
            return $this->belongsToBar(Bar::class, "id", "bar"); // Relationship
        }
    }


我认为这是不可能的。我认为您应该遍历数组并使用
Question::find($id)
    <?php

    namespace App\Relations\Relation;

    use Closure;
    use Illuminate\Database\Eloquent\Relations\Relation;
    use Illuminate\Database\Eloquent\Builder;
    use Illuminate\Database\Eloquent\Collection;
    use Illuminate\Database\Eloquent\Model;

    class BarRelation extends Relation
    {
        /**
         * The baseConstraints callback
         *
         * @var string
         */
        protected $foreignKey;
        protected $localKey;

        /**
         * Create a new belongs to relationship instance.
         *
         * @param Builder $query
         * @param Model $parent
         * @param string $foreignKey
         * @param $localKey
         */
        public function __construct(Builder $query, Model $parent, $foreignKey, $localKey)
        {
            $this->foreignKey = $foreignKey;
            $this->localKey = $localKey;

            parent::__construct($query, $parent);
        }

        /**
         * Set the base constraints on the relation query.
         *
         * @return void
         */
        public function addConstraints()
        {
            if (static::$constraints) {
                $this->query->where($this->foreignKey, '=', $this->getParentKey());

                $this->query->whereNotNull($this->foreignKey);
            }
        }

        /**
         * Get the key value of the parent's local key.
         *
         * @return mixed
         */
        public function getParentKey()
        {
            return $this->parent->getAttribute($this->localKey);
        }

        /**
         * Set the constraints for an eager load of the relation.
         *
         * @param  array  $models
         * @return void
         */
        public function addEagerConstraints(array $models)
        {
            $key = $this->related->getTable().'.'.$this->foreignKey;

            $whereIn = $this->whereInMethod($this->related, $this->foreignKey);

            $this->query->{$whereIn}($key, $this->getEagerModelKeys($models));
        }

        /**
         * Gather the keys from an array of related models.
         *
         * @param  array  $models
         * @return array
         */
        protected function getEagerModelKeys(array $models)
        {
            $keys = [];
            // First we need to gather all of the keys from the parent models so we know what
            // to query for via the eager loading query. We will add them to an array then
            // execute a "where in" statement to gather up all of those related records.
            foreach ($models as $model) {
                if (is_array($model->{$this->localKey}) && count($model->{$this->localKey}) > 0) {
                foreach($model->{$this->localKey} as $ids){
                        $keys[] = $ids;
                    }
                }
            }
            // If there are no keys that were not null we will just return an array with null
            // so this query wont fail plus returns zero results, which should be what the
            // developer expects to happen in this situation. Otherwise we'll sort them.
            if (count($keys) === 0) {
                return [null];
            }

            sort($keys);

            return array_values(array_unique($keys));
        }

        /**
         * Initialize the relation on a set of models.
         *
         * @param  array   $models
         * @param  string  $relation
         * @return array
         */
        public function initRelation(array $models, $relation)
        {
            foreach ($models as $model) {
                $model->setRelation($relation, $this->related->newCollection());
            }

            return $models;
        }

        /**
         * Match the eagerly loaded results to their parents.
         *
         * @param  array   $models
         * @param Collection $results
         * @param  string  $relation
         * @return array
         */
        public function match(array $models, Collection $results, $relation)
        {
            return $this->matchOneOrMany($models, $results, $relation, 'one');
        }

        /**
         * Build model dictionary keyed by the relation's foreign key.
         *
         * @param Collection $results
         * @return array
         */
        protected function buildDictionary(Collection $results)
        {
            $foreign = $this->foreignKey;

            return $results->mapToDictionary(function ($result) use ($foreign) {
                    return [$result->{$foreign} => $result];
            })->all();
        }

        protected function getRelationValue(array $dictionary, $key, $type)
        {
            $value = $dictionary[$key];

            return $type === 'one' ? reset($value) : $this->related->newCollection($value);
        }

        protected function matchOneOrMany(array $models, Collection $results, $relation, $type)
        {
            $dictionary = $this->buildDictionary($results);

            if(count($dictionary) > 0){
                $data = [];
                foreach ($models as $model) {
                    foreach($model->getAttribute($this->localKey) as $key){
                        if (array_key_exists($key, $dictionary)) {
                            $data[] = $this->getRelationValue($dictionary, $key, $type);
                                $model->setRelation(
                                $relation, collect(array_unique($data))
                            );
                        }
                    }
                }
            }

            return $models;
        }

        /**
         * Get the results of the relationship.
         *
         * @return mixed
         */
        public function getResults()
        {
            return $this->get();
        }

        /**
         * Execute the query as a "select" statement.
         *
         * @param  array  $columns
         * @return Collection
         */
        public function get($columns = ['*'])
        {
            // First we'll add the proper select columns onto the query so it is run with
            // the proper columns. Then, we will get the results and hydrate out pivot
            // models with the result of those columns as a separate model relation.
            $columns = $this->query->getQuery()->columns ? [] : $columns;

            if ($columns == ['*']) {
                $columns = [$this->related->getTable().'.*'];
            }

            $builder = $this->query->applyScopes();

            $models = $builder->addSelect($columns)->getModels();

            // If we actually found models we will also eager load any relationships that
            // have been specified as needing to be eager loaded. This will solve the
            // n + 1 query problem for the developer and also increase performance.
            if (count($models) > 0) {
                $models = $builder->eagerLoadRelations($models);
            }

            return $this->related->newCollection($models);
        }
    }
$foo = Foo::with(["bar"])->where("id", 1)->first();
$bars = $foo->bar(); // Result is the Eloquent Collection!
$bar = $bars->first(); // Bar::class