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

有个关于 PHP 的小疑惑

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

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

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

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

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

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

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

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

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

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

    弱类型的,只要是用双等号的,大部分 int 和 string 都不分。
    在 php 更为突出,因为后端全是数据处理。
    QlanQ
        32
    QlanQ  
       40 天前
    @kivmi #25 其实现在都用 (int)$a 了
    QlanQ
        33
    QlanQ  
       40 天前
    人的问题,Java 和其他语言也会有,比如 一个 data 应该返回 [] ;但是如果 一条数据都没有,又会返回 null
    cat1879
        34
    cat1879  
       40 天前
    弱类有弱类的方便,所以要接受带来的副作用
    darklinden
        35
    darklinden  
       40 天前
    所以对接 Phper 的接口从来不敢上来直接用 json 对象解析器,因为指不定啥时候就会炸
    “我服务好好的你那儿怎么挂了?去查吧。”
    “你就说我返回的 0 ,‘0’,false , ‘false’ 它是不是非 true 吧”
    easychen
        36
    easychen  
       40 天前
    其实差不多十年前,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
       40 天前
    @easychen 这样会让 phper 们不会写代码了吧?
    easychen
        38
    easychen  
       40 天前
    @seansong CUrsor 和 Trae 会就行。
    kk2syc
        39
    kk2syc  
       40 天前
    @kivmi #25 intval 错误的时候返回 1 ,好奇,你在业务线这样写东西?
    seansong
        40
    seansong  
    OP
       40 天前
    @easychen 这么说,确实是
    DOLLOR
        41
    DOLLOR  
       40 天前   ❤️ 2
    @uqf0663
    @jiuhuicinv

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

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


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