php7.4,iconv,utf-8转gbk异常

这个问题是线上的服务发现的。我们的业务需要把 utf-8 的字符集,转成 gbk 的字符集。可是现在转码异常。
我用的docker hyperf 镜像构建的容器。这是构建文件。

# Default Dockerfile
#
# @link     https://www.hyperf.io
# @document https://hyperf.wiki
# @contact  group@hyperf.io
# @license  https://github.com/hyperf-cloud/hyperf/blob/master/LICENSE

FROM hyperf/hyperf:7.4-alpine-v3.11-cli
LABEL maintainer="Hyperf Developers <group@hyperf.io>" version="1.0" license="MIT" app.name="Hyperf"

##
# ---------- env settings ----------
##
# --build-arg timezone=Asia/Shanghai
ARG timezone

ENV TIMEZONE=${timezone:-"Asia/Shanghai"} \
    COMPOSER_VERSION=1.10.10 \
    APP_ENV=prod
    #SCAN_CACHEABLE=(false)

# update
RUN set -ex \
    # install composer
    && cd /tmp \
    && wget https://github.com/composer/composer/releases/download/${COMPOSER_VERSION}/composer.phar \
    && chmod u+x composer.phar \
    && mv composer.phar /usr/local/bin/composer \
    # show php version and extensions
    && php -v \
    && php -m \
    && php --ri swoole \
    #  ---------- some config ----------
    && cd /etc/php7 \
    # - config PHP
    && { \
        echo "upload_max_filesize=128M"; \
        echo "post_max_size=128M"; \
        echo "memory_limit=1G"; \
        echo "date.timezone=${TIMEZONE}"; \
    } | tee conf.d/99_overrides.ini \
    # - config timezone
    && ln -sf /usr/share/zoneinfo/${TIMEZONE} /etc/localtime \
    && echo "${TIMEZONE}" > /etc/timezone \
    # ---------- clear works ----------
    && rm -rf /var/cache/apk/* /tmp/* /usr/share/man \
    && echo -e "\033[42;37m Build Completed :).\033[0m\n"

WORKDIR /opt/www

# Composer Cache
# COPY ./composer.* /opt/www/
# RUN composer install --no-dev --no-scripts

COPY . /opt/www
RUN composer install --no-dev -o && php bin/hyperf.php

EXPOSE 9501

ENTRYPOINT ["php", "/opt/www/bin/hyperf.php", "start"]

大家可以看到php版本是7.4.
这是我的容器内的具体版本

php7.4,iconv,utf-8转gbk异常

这是我的转码代码

public function testIcon()
    {
        $str = '一个数字';
        $res = $this->utfToGbk($str);
        var_dump($res);
    }

    function utfToGbk($data)
    {
        $encode = mb_detect_encoding($data, array("ASCII",'UTF-8',"GB2312","GBK",'BIG5','gb18030'));
        var_dump('字符编码是=' . $encode);
        if ($encode != 'UTF-8'){
            var_dump($encode,$data);
            unset($data);
        }

        return iconv('UTF-8', 'GB2312', $data);
    }

大家有遇到过吗?我们测试环境的php7.2没有发现这个问题。线上环境是php7.4.线上环境是不能动的。这个大家有咩有好的解决办法。

这是我的打印的信息。

php7.4,iconv,utf-8转gbk异常

huanbird
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
最佳答案

会不会跟这个是一样问题 github.com/hyperf/hyperf-docker

# fix aliyun oss wrong charset: https://github.com/aliyun/aliyun-oss-php-sdk/issues/101
RUN apk --no-cache --allow-untrusted --repository http://dl-cdn.alpinelinux.org/alpine/edge/community/ add gnu-libiconv
ENV LD_PRELOAD /usr/lib/preloadable_libiconv.so php
2周前 评论
huanbird (楼主) 2周前
讨论数量: 6
huanbird

file 刚刚测试过。php7.2没有问题。这就很蛋疼啦!

2周前 评论

有点想不动了。。你上面mb_detect。。。你怎么不直接用mb_convert?

如果要用iconv,也需要加上//ignore,gb2312的字库比较小,转过来肯定会丢字符。所以要加上//ignore,忽略掉不能转的内容

2周前 评论

我重新做了一个测试。不正常,是你的终端问题。因为终端是UTF8的。你可以file_put_contents('test.txt',iconv('UTF-8','GBK','一个数字'));

把文字用GBK编码格式打开,会发现,内容是正常的

2周前 评论
隔壁王叔叔 (作者) 2周前
huanbird

问题定位到啦。是docker问题。只要在docker里面运行,就会出错。具体docker是什么原因。正在找。一会找到更新。

2周前 评论

会不会跟这个是一样问题 github.com/hyperf/hyperf-docker

# fix aliyun oss wrong charset: https://github.com/aliyun/aliyun-oss-php-sdk/issues/101
RUN apk --no-cache --allow-untrusted --repository http://dl-cdn.alpinelinux.org/alpine/edge/community/ add gnu-libiconv
ENV LD_PRELOAD /usr/lib/preloadable_libiconv.so php
2周前 评论
huanbird (楼主) 2周前
huanbird

在这里统一回复一下。就是景象的问题。需要的东西是这个。

file
具体代码是这个。

RUN apk add --no-cache --repository http://mirrors.aliyun.com/alpine/edge/community gnu-libiconv
ENV LD_PRELOAD /usr/lib/preloadable_libiconv.so php
2周前 评论
隔壁王叔叔 2周前
huanbird (作者) (楼主) 2周前
隔壁王叔叔 2周前
huanbird (作者) (楼主) 1周前
隔壁王叔叔 1周前

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!