Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

mozew's avatar
Level 6

Uncaught TypeError: response.forEach is not a function

script

<script>
    function categoryCheckbox(id){
        $('.articleFilters').empty();
        $.ajax({
            type: 'GET',
            url: 'getArticle/' + id,
            success: function(response) {
                //console.log(response);
                response.forEach(element => {
                    $('.articleFilters').append(element.id);
                });
            },
        });
    }
</script

err

0 likes
22 replies
rodrigo.pedra's avatar

What is the output of console.log(response); ?

I am guessing your response could wrapped into a data property, if that is the case test this:

function categoryCheckbox(id) {
    $('.articleFilters').empty();
    $.ajax({
        type: 'GET',
        url: 'getArticle/' + id,
        success: function (response) {
            console.log(response);
            response.data.forEach(element => {
                $('.articleFilters').append(element.id);
            });
        },
    });
}
mozew's avatar
Level 6

@Sinnbeck I replaced this code

public function show($id)
{
    $data = Article::query()->whereHas('categories', function ($query) use ($id){
        $query->where('id', $id);
    })->get();
    echo response()->json([$data]);
}

Is it correct?

rodrigo.pedra's avatar

@sinnbeck from the second screenshot it seems a valid JSON, just with a lot of UTF-8 encoded characters within the strings

@kiph odd, because this response is surely an array and a for each should work.

You could check for an array before calling forEach:

function categoryCheckbox(id) {
    $('.articleFilters').empty();
    $.ajax({
        type: 'GET',
        url: 'getArticle/' + id,
        success: function (response) {
            if (Array.isArray(response)) {
                response.forEach(element => {
                    $('.articleFilters').append(element.id);
                });
            } else {
                console.log('invalid response: ', response);
            }
        },
    });
}
Sinnbeck's avatar

@rodrigo.pedra I think it looked like a string, not an array :)

@kiph Try returning it so laravel can set the correct headers

public function show($id)
{
    $data = Article::query()->whereHas('categories', function ($query) use ($id){
        $query->where('id', $id);
    })->get();
    return response()->json([$data]);
}
mozew's avatar
Level 6

@Sinnbeck

Before

public function show($id)
{
    $data = Aricle::query()->whereHas('categories', function ($query) use ($id){
        $query->where('id', $id);
    })->get();
    echo json_encode($data);
}

After

public function show($id)
{
    $data = Article::query()->whereHas('categories', function ($query) use ($id){
        $query->where('id', $id);
    })->get();
    echo response()->json([$data]);
}
Sinnbeck's avatar

@kiph No. Change the echo to return

public function show($id)
{
    $data = Article::query()->whereHas('categories', function ($query) use ($id){
        $query->where('id', $id);
    })->get();
    return response()->json([$data]); //echo changed to return
}
rodrigo.pedra's avatar
Level 56

@Sinnbeck on the second screenshot, this one:

https://laracasts.com/discuss/channels/javascript/uncaught-typeerror-responseforeach-is-not-a-function-1?page=1&replyId=769528

You can see it is an array of objects... Actually that it should be an array of objects... But in reality you are correct it is an unparsed JSON encoded string!!!

@kiph sorry, there was a long time I didn't use ajax from jQuery, and I oversaw this...

First, remove the additional array wrap from the response:

public function show($id)
{
    $data = Aricle::query()->whereHas('categories', function ($query) use ($id){
        $query->where('id', $id);
    })->get();
return json_encode($data); // <<< CHANGE BACK TO THIS
}

Second, either add the dataType property, so jQuery auto parses the returned JSON string:

function categoryCheckbox(id) {
    $('.articleFilters').empty();
    $.ajax({
        type: 'GET',
        url: 'getArticle/' + id,
        dataType: 'json',
        success: function (response) {
            response.forEach(element => {
                $('.articleFilters').append(element.id);
            });
        },
    });
}

Reference: https://api.jquery.com/jQuery.ajax/#data-types

Or, parse the JSON string yourself:

function categoryCheckbox(id) {
    $('.articleFilters').empty();
    $.ajax({
        type: 'GET',
        url: 'getArticle/' + id,
        success: function (response) {
            response = JSON.parse(response);
            response.forEach(element => {
                $('.articleFilters').append(element.id);
            });
        },
    });
}
2 likes
Sinnbeck's avatar

@rodrigo.pedra Ah yeah the dataType on the ajax method is probably what is needed :) I assumed it would be set automatically if the headers was correct on the response

By header I mean this

header('Content-Type: application/json');

Which I believe laravel will set if you return instead of echo

1 like
rodrigo.pedra's avatar

@kiph actually something is very weird...

On your last posted console.log(...) the HTTP headers are outputted in the response...

Are you sure you don't have any other echo statement somewhere else in your code? check the web.php file, actually you should check everywhere for an unwanted echo or for an space before an opening <?php tag on a class file.

Also, try to avoid using echo directly as PHP will write it directly the output and it could cause problems on how Laravael builds the response objects

rodrigo.pedra's avatar

@Sinnbeck you are one more time correct, reading the link I posted for the jQuery docs, it states it will try to check the Content-Type header.

But take a look into the screenshot from this comment:

https://laracasts.com/discuss/channels/javascript/uncaught-typeerror-responseforeach-is-not-a-function-1?page=1&replyId=769539

The response headers are outputted on the console, which is very weird considered I suggested for @kiph to use console.log(response), also the raw headers like this should not be available to JavaScript, unless they are in the body of the response

Sinnbeck's avatar

@rodrigo.pedra Just tested it and the dataType isnt needed as long as you return instead of using echo :) With echo it breaks.

@kiph Change to return and it should work :)

1 like
rodrigo.pedra's avatar

Well it seems @kiph got it fixed.

Thinking about it I guess the whole problem was that you were using echo and not return.

So the fairest thing would be to mark @sinnbeck 's suggestion as the best answer.

But I think both me and @sinnbeck agree that the best thing is that you could get it fixed.

Have a nice day =)

1 like
mozew's avatar
Level 6

@rodrigo.pedra Thanks for answer

My complete code is like this

Controller

public function show($id)
{
    $data = Course::query()->whereHas('categories', function ($query) use ($id){
        $query->where('id', $id);
    })->get();
    return json_encode($data);
}

Ajax

<script>
    function categoryCheckbox(id) {
        $('.courseFilters').empty();
        $.ajax({
            type: 'GET',
            url: 'getCategoryCourse/' + id,
            dataType: 'json',
            success: function (response) {
                response.forEach(element => {
                    $('.courseFilters').append(element.id);
                });
            },
        });
    }
</script>
1 like
Sinnbeck's avatar

@kiph Use laravel as its meant to be used..

public function show($id)
{
    $data = Course::query()->whereHas('categories', function ($query) use ($id){
        $query->where('id', $id);
    })->get();
    return response()->json($data); //this is the laravel way
}
Ajax

<script>
    function categoryCheckbox(id) {
        $('.courseFilters').empty();
        $.ajax({
            type: 'GET',
            url: 'getCategoryCourse/' + id,
            success: function (response) {
                response.forEach(element => {
                    $('.courseFilters').append(element.id);
                });
            },
        });
    }
</script>
2 likes
Sinnbeck's avatar

@MichalOravec I assumed. I figured it out when he was echoing from a controller. Haven't seen anyone else do that :)

Please or to participate in this conversation.