Laravel Collection Add Values To List Of Array Filtering Specific Value

159 Views Asked by At

I am receiving data from database in this format

{
    "status_code": "00",
    "data": {
        "id": 1,
        "applicant_id": 1,
        "book_date_time": "2020-12-31 13:00:00",
        "status": "On Lock",
        "reference_number": "R2361-3961000001",
        "questionnaire_ids": [
            {
                "id": 1,
                "name": "Are you experiencing any of these symptoms? Please select all that apply",
                "answer": [
                    {
                        "id": 1,
                        "name": "Fever, chills, or sweating"
                    }
                ]
            },
            {
                "id": 2,
                "name": "Do any of these apply to you? Please select all that apply",
                "answer": [
                    {
                        "id": 7,
                        "name": "Moderate to serve asthma or chronic lung disease"
                    }
                ]
            },
            {
                "id": 3,
                "name": "In the last 14 days, have you travelled internationally?",
                "answer": [
                    {
                        "id": 17,
                        "name": "No"
                    },
                    {
                        "id": 18,
                        "name": "Yes"
                    }
                ]
            },
            {
                "id": 4,
                "name": "In the last 14 days, have you been in an area where COVID-19 is widespread",
                "answer": [
                    {
                        "id": 20,
                        "name": "Yes"
                    }
                ]
            },
            {
                "id": 5,
                "name": "In the last 14 days, what is your exposure to others who are known to have COVID-19?",
                "answer": [
                    {
                        "id": 22,
                        "name": "I live with someone who has COVID-19"
                    }
                ]
            },
            {
                "id": 6,
                "name": "Do you live or work in medical facility?",
                "answer": [
                    {
                        "id": 29,
                        "name": "No, I don't live or work or plan to live or work in a care facility"
                    }
                ]
            },
        ],
        "applicant_detail": {
            "id": 1,
            "user_id": 1,
            "first_name": "Mohd Farhan",
            "middle_name": "Bin",
            "last_name": "Ramli",
            "email": "[email protected]",
            "mobile_no": null
        },
        "transaction": null
    }
}

And I would need to append a data from external source to be put into questionnaire_ids in which the content of array have an answer of id 18 like below

{
    "id": 3,
    "name": "In the last 14 days, have you travelled internationally?",
    "answer": [
        {
            "id": 17,
            "name": "No"
        },
        {
            "id": 18,
            "name": "Yes",
            // Start of the data that need to be inserted
            "field_input": {
                "place_travelled_internationally": "Kuala Lumpur",
                "date_travelled_internationally": "2020-10-10"
            }
            // End of the data that need to be inserted
        }
    ]
},

so that it would become like this

{
    "status_code": "00",
    "data": {
        "id": 1,
        "applicant_id": 1,
        "book_date_time": "2020-12-31 13:00:00",
        "status": "On Lock",
        "reference_number": "R2361-3961000001",
        "questionnaire_ids": [
            {
                "id": 1,
                "name": "Are you experiencing any of these symptoms? Please select all that apply",
                "answer": [
                    {
                        "id": 1,
                        "name": "Fever, chills, or sweating"
                    }
                ]
            },
            {
                "id": 2,
                "name": "Do any of these apply to you? Please select all that apply",
                "answer": [
                    {
                        "id": 7,
                        "name": "Moderate to serve asthma or chronic lung disease"
                    }
                ]
            },
            {
                "id": 3,
                "name": "In the last 14 days, have you travelled internationally?",
                "answer": [
                    {
                        "id": 17,
                        "name": "No"
                    },
                    {
                        "id": 18,
                        "name": "Yes",
                        // Start of the data that need to be inserted
                        "field_input": {
                           "place_travelled_internationally": "Kuala Lumpur",
                           "date_travelled_internationally": "2020-10-10"
                        }
                        // End of the data that need to be inserted
                    }
                ]
            },
            {
                "id": 4,
                "name": "In the last 14 days, have you been in an area where COVID-19 is widespread",
                "answer": [
                    {
                        "id": 20,
                        "name": "Yes"
                    }
                ]
            },
            {
                "id": 5,
                "name": "In the last 14 days, what is your exposure to others who are known to have COVID-19?",
                "answer": [
                    {
                        "id": 22,
                        "name": "I live with someone who has COVID-19"
                    }
                ]
            },
            {
                "id": 6,
                "name": "Do you live or work in medical facility?",
                "answer": [
                    {
                        "id": 29,
                        "name": "No, I don't live or work or plan to live or work in a care facility"
                    }
                ]
            },
        ],
        "applicant_detail": {
            "id": 1,
            "user_id": 1,
            "first_name": "Mohd Farhan",
            "middle_name": "Bin",
            "last_name": "Ramli",
            "email": "[email protected]",
            "mobile_no": null
        },
        "transaction": null
    }
}

I have tried using normal array replacement like below but it is not dynamic as it will throw error when the key change

$value = '{"answer_input":{"18":{"place_travelled_internationally":"Sungai Wijaya Resources Sdn Bhd","date_travelled_internationally":"2020-12-30"}},"questions":[1,2,3,4,5,6],"answers":[1,7,18,20,22,27]}';

$questionnaires_data = json_decode($value, true);
$questions = collect($questionnaires_data['questions']);
$answers = collect($questionnaires_data['answers']);
$answer_input = collect($questionnaires_data['answer_input']);

foreach ($questions as $key => $question) {
    $questionnaires[$key] = Question::whereId($question)->select('id', 'name')->first();
    $questionnaires[$key]['answer'] = Answer::whereIn('id', $answers)->select('id', 'name')->where('question_id', $question)->get();
}

if ($answers->contains('18')) {
    $questionnaires[2]['answer'][1]['field_input'] = $answer_input[18];
}

return $questionnaires;

I have tried using collection map but I am unable to achieve for the solution, as i am not understand how to make this work, the closest i can get is as below

the code

$value = '{"answer_input":{"18":{"place_travelled_internationally":"Sungai Wijaya Resources Sdn Bhd","date_travelled_internationally":"2020-12-30"}},"questions":[1,2,3,4,5,6],"answers":[1,7,18,20,22,27]}';


$questionnaires_data = json_decode($value, true);
$questions = collect($questionnaires_data['questions']);
$answers = collect($questionnaires_data['answers']);
$answer_input = collect($questionnaires_data['answer_input']);

foreach ($questions as $key => $question) {
    $questionnaires[$key] = Question::whereId($question)->select('id', 'name')->first();
    $questionnaires[$key]['answer'] = Answer::whereIn('id', $answers)->select('id', 'name')->where('question_id', $question)->get();
}
if ($answers->contains('18')) {
    $questionnaires = collect($questionnaires)->map(function ($row) {
        return collect($row)->map(function ($row2) {
            return $row2;
        });
    })->values()->all();
}

return $questionnaires;

the output (not desired output)

{
    "status_code": "00",
    "data": {
        "id": 1,
        "applicant_id": 1,
        "book_date_time": "2020-12-31 13:00:00",
        "status": "Pending Payment",
        "reference_number": "R2361-3961000001",
        "questionnaire_ids": [
            {
                "id": 1,
                "name": "Are you experiencing any of these symptoms? Please select all that apply",
                "answer": [
                    {
                        "id": 1,
                        "name": "Fever, chills, or sweating"
                    }
                ]
            },
            {
                "id": 2,
                "name": "Do any of these apply to you? Please select all that apply",
                "answer": [
                    {
                        "id": 7,
                        "name": "Moderate to serve asthma or chronic lung disease"
                    }
                ]
            },
            {
                "id": 3,
                "name": "In the last 14 days, have you travelled internationally?",
                "answer": [
                    {
                        "id": 18,
                        "name": "Yes"
                    }
                ]
            },
            {
                "id": 4,
                "name": "In the last 14 days, have you been in an area where COVID-19 is widespread",
                "answer": [
                    {
                        "id": 20,
                        "name": "Yes"
                    }
                ]
            },
            {
                "id": 5,
                "name": "In the last 14 days, what is your exposure to others who are known to have COVID-19?",
                "answer": [
                    {
                        "id": 22,
                        "name": "I live with someone who has COVID-19"
                    }
                ]
            },
            {
                "id": 6,
                "name": "Do you live or work in medical facility?",
                "answer": [
                    {
                        "id": 27,
                        "name": "I have live or worked in Hospital or other care facility in the past 14 days. This includes volunteering"
                    }
                ]
            }
        ],
        "applicant_detail": {
            "id": 1,
            "user_id": 1,
            "first_name": "Mohd Farhan",
            "middle_name": "Bin",
            "last_name": "Ramli",
            "email": "[email protected]",
            "mobile_no": null
        },
        "transaction": {
            "id": 1,
            "booking_id": 1,
            "status": "Pending",
            "order_no": "HDN000001",
            "remarks": "HDN Booking Payment",
            "transaction_date": "2020-12-04 17:37:56",
            "pgw_transaction_response": null
        }
    }
}

kindly guide on how to achieve the solution to this problem.

1

There are 1 best solutions below

0
On

the solution to fix this is to use laravel collection of map + contains + put as below

$questionnaires_data = json_decode($value, true);
$questions = collect($questionnaires_data['questions']);
$answers = collect($questionnaires_data['answers']);
$answer_input = collect($questionnaires_data['answer_input']);

foreach ($questions as $key => $question) {
    $questionnaires[$key] = Question::whereId($question)->select('id', 'name')->first();
    $questionnaires[$key]['answer'] = Answer::whereIn('id', $answers)->select('id', 'name')->where('question_id', $question)->get();
}

if ($answers->contains('18')) {
    $questionnaires = collect($questionnaires)->map(function ($item) use ($answer_input) {
        return collect($item)->map(function ($item2, $key2) use ($answer_input) {
            if ($key2 == 'answer') {
                return collect($item2)->map(function ($item3, $key3) use ($answer_input) {
                    if (collect($item3)->contains(18)) {
                        return collect($item3)->put('answer_input', $answer_input[18]);
                    } else {
                        return $item3;
                    }
                });
            } else {
                return $item2;
            }
        })->all();
    })->values()->all();
}

return $questionnaires;