Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.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 Laravel 5无法更新关系_Php_Laravel 5 - Fatal编程技术网

Php Laravel 5无法更新关系

Php Laravel 5无法更新关系,php,laravel-5,Php,Laravel 5,我已经尝试了无数个小时了,但仍然在更新模型关系时遇到问题,最接近的是“方法填充不存在”。错误 上市模式: class Listing extends Model { protected $fillable = [ 'uid', 'start_date',........... ]; public function locations() { retu

我已经尝试了无数个小时了,但仍然在更新模型关系时遇到问题,最接近的是“方法填充不存在”。错误

上市模式:

 class Listing extends Model
    {       
        protected $fillable = [
            'uid', 'start_date',...........
        ];     

        public function locations()
        {
            return $this->hasMany('App\ListingLocation');
        }        
    }
位置(与列表的关系-hasMany):

这将返回我的模型和关系,我可以使用dd($listing)查看它们

这将更新我的列表模型,我可以在再次调用dd($listing)后看到更改

但是,当我尝试按照以下方式填充关系时,我得到“方法填充不存在”

$listing->locations->fill($array['locations']);

如何在调用$listing->push()之前成功更新关系

将您的位置更改为单个记录,而不是集合

例如:

$listings->locations->first()->fill($array['locations']);
要填写每个记录,请使用foreach

@foreach($listings->locations as $location)
$location->fill(do_something);
@endforeach

将您的位置更改为单个记录,而不是集合

例如:

$listings->locations->first()->fill($array['locations']);
要填写每个记录,请使用foreach

@foreach($listings->locations as $location)
$location->fill(do_something);
@endforeach

最后,我创建了一个新类来扩展hasMany,它允许我按照alexweissman的说法使用sync

论坛摘录:

use Illuminate\Database\Eloquent\Relations\HasMany;

/**
 * @link https://github.com/laravel/framework/blob/5.4/src/Illuminate/Database/Eloquent/Relations/HasMany.php
 */
class HasManySyncable extends HasMany
{
    public function sync($data, $deleting = true)
    {
        $changes = [
            'created' => [], 'deleted' => [], 'updated' => [],
        ];

        $relatedKeyName = $this->related->getKeyName();

        // First we need to attach any of the associated models that are not currently
        // in the child entity table. We'll spin through the given IDs, checking to see
        // if they exist in the array of current ones, and if not we will insert.
        $current = $this->newQuery()->pluck(
            $relatedKeyName
        )->all();

        // Separate the submitted data into "update" and "new"
        $updateRows = [];
        $newRows = [];
        foreach ($data as $row) {
            // We determine "updateable" rows as those whose $relatedKeyName (usually 'id') is set, not empty, and
            // match a related row in the database.
            if (isset($row[$relatedKeyName]) && !empty($row[$relatedKeyName]) && in_array($row[$relatedKeyName], $current)) {
                $id = $row[$relatedKeyName];
                $updateRows[$id] = $row;
            } else {
                $newRows[] = $row;
            }
        }

        // Next, we'll determine the rows in the database that aren't in the "update" list.
        // These rows will be scheduled for deletion.  Again, we determine based on the relatedKeyName (typically 'id').
        $updateIds = array_keys($updateRows);
        $deleteIds = [];
        foreach ($current as $currentId) {
            if (!in_array($currentId, $updateIds)) {
                $deleteIds[] = $currentId;
            }
        }

        // Delete any non-matching rows
        if ($deleting && count($deleteIds) > 0) {
            $this->getRelated()->destroy($deleteIds);

            $changes['deleted'] = $this->castKeys($deleteIds);
        }

        // Update the updatable rows
        foreach ($updateRows as $id => $row) {
            $this->getRelated()->where($relatedKeyName, $id)
                 ->update($row);
        }

        $changes['updated'] = $this->castKeys($updateIds);

        // Insert the new rows
        $newIds = [];
        foreach ($newRows as $row) {
            $newModel = $this->create($row);
            $newIds[] = $newModel->$relatedKeyName;
        }

        $changes['created'][] = $this->castKeys($newIds);

        return $changes;
    }


    /**
     * Cast the given keys to integers if they are numeric and string otherwise.
     *
     * @param  array  $keys
     * @return array
     */
    protected function castKeys(array $keys)
    {
        return (array) array_map(function ($v) {
            return $this->castKey($v);
        }, $keys);
    }

    /**
     * Cast the given key to an integer if it is numeric.
     *
     * @param  mixed  $key
     * @return mixed
     */
    protected function castKey($key)
    {
        return is_numeric($key) ? (int) $key : (string) $key;
    }
}
然后,您可以在模型类中重写Eloquent的hasMany方法:

 /**
     * Overrides the default Eloquent hasMany relationship to return a HasManySyncable.
     *
     * {@inheritDoc}
     */
    public function hasMany($related, $foreignKey = null, $localKey = null)
    {
        $instance = $this->newRelatedInstance($related);

        $foreignKey = $foreignKey ?: $this->getForeignKey();

        $localKey = $localKey ?: $this->getKeyName();

        return new HasManySyncable(
            $instance->newQuery(), $this, $instance->getTable().'.'.$foreignKey, $localKey
        );
    }

    /**
     * Get all of a user's phone numbers.
     */
    public function phones()
    {
        return $this->hasMany('App\Phone');
    }
同步方法现在可用于此模型上的任何多个关系:

$user->phones()->sync([
    [
    'id' => 21,
        'label' => "primary",
        'number' => "5555551212"
    ],
    [
    'id' => null,
        'label' => "mobile",
        'number' => "1112223333"
    ]
]);

最后,我创建了一个新类来扩展hasMany,它允许我按照alexweissman的说法使用sync

论坛摘录:

use Illuminate\Database\Eloquent\Relations\HasMany;

/**
 * @link https://github.com/laravel/framework/blob/5.4/src/Illuminate/Database/Eloquent/Relations/HasMany.php
 */
class HasManySyncable extends HasMany
{
    public function sync($data, $deleting = true)
    {
        $changes = [
            'created' => [], 'deleted' => [], 'updated' => [],
        ];

        $relatedKeyName = $this->related->getKeyName();

        // First we need to attach any of the associated models that are not currently
        // in the child entity table. We'll spin through the given IDs, checking to see
        // if they exist in the array of current ones, and if not we will insert.
        $current = $this->newQuery()->pluck(
            $relatedKeyName
        )->all();

        // Separate the submitted data into "update" and "new"
        $updateRows = [];
        $newRows = [];
        foreach ($data as $row) {
            // We determine "updateable" rows as those whose $relatedKeyName (usually 'id') is set, not empty, and
            // match a related row in the database.
            if (isset($row[$relatedKeyName]) && !empty($row[$relatedKeyName]) && in_array($row[$relatedKeyName], $current)) {
                $id = $row[$relatedKeyName];
                $updateRows[$id] = $row;
            } else {
                $newRows[] = $row;
            }
        }

        // Next, we'll determine the rows in the database that aren't in the "update" list.
        // These rows will be scheduled for deletion.  Again, we determine based on the relatedKeyName (typically 'id').
        $updateIds = array_keys($updateRows);
        $deleteIds = [];
        foreach ($current as $currentId) {
            if (!in_array($currentId, $updateIds)) {
                $deleteIds[] = $currentId;
            }
        }

        // Delete any non-matching rows
        if ($deleting && count($deleteIds) > 0) {
            $this->getRelated()->destroy($deleteIds);

            $changes['deleted'] = $this->castKeys($deleteIds);
        }

        // Update the updatable rows
        foreach ($updateRows as $id => $row) {
            $this->getRelated()->where($relatedKeyName, $id)
                 ->update($row);
        }

        $changes['updated'] = $this->castKeys($updateIds);

        // Insert the new rows
        $newIds = [];
        foreach ($newRows as $row) {
            $newModel = $this->create($row);
            $newIds[] = $newModel->$relatedKeyName;
        }

        $changes['created'][] = $this->castKeys($newIds);

        return $changes;
    }


    /**
     * Cast the given keys to integers if they are numeric and string otherwise.
     *
     * @param  array  $keys
     * @return array
     */
    protected function castKeys(array $keys)
    {
        return (array) array_map(function ($v) {
            return $this->castKey($v);
        }, $keys);
    }

    /**
     * Cast the given key to an integer if it is numeric.
     *
     * @param  mixed  $key
     * @return mixed
     */
    protected function castKey($key)
    {
        return is_numeric($key) ? (int) $key : (string) $key;
    }
}
然后,您可以在模型类中重写Eloquent的hasMany方法:

 /**
     * Overrides the default Eloquent hasMany relationship to return a HasManySyncable.
     *
     * {@inheritDoc}
     */
    public function hasMany($related, $foreignKey = null, $localKey = null)
    {
        $instance = $this->newRelatedInstance($related);

        $foreignKey = $foreignKey ?: $this->getForeignKey();

        $localKey = $localKey ?: $this->getKeyName();

        return new HasManySyncable(
            $instance->newQuery(), $this, $instance->getTable().'.'.$foreignKey, $localKey
        );
    }

    /**
     * Get all of a user's phone numbers.
     */
    public function phones()
    {
        return $this->hasMany('App\Phone');
    }
同步方法现在可用于此模型上的任何多个关系:

$user->phones()->sync([
    [
    'id' => 21,
        'label' => "primary",
        'number' => "5555551212"
    ],
    [
    'id' => null,
        'label' => "mobile",
        'number' => "1112223333"
    ]
]);

Locations
是一个
具有多个
关系,因此它将返回一个集合,而不是单个模型。您必须选择要更新的位置。我认为您正在寻找同步方法:
$listing->locations()->sync($array['locations')由于这是一对多关系,同步无法正常工作?调用sync时,我收到一个错误:调用undefined方法Illumb\\Database\\Query\\Builder::sync()
Locations
是一个
关系,因此它将返回一个集合,而不是单个模型。您必须选择要更新的位置。我认为您正在寻找同步方法:
$listing->locations()->sync($array['locations')由于这是一对多关系,同步无法正常工作?调用sync时,我收到一个错误:调用undefined方法illumb\\Database\\Query\\Builder::sync(),这似乎也不起作用,因为它试图填充第一条记录中的位置数组。即使我将其更新为…->fill($array['locations'][0]);在进行转储时,它仍然不会更新属性,同时注意,如果使用update而不是fill,这会起作用,但是我希望覆盖该模型的所有位置,而不仅仅是第一个位置。同步似乎是我想要的,但不确定它是否适用于一对多关系我已经更新了我的答案,同步适用于多对多。。。这似乎也不起作用,因为它试图填充第一条记录中的一组位置。即使我将其更新为…->fill($array['locations'][0]);在进行转储时,它仍然不会更新属性,同时注意,如果使用update而不是fill,这会起作用,但是我希望覆盖该模型的所有位置,而不仅仅是第一个位置。同步似乎是我想要的,但不确定它是否适用于一对多关系我已经更新了我的答案,同步适用于多对多。。。不是一对多