'Why PHP strlen() and Javascript xxx.length is not equal?

I have following text:

Ankylosaurus was an armored dinosaur that lived roughly 67 million years ago, at the very end of the Cretaceous Period. This genus was among the last of the non-avian dinosaurs, living alongside Tyrannosaurus, Triceratops, and Edmontosaurus. Its name means 'fused lizard'; bones in its skull and other parts of its body were fused, increasing their strength. Ankylosaurus was up to 6.25 m (20.5 feet) long and 1.7 m (5.6 feet) tall, weighing about 4.8–8 tonnes (11,000–18,000 lb). It had a broad, robust body with a wide, low skull. The front parts of the jaws were covered in a beak, with rows of small, leaf-shaped teeth behind it, adapted for a herbivorous diet. It was covered in armor plates for protection against predators, with bony half-rings covering the neck, and had a large club on the end of its tail which may have been used as a weapon. Fossils from a few specimens of Ankylosaurus have been found in various geological formations in western North America, but a complete skeleton has

Now I run bellow PHP and JS code:

echo strlen(trim($text));

and

var text = "above text";
alert( text.length);

Now PHP is showing 1004 and JS is showing me 1000 characters, Why?



Solution 1:[1]

Your two versions are unlikely to print the same output because they do different things.

JavaScript's String.length property returns a character count (though based in an early and outdated definition of character):

console.log(`–`.length);
console.log(`?`.length);

PHP's strlen() function returns a byte count and you're possibly using a multi-byte encoding like UTF-8 (or you should). Please compare:

var_dump(strlen('–'), mb_strlen('–'));
var_dump(strlen('?'), mb_strlen('?'));
int(3)
int(1)
int(4)
int(1)

You're also removing leading and trailing whitespace only in the JavaScript version and spaces are people too.


To build a reliable character-count cross-language function:

  • PHP: mb_strlen() should work fine out of the box, as long as you configure your application to tell PHP about encoding being used (or specify the encoding manually every time) and you feed it with properly encoded data. In 2018 there's normally no reason to use anything else than UTF-8.

    var_dump(mb_strlen('–?', 'UTF-8'));
    
  • JavaScript: String.length may seem to work for you if you think you don't need to account for emojis but, to be on the safe side, you can check JavaScript has a Unicode problem for some workarounds (the article is interesting even for pure learning purposes).

Solution 2:[2]

Ascii characters are 1 byte in length. strlen function assumes that every character is 1 byte in length, which works fine for the English language.

But when you start dealing with non-English languages, characters can take more than 1 byte to represent. If more than 1 byte should use mb_strlen.

Solution 3:[3]

When i try to approximate strlen with JS i'm using :

<?php
echo strlen("?as%20?"); // 13
const str = "?as%20?"
const len = new URL(str.replace(/%[A-F0-9]{2}/g, "..."), "https:$").pathname.replace(/%[A-F0-9]{2}/g, ".").length - 1
console.log(len) // 13

Solution 4:[4]

I was facing the same issue, js string length is different

var string = "adsf dsfkslk sldkflak fkddfsl ldafldskjf";
console.log(string.length);

php is giving different length

$string =  "adsf dsfkslk sldkflak fkddfsl ldafldskjf";

then I tried in php

 $my_str =  "adsf dsfkslk sldkflak fkddfsl ldafldskjf";
        $my_str = strip_tags($my_str);
        $my_str = html_entity_decode($my_str);
        $my_str = trim($my_str," \t\n\r\0\x0B\xC2\xA0");
        $my_str=trim(preg_replace('/\s\s+/', '', $my_str));
        $my_str = mb_strlen($my_str);

it is returning the exact the count.

Solution 5:[5]

You have to convert line breaks in PHP because, in JavaScript, a line break is a single newline character. When it is sent, there are two that's why the count is not matching.

$description = $_POST['description'];
$description = str_replace("\r\n", "\n", $description);
$description = str_replace("\r", "\n", $description);

$count = mb_strlen($description); // now this count will match with JavaScript var.length

Solution 6:[6]

first, text its show it self while not fade its can be considered animated too, or create some async function

check this code :

import 'package:flutter/material.dart';

class FadeTextAuto extends StatefulWidget {
  const FadeTextAuto({Key? key}) : super(key: key);

  @override
  _FadeTextAutoState createState() => _FadeTextAutoState();
}

class _FadeTextAutoState extends State<FadeTextAuto>  with SingleTickerProviderStateMixin{

  late Animation _animationFadeInOut;
  late AnimationController _animationController;

  bool _textShouldPlay = false;
  late Animation _animationText;
  String info = "This text appear in";

  @override
  void initState() {
    super.initState();
    _animationController = AnimationController(vsync: this, duration: const Duration(milliseconds: 2000));

    _animationFadeInOut = Tween<double>(
        begin: 0.0, end: 1.0).animate(CurvedAnimation(parent: _animationController, curve: Curves.linear));
    _animationText = StepTween(
      begin: 1, end: 3
    ).animate(CurvedAnimation(parent: _animationController, curve: Curves.linear));
  }
  
  @override
  Widget build(BuildContext context) {
    return Material(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          TextButton(onPressed: (){
            setState(() {
              info = "This text appear in";
              _textShouldPlay = false;
            });
            print(_animationText.value);
            _animationController.forward().then((value){
              if(mounted){
                setState(() {
                  _textShouldPlay = true;
                  info = "Hey read this Information";
                });
               Future.delayed(const Duration(milliseconds: 2000),(){
                 //wait a little for text can be read
                 if(mounted){
                   setState(() {
                    _textShouldPlay = false;
                     info = "this Text will be disappear in";
                   });
                 }
               }).then((value){
                 if(mounted){
                   _animationController.reverse();
                 }
               });
              }
            });
          }, child: const Text("User Click")),
          AnimatedBuilder(
            animation: _animationController,
            builder: (context, child){
              return Opacity(
                opacity: _animationFadeInOut.value,
                child: Text(
                  "$info ${_textShouldPlay?"":_animationText.value} ", style: const TextStyle(color: Colors.cyan, fontSize: 20),
                ),
              );
            },
          ),
        ],
      ),
    );
  }

  @override
  void dispose() {
    _animationController.dispose();
    super.dispose();
  }
}

result : enter image description here

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Tùng Phan Thanh
Solution 3
Solution 4
Solution 5 ajmirani
Solution 6 Sayyid J