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

aliawwad's avatar

json_encode returns Malformed UTF-8 characters

I just upgraded PHP from 7.3 to 7.4 , and upgraded Laravel from 6.x to 7.x.

The home controller returns a collection, and I pass this collection to vuejs component. this was working fine in laravel 6.x with PHP 7.3.

Then After the upgrade of both PHP & Laravel, and after many test, I found that my collection is returned to my view as "false". and When I added json_last_error_msg() , I found the following error: Malformed UTF-8 characters, possibly incorrectly encoded

I wanted to test if the issue is within PHP 7.4, so I reverted back to laravel 6.x, but it was working fine there too.

To my understanding, if I do not convert the collection to json from the controller itself, then in my blade view if I just echo it there {{ $most_viewed_this_week}} it should be automatically converted to json:

<books-group-request :items="{{$most_viewed_this_week}}">
</books-group-request>

but this returns the following error: Method Illuminate\Database\Eloquent\Collection::__toString() must return a string value

------- UPDATE -----

a sample record:

#original: array:31 [▼
        "id" => 9
        "isbn" => "9789778535419"
        "title_ar" => "أي حرف أكل الوحش؟"
        "title_en" => "أي حرف أكل الوحش؟"
        "description_ar" => """
          هم نم يم نم نم ... حرف جميل ما ألذ الطعام!
          هذا ما يقوله الوحش الظريف كلما أكل حرفا من الحروف القصة. ولكن كيف سنعرف أي حرف أكل الوحش حتى نستطيع أن نكمل يا ترى؟
          """
        "description_en" => null
        "year" => null
        "price" => null
        "currency_id" => null
        "number_of_papers" => 45
        "edition" => null
        "age_from_year" => null
        "age_to_year" => null
        "series_ar" => null
        "series_en" => null
        "publisher_id" => 5
        "language_id" => 1
        "user_id" => 5
        "created_by" => 5
        "updated_by" => 13
        "deleted_at" => null
        "created_at" => "2020-01-04 12:08:24"
        "updated_at" => "2020-06-07 19:38:20"
        "is_draft" => 0
        "is_approved" => 1
        "title_fr" => "le monstre mangeur de lettres"
        "description_fr" => """
          yam yam .... Que c'est bon , cette lettre est très délicieuse!
          C'est ce que dit le drôle de monstre chaque fois qu'il mange une lettre de chaque mot d'une histoire . Mais comment saurons-nous quelle lettre 
           a mangé le  le monstre pour pouvoir  compléter l'histoire?
          """
        "series_fr" => null
        "book_reviews_count" => 2
        "user_favorites_count" => 4
        "views_count" => 0
0 likes
4 replies
thewebartisan7's avatar

I suppose this is a component, then variable should be without {{ }}, example:

<books-group-request :items="$most_viewed_this_week"></books-group-request>

aliawwad's avatar

@zoroaster no this is a VueJs component, so the $most_viewed_this_week collection must be returned as json, and {{$most_viewed_this_week}} should to the trick.

Again, this was working fine with Laravel 6, only happened when upgraded to 7.

Just to clarify further, in my controller if I dd($most_viewed_this_week); I can see the collection available without any problem. But when i change it to:

$json  = json_encode($most_viewed_this_week);
$error = json_last_error_msg();
var_dump($json, $error);

then I get bool(false) string(56) "Malformed UTF-8 characters, possibly incorrectly encoded"

thewebartisan7's avatar

Sorry, I didn't understand. I am not sure why but your pasted php array has three times """ for description_ar and description_fr not sure why. Try test outside with plain php, example https://ideone.com/jjVpxT

Or instead try:

<books-group-request :items="@json($most_viewed_this_week)">
</books-group-request>

aliawwad's avatar

I found the problem, however I still do not know how it caused this problem.

In Book.php model i had the following:

$filename = basename(parse_url($url, PHP_URL_PATH));
$filename = str_replace('%20', ' ', $filename);

If I change it to $filename = 'foo' then it works just fine.

Again, I cannot find any reasonable cause, because it is still working fine on Laravel 6.x instance, but after upgrading to Laravel 7.x this came up.

By the way, my uploaded files are in Arabic language.

Please or to participate in this conversation.