PHP/Laravel: Вложенный объект превращается в массив

#php #laravel #validation

Вопрос:

Для проверки данных входящих запросов я использую метод проверки. Мне нужно создавать разные модели, поэтому я использую разные правила проверки с разными данными.

Мои входящие данные выглядят так

 {
    "type": "b2b",
    "registration_number": "123456789",
    "vat_number": "123456789",
    "company_name": "Test company",
    "legal_entity_type": "NV",
    "phone": "1234567",
    "email": "test@company.com",
    "physical_address": {
        "street": "Teststreet",
        "number": "12",
        "addition": "5",
        "zip": "12345",
        "city": "Brussels",
        "country": "Belgium"
    },
    "billing_address": {
        "street": "Teststreet",
        "number": "12",
        "addition": "5",
        "zip": "12345",
        "city": "Brussels",
        "country": "Belgium"
    },
    "contacts": [
        {
            "function": "CEO",
            "first_name": "John",
            "last_name": "Doe",
            "phone": "123456789",
            "email": "john.doe@gmail.com"
        },
        {
            "function": "COO",
            "first_name": "Jane",
            "last_name": "Doe",
            "phone": "987654321",
            "email": "jane.doe@gmail.com"
        }
    ]
}
 

Проверка основной информации не является проблемой

 $clientData = $request->validate([
    'type' => ['required', 'string', 'in:b2b,b2c'],
    'vat_number' => ['string', 'max:255'],
    'company_name' => ['string', 'max:255'],
    'legal_entity_type' => ['string', 'max:255'],
    'phone' => ['required', 'string', 'max:255'],
    'email' => ['required', 'string', 'max:255'],
    'first_name' => ['string', 'max:255'],
    'last_name' => ['string', 'max:255'],
    'date_of_birth' => ['date'],
]);
 

Но вложенные объекты являются. Я хочу проверить физический и платежный адрес, но php превращает эти объекты в массивы. Это приводит к "Call to a member function validate() on array" ошибке:

 $physicalAddress = $request['physical_address']->validate([
    'street' => ['required', 'string', 'max:255'],
    'number' => ['required', 'string', 'max:255'],
    'addition' => ['string', 'max:255'],
    'zip' => ['required', 'string', 'max:255'],
    'city' => ['required', 'string', 'max:255'],
    'country' => ['required', 'string', 'max:255'],
]);
 

В документах Laravel я узнал, что вы можете использовать точку для проверки данных вложенного массива

 $physicalAddress = $request->validate([
    'physical_address.street' => ['required', 'string', 'max:255'],
    'physical_address.number' => ['required', 'string', 'max:255'],
    'physical_address.addition' => ['string', 'max:255'],
    'physical_address.zip' => ['required', 'string', 'max:255'],
    'physical_address.city' => ['required', 'string', 'max:255'],
    'physical_address.country' => ['required', 'string', 'max:255'],
]);
 

Но в результате получается массив с одним элементом

 [2021-09-17 15:24:59] local.DEBUG: array (
  'physical_address' => 
  array (
    'street' => 'Teststreet',
    'number' => '12',
    'addition' => '5',
    'zip' => '12345',
    'city' => 'Brussels',
    'country' => 'Belgium',
  ),
)  
 

Чтобы использовать это в дальнейшем, я должен назначить первый элемент $PhysicalAddress $PhysicalAddress: $physicalAddress = $physicalAddress[0] .

Поскольку это очень просто, мне не нравится эта дополнительная строка. Для меня это похоже на хакерское кодирование, и я думаю, что есть лучшее решение, чтобы сохранить его в качестве объекта в первую очередь.

Есть какие-нибудь предложения?

Ответ №1:

$physicalAddress = $request['physical_address']->validate() это не работает просто потому validate() , что является методом запроса и $request['physical_address'] представляет собой массив.

В чем проблема с использованием проверки?

 $validated = $request->validate([
    'street' => 
    'number' => 
    'addition' => 
    'zip' => 
    'city' => 
    'country' =>

    'physical_address.street' =>
    'physical_address.number' => 
    'physical_address.addition' =>
    'physical_address.zip' => 
    'physical_address.city' => 
    'physical_address.country' => 

    'billing_address.street' => 
    'billing_address.number' => 
    'billing_address.addition' => 
    'billing_address.zip' => 
    'billing_address.city' => 
    'billing_address.country' => 

    'contacts.*.function' => 
    'contacts.*.first_name' => 
    'contacts.*.last_name' => 
    'contacts.*.phone' => 
    'contacts.*.email' => 
]);
 

Комментарии:

1. Часть адреса/контакта не может быть повторно использована при таком подходе

2. Что ты имеешь в виду? 'contacts.*.function' должно совпадать со всеми элементами массива контактов. Или вы говорите о том, как дублируются physical_address и billing_address?

3. У меня есть другие функции контроллера, в которых запрос содержит адрес или контакт. Я хочу отделить часть проверки, чтобы я мог повторно использовать ее во всем проекте.