V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
seansong
V2EX  ›  PHP

有个关于 PHP 的小疑惑

  •  
  •   seansong · 2025 年 4 月 26 日 · 7556 次点击
    这是一个创建于 264 天前的主题,其中的信息可能已经有所发展或是发生改变。
    第一次对接几个 php 写的接口,遇到一个能理解但想好奇八卦一下的细节,对方接口返回 json ,其中有个字段

    "is_completed": 0
    "is_completed": "0"
    "is_completed": false

    同一个接口返回的完全一样的同一份数据,为什么每次请求,得到的数据类型都不一样呢,而且是随机的,有时候接口返回的数组中,不同元素里面的这个字段,都会出现不一样的类型,什么场景下会出现这种情况,个别程序员搞成这样的,还是 php 生态中就是这样

    弱类型,好像能理解,但就是好奇罢了
    73 条回复    2025-05-27 15:50:59 +08:00
    vem
        1
    vem  
       2025 年 4 月 26 日   ❤️ 1
    有可能这个字段是存 Redis 缓存的,有时候从缓存取,有时候数据库取导致返回值不一样了
    sagaxu
        2
    sagaxu  
       2025 年 4 月 26 日
    PHP 传统,除了 str 和 int 不分,{}和[]也不分,框架随意整,程序员也不在意,前端会兼容,岁月静好
    ferock
        3
    ferock  
    PRO
       2025 年 4 月 26 日
    PHP 传统,写接口的那位不在意。。。
    uqf0663
        4
    uqf0663  
       2025 年 4 月 26 日
    false==0 能理解,但是 false=="0"绝对不是 php 的锅
    abccccabc
        5
    abccccabc  
       2025 年 4 月 26 日
    你要告诉 php ,把值固定下来,不然强类型语言无法解析,一会字符串、一会整型,数据类型都变了,只能定义一种数据类型。这样,php 端马上就能改了。我以前也是这样的
    akira
        6
    akira  
       2025 年 4 月 26 日
    这种就是 个别 程序员 的锅了, 啥语言都会有类似的问题的。
    zhhqiang
        7
    zhhqiang  
       2025 年 4 月 26 日 via Android
    应该有判断导致的吧 可能是多个位置处理赋值导致不一样
    glitter1105
        8
    glitter1105  
       2025 年 4 月 26 日
    你规定要什么类型的值,告诉后端必须这样处理。
    v1
        9
    v1  
       2025 年 4 月 26 日
    写接口的 phper 不在意,你和他沟通,强制为 int 就行,php 就加 3 行代码能解决
    caola
        10
    caola  
       2025 年 4 月 26 日
    有可能是从不同地方获取的数据,就不去管对应的是什么类型直接输出了,
    有时从数据库获取是正确类型,有时是从 redis 或表单获取默认就是字符串类型,在 PHP 用 if 判断 0 、"0"、false 都得到相同的结果 false ,所以什么类型就不是那么重要,同样前端 js 也表现一样,所以大多数情况下的前后端都没有类型上的问题
    realpg
        11
    realpg  
    PRO
       2025 年 4 月 26 日
    if 条件一 return false elseif 条件二 return 0 elseif 条件三 return "0"

    很正常 他们自己程序内这些都好处理 对外提供的接口你跟他沟通一下就完事了 不是什么过分要求
    因为在他们那边都一样 他不太注意这个 不是问题
    jiuhuicinv
        12
    jiuhuicinv  
       2025 年 4 月 26 日
    false==0 能理解,但是 false=="0"绝对不是 php 的锅
    hefish
        13
    hefish  
       2025 年 4 月 26 日
    php 程序员便宜知道吧。 便宜他总有便宜的道理。
    wakarimasen
        14
    wakarimasen  
       2025 年 4 月 26 日
    不应该说,世界上最好的语言,其伟大之处就是能让这些人也入行?
    z7356995
        15
    z7356995  
       2025 年 4 月 26 日
    你自己单步执行一步步调试一下
    Felldeadbird
        16
    Felldeadbird  
       2025 年 4 月 26 日
    如果是同一个接口类型变化,PHP 没有强制返回类型。业务逻辑上返回了 0 和“0”,语言特性。

    如果不是同一个接口,大概率还是写代码的人水平太低了。没有统一的数据处理。加上语言特性导致返回类型可变
    wenber
        17
    wenber  
       2025 年 4 月 26 日
    多条逻辑判断结果值类型随意定义罢了,PHP 在国内的名声就是让这帮“二杆子货”霍霍了
    seansong
        18
    seansong  
    OP
       2025 年 4 月 26 日
    @abccccabc 那倒不会说无法处理,在反序列化的时候注意一下就行,只是,心里特别没底,因为不知道有多少是测试阶段没遇到的,可能就漏处理了,我也就是临时帮别人写个小东西,看到这种情况,好奇了一下而已
    prosgtsr
        19
    prosgtsr  
       2025 年 4 月 26 日 via iPhone
    我在对接某个支付的时候遇到过这个问题,搞得我这边解析 json 报错了,去反馈之后告诉我在某个场景下会出现……
    我又一次理解到了为啥企业项目喜欢用 java 开发
    kivmi
        20
    kivmi  
       2025 年 4 月 26 日   ❤️ 1
    感谢 php ,让我一个高中的也能入行
    kivmi
        21
    kivmi  
       2025 年 4 月 26 日
    @Felldeadbird 一看就是写代码的人的水平的问题,一般不会出现这种问题,同一个接口还会出现这中问题,应该还是从不同的数据源取数据,有没有处理的问题吧
    kivmi
        22
    kivmi  
       2025 年 4 月 26 日
    @prosgtsr java 是强类型语言,类型不对就报错,不改代码编译不过去啊
    kivmi
        23
    kivmi  
       2025 年 4 月 26 日
    @jiuhuicinv false == 0 和 false == "0" 有毛区别吗? === 才有类型的检测
    jiuhuicinv
        24
    jiuhuicinv  
       2025 年 4 月 26 日
    @kivmi 好家伙,我就是那个二杆子货
    kivmi
        25
    kivmi  
       2025 年 4 月 26 日
    @kk2syc echo intval(false).PHP_EOL;
    echo intval("0").PHP_EOL;
    echo intval(0).PHP_EOL; 要毛三行代码,加个 intval 就行了
    kivmi
        26
    kivmi  
       2025 年 4 月 26 日
    @jiuhuicinv 你是不是我不知道,但是我肯定是,你看哪些说写 php 的都是二杆子货
    newtype0092
        27
    newtype0092  
       2025 年 4 月 26 日
    之前做 PHP 后端遇到过,当时是接手前人的项目,前端报类似的 BUG 给我。

    我以为是个很简单的问题,就开始追查,结果发现像在扯毛线头。。。
    从收到请求开始,网关、业务层、框架、三方库、数据库、缓存、内部微服务。。。所有地方都可能出问题。
    各处代码的维护者对这些值的校验逻辑不一致,业务逻辑的差异又导致不确定会经过哪些处理链路。

    最后 leader 问我多久能解决这个问题,我说需要添加一个中间件来统一 ResponseBody 的 json 映射逻辑,估计要一个月,将中间件应用到所有 PHP 服务,测试所有受影响的接口,再做相应的适配,需要估计两到三个月,前端受影响的地方需要同步更新,需要他们评估时间。

    最后采用的方案是在前端报 BUG 的那个接口返回时对指定两个 key 做一次 cast ,工期 1 小时。

    上面看起来是一个我被“急功近利”的领导压迫下不得不写 dirty code 的故事。不过我后来简单统计,那个项目上线到我离职为止,同样原因的 BUG 两年多时间内我处理过 4 、5 次,算上同事处理的总共可能十多次,大概耗费的总的工期在 2 到 3 天。所以我也不敢说我的想法真的就比当时的 leader 高明,毕竟眼界和职责都不一样。
    (这个问题看起来应该会出现的非常频繁,但实际上很多时候不触碰到一些特殊 case 是不会被发现的,容易发现的地方一般在自测时就会顺手改掉,所以实际被主动上报的情况反而不多。)
    Norie
        28
    Norie  
       2025 年 4 月 26 日 via Android
    有一个 transformer 就不会了,比如 laravel 的
    4UyQY0ETgHMs77X8
        29
    4UyQY0ETgHMs77X8  
       2025 年 4 月 27 日
    人的问题,反正我基本能用 true 和 false 就 true 和 false 了,除非有些对接三方要求字符串,否则基本不会出现字符串 0
    mitoop
        30
    mitoop  
       2025 年 4 月 27 日
    人的问题 弱类型不是这么弱的 弱类型可能 int 返回 string 但这是一直在变化
    lyxxxh2
        31
    lyxxxh2  
       2025 年 4 月 27 日
    https://learnku.com/laravel/t/87153
    跟这个人类似。

    弱类型的,只要是用双等号的,大部分 int 和 string 都不分。
    在 php 更为突出,因为后端全是数据处理。
    QlanQ
        32
    QlanQ  
       2025 年 4 月 27 日
    @kivmi #25 其实现在都用 (int)$a 了
    QlanQ
        33
    QlanQ  
       2025 年 4 月 27 日
    人的问题,Java 和其他语言也会有,比如 一个 data 应该返回 [] ;但是如果 一条数据都没有,又会返回 null
    cat1879
        34
    cat1879  
       2025 年 4 月 27 日
    弱类有弱类的方便,所以要接受带来的副作用
    darklinden
        35
    darklinden  
       2025 年 4 月 27 日
    所以对接 Phper 的接口从来不敢上来直接用 json 对象解析器,因为指不定啥时候就会炸
    “我服务好好的你那儿怎么挂了?去查吧。”
    “你就说我返回的 0 ,‘0’,false , ‘false’ 它是不是非 true 吧”
    easychen
        36
    easychen  
       2025 年 4 月 27 日
    其实差不多十年前,PHP 就可以不是弱类型了啊。

    > PHP 从 PHP 7.0 ( 2015 年 12 月发布)开始,首次引入了标量类型声明( scalar type declarations ),可以对函数参数和返回值进行类型约束。也是从 PHP 7.0 开始,可以开启 严格模式( strict_types )在文件头部加上:

    declare(strict_types=1);

    这样,PHP 就不会再自动把类型兼容(比如 int 传 string 会出错而不是自动转换)。
    seansong
        37
    seansong  
    OP
       2025 年 4 月 27 日
    @easychen 这样会让 phper 们不会写代码了吧?
    easychen
        38
    easychen  
       2025 年 4 月 27 日
    @seansong CUrsor 和 Trae 会就行。
    v1
        39
    v1  
       2025 年 4 月 27 日
    @kivmi #25 intval 错误的时候返回 1 ,好奇,你在业务线这样写东西?
    seansong
        40
    seansong  
    OP
       2025 年 4 月 27 日
    @easychen 这么说,确实是
    AV1
        41
    AV1  
       2025 年 4 月 27 日   ❤️ 2
    @uqf0663
    @jiuhuicinv

    php 里写 [false == 0] 跟 [false == "0"] 还真没区别

    参考 php ==真值表:
    https://imgur.com/a/sDmywKN


    出处 https://github.com/sentientmachine/php_equality_charts
    8355
        42
    8355  
       2025 年 4 月 27 日
    @seansong #37 可能是你对接的人比较菜吧。。。大厂一样用 php ,什么语言对输入输出结果没有任何影响,一样有很多可以写出规范代码的人。
    kivmi
        43
    kivmi  
       2025 年 4 月 27 日
    @kk2syc 直接用,有什么问题?提前暴露问题不是更好?你非要把你的代码,搞的什么觉得有多么健壮?等到了生产,出问题了然后查日志去?实际开发,也很难遇到过你这么复杂的场景,本身就是用来处理基本类型的,你非要整个对象,违背了它设计的初衷。
    kivmi
        44
    kivmi  
       2025 年 4 月 27 日
    @easychen 你这一加,php 不就更慢了?
    kivmi
        45
    kivmi  
       2025 年 4 月 27 日
    @QlanQ 好些年没写 php 了,php8 特性有些没关注到
    kivmi
        46
    kivmi  
       2025 年 4 月 27 日
    @seansong php8 跟 ts 一样,可以指定类型了,加个类型而已,难道加个类型会被搞死?就像你写 js 的,就不会 ts 了?
    dabingbing
        47
    dabingbing  
       2025 年 4 月 27 日
    PHP 写多了,不习惯强类型,但是实际上写 PHP 代码的时候,会有意的强制类型,比如 intval 之类的
    seansong
        48
    seansong  
    OP
       2025 年 4 月 27 日
    @kivmi “你这一加,php 不就更慢了?” 按理说,严格类型,应该是变快吧,怎么会更慢呢?当然,我不了解 php 的内存管理,这么说不一定对哈,不用做隐式转换,应该是节约了资源才对
    ibin
        49
    ibin  
       2025 年 4 月 27 日
    @seansong 更快了,避免隐式类型转换
    kivmi
        50
    kivmi  
       2025 年 4 月 27 日
    @seansong 好问题!的确没有隐式转换肯定会快,但是 php 所有的类型都是使用 ZVAL 一个结构体来存储的,php 是做不到真正的强类型的,这是 PHP 的设计问题! declare(strict_types=1)并不影响 php 的类型设计,只是约束了函数参数和返回值的类型而已!并没有对 php 的类型有实质性的改变!
    0IuL7w7X5K2HJxZf
        51
    0IuL7w7X5K2HJxZf  
       2025 年 4 月 27 日
    @newtype0092 你真搞了中间件统一了的话,很可能会在你有很多意想不到的地方报 bug 一堆出来。
    seansong
        52
    seansong  
    OP
       2025 年 4 月 27 日
    @kivmi 你这么说,我大概理解了,php 存的并不是 raw data ,那严格类型确实不会带来性能的提升
    siweipancc
        53
    siweipancc  
       2025 年 4 月 27 日 via iPhone   ❤️ 1
    0 ,空字符串,空数组,-1 都属于 false ,就问你怕不怕
    sycxyc
        54
    sycxyc  
       2025 年 4 月 27 日
    @siweipancc -1 不属于 false 吧。其它例子也适用于 js
    will800
        55
    will800  
       2025 年 4 月 27 日
    @kivmi #20 据说 rails 更灵活一点,怎么不从 rails 入行呢?
    kivmi
        56
    kivmi  
       2025 年 4 月 27 日
    @will800 你在说什么?回复我刚写的 python fastapi 的问题?
    kivmi
        57
    kivmi  
       2025 年 4 月 27 日
    @will800 哦 我知道你说的应该是高中那条!以前 ruby 国内没那么火,java 和 php 最火,java 一直卡学历,然后转的 php
    NowTime
        58
    NowTime  
       2025 年 4 月 27 日 via Android
    负责维护的一个 Laravel 项目,4 年前还是 PHP 7.1, Laravel 5.8 ,现在已经升级到了 PHP 8.4 、Laravel 12 了,学过 Java 所以对 PHP 类型声明一点都不突兀反而觉得很好用,并且能用对象的都用对象不使用 array ,基本很难出现什么 API 字段类型不对、弱判断等问题,代码也写的很舒服。
    michealzh
        59
    michealzh  
       2025 年 4 月 28 日
    这个不是 php 的问题...
    gloeaerris
        60
    gloeaerris  
       2025 年 4 月 28 日
    这个是个人问题,不是 PHP 的问题,门槛太低就会有很多菜鸡
    GuangXiN
        61
    GuangXiN  
       2025 年 4 月 28 日
    JS 也是 false == '0'
    我这儿已经强制用 === 了
    sthwrong
        62
    sthwrong  
       2025 年 4 月 28 日
    这个和 php 无关,我对接的 java 喜欢用 map ,返回值类型也不固定。
    jhdxr
        63
    jhdxr  
       2025 年 4 月 28 日
    @seansong #52
    @kivmi #50
    你错了,严格类型在执行的时候是会带来性能提升的。PHP 的很多 opcode 都对于不同类型有不同的处理,如果在编译时(这个编译不是编译型语言的编译,而只是从 php 代码转化为 php 自己的中间代码——以前是直接转 OPCODE ,后来是转 AST )的时候无法确定就会落入一个兜底的逻辑。能够提前确定类型可以规避掉这部分并不小的开销。
    但需要说明的是,这个判断并不是类型提示(这只是一种可以用来帮助推断的信息),还包括了别的推断手段。
    yc8332
        64
    yc8332  
       2025 年 4 月 28 日
    接口没有做统一的数据处理。。直接返回是数字 int ,然后 int 存到数据库,取出来就变成 string 了,然后可能取的时候他没值就把数据库的返回值给返回了,就是 false 。。。
    正常会做个数值强制转换,看是返回字符串或者是数字。。统一接口的返回值
    seansong
        65
    seansong  
    OP
       2025 年 4 月 28 日
    @yc8332 int 存进数据库,取出来为什么会是 string ?这个有点奇怪
    LieNoWell
        66
    LieNoWell  
       2025 年 4 月 29 日
    单纯是程序员的问题。
    Java 也见过同一个接口,返回一条数据时是对象,多条数据时是列表的情况。
    yc8332
        67
    yc8332  
       2025 年 4 月 29 日
    @seansong 基本上常见的编程语言的 mysql 驱动都是默认字符串返回的,保证精度不会丢失,然后程序里再自己转换,驱动那边也有参数可以设置不默认返回字符串类型。
    seansong
        68
    seansong  
    OP
       2025 年 4 月 29 日
    @yc8332 你说的是 int 吗?
    yc8332
        69
    yc8332  
       2025 年 4 月 29 日
    @seansong 就是数据库里的字段查询返回不管你是什么类型,传输过程默认是字符串。
    seansong
        70
    seansong  
    OP
       2025 年 4 月 29 日
    @yc8332 不应该是字节流么,怎么会是字符串呢,哥们你这大误解了,pg/mysql 这两个最常见的,协议传输的都是字节流
    yc8332
        71
    yc8332  
       2025 年 4 月 29 日
    @seansong 我说的内容,内容。。你可以去了解一下,传输哪个协议底层不是字节流?
    seansong
        72
    seansong  
    OP
       2025 年 4 月 29 日
    @yc8332 可能 php 的客户端库会在过去到字节之后把内容先解码成字符串吧,肯定不会是常见行为的,毕竟这个行为在强类型需要里面直接就是错误
    soul11201
        73
    soul11201  
       2025 年 5 月 27 日
    混乱有序
    关于   ·   帮助文档   ·   自助推广系统   ·   博客   ·   API   ·   FAQ   ·   Solana   ·   3171 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 42ms · UTC 13:53 · PVG 21:53 · LAX 05:53 · JFK 08:53
    ♥ Do have faith in what you're doing.