Как обновить значение внешнего ключа ide в Laravel Eloquent?

Я довольно новичок в Laravel и не смог найти ответ на эту проблему ни в документах Laravel, ни здесь. Я думаю, это просто вопрос того, как его искать, потому что я уверен, что это частый случай.

У меня есть две модели в отношениях (это упрощенный случай), я получаю нужную мне информацию через файл ресурсов, но я не могу понять, как правильно хранить или обновлять информацию. Вот пример кода:

ModelsCompany.php

class Company extends Model
{
    protected $fillable = [
        'name', 'blablabla', 'country_id', 'blablabla2',
    ];

    public function country() {
        return $this->belongsTo(Country::class);
    }
}
ModelsCountry.php

class Country extends Model
{
    protected $fillable = [
        'code', 'name', 'prefix', 'tax_code_id',
    ];

    public function companies() {
        return $this->hasMany(Company::class);
    }
}

Затем у меня есть файл CompanyController для управления запросами API:

ControllersCompanyController.php

class CompanyController extends BaseController
{
    public function index()
    {
        $companies = Company::paginate();
        $response = CompanyResource::collection($companies)->response()->getData(true);

        return $this->sendResponse($response, 'Companies retrieved successfully');
    }

    public function store(Request $request)
    {
        $input = $request->all();

        $validator = Validator::make($input, $this->validation_rules);

        if($validator->fails()){
            return $this->sendError('Validation error.', $validator->errors());
        }

        $company = Company::create($input);

        return $this->sendResponse($company->toArray(), 'Company added successfully.');
    }
}

...

    public function update(Request $request, Company $company)
    {
        $input = $request->all();

        $validator = Validator::make($input, $this->validation_rules);

        if($validator->fails()){
            return $this->sendError('Validation error.', $validator->errors());
        }

        $company->update($input);

        return $this->sendResponse($company->toArray(), 'Company updated successfully.');
    }

А вот CompanyResource, который я использую для отображения информации по мере необходимости.

Resources/CompanyResource.php

class CompanyResource extends JsonResource
{
    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'name' => $this->name,
            'blablabla' => $this->blablabla,
            'country' => $this->country,
            'blablabla2' => $this->blablabla2,
        ];
    }
}

Поэтому при поиске компаний (или отдельной компании) я получаю вложенный JSON:

{
  "id": "1",
  "name": "something",
  "blablabla": "blablabla",
  "country": {
    "id": "100",
    "code": "MA",
    "name": "Mars",
    "prefix": "123",
    "tax_code_id": "#$%"
  },
  "blablabla2": "blablabla2"
}

Если я создаю или обновляю новую компанию, я отправляю полезную нагрузку, которая имеет ту же структуру, что и та, которую я получаю выше, но если я изменяю значение идентификатора страны, моя модель компании не получает его.

PUT Api/companies/1

{
  "name": "something",
  "blablabla": "blablabla3",
  "country": {
    "id": "200",
    "code": "JU",
    "name": "Jupiter",
    "prefix": "456",
    "tax_code_id": "#=%"
  },
  "blablabla2": "blablabla2"
}

Я ожидаю обновить поле country_id в таблице компаний для записи 1, чтобы оно совпадало с полезной нагрузкой (т.е. от 100 до 200), но этого не происходит.

Я мог бы отредактировать логику внешнего интерфейса, чтобы отправлять только данные country_id в полезной нагрузке, поскольку я не собираюсь обновлять таблицу стран, и вся эта дополнительная информация является избыточной, но я хотел бы знать, как управлять ею в контроллере с Laravel.

Не могли бы вы помочь мне? Заранее спасибо.

Всего 1 ответ


Если вы хотите, чтобы он теперь работал с кодом, вам нужно иметь country_id в корневом объекте JSON, который вы отправляете. Поскольку это способ, которым вы бы заполнить идентификатор. На мой взгляд, это не лучший подход, но именно поэтому ваше обновление не работает в данный момент.

{
    "name": "something",
    "blablabla": "blablabla3",
    "country_id": 200,
    ...

Мне действительно нравится подход отправки полных объектов. Обычно заполнять идентификаторы не очень хорошо, так как это может помешать работе отношений. Laravel установит ваши отношения, когда вы будете общаться, в противном случае вы не гарантированно будете иметь правильные отношения после заполнения.

Для этого я бы взял идентификатор и связал объект страны с компанией. По логике похоже на это.

// only fill non relation fields, fill used as save is needed after associate()
$company->fill($request->only(['name', 'blabla']));

$company->country()->associate(Country::find($request->get('country')['id']));

//associate does not save
$company->save();

Есть идеи?

10000