Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:130809 X-Original-To: internals@lists.php.net Delivered-To: internals@lists.php.net Received: from php-smtp4.php.net (php-smtp4.php.net [45.112.84.5]) by lists.php.net (Postfix) with ESMTPS id 2DAC61A00BC for ; Fri, 8 May 2026 12:54:01 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1778244845; bh=ElS+2GsYoYiU3dBTt8k6g5LS4rrX2YhXBvGn1Scg73g=; h=References:In-Reply-To:From:Date:Subject:To:From; b=KFKwA2l86PRpgRi0iVkxLJeWjGol2YVQf67eoSUvConSxyzeGJG8ZesdkSSHhfsaP JTuTTHWb7n5kWuBHjrST+KLqy0gxS1gAqgAkr4RwNCiCDMGWx+TpF+0XKLiytQbGXw yR/1T7pzKXs166of8O0EpRVAkBTxusjOx1dTFVD0deHqXOwdSTZO0CWScxi3ubysx9 TyPw/EKWP3fVFMxqsof2IDYRMGRJh0ZfGkcAWzHjCDUrVfJRwFYpgzaaxnCClKo9gd yiDGIZ0SjO5zUZHQ7FBxZcIl5kkBp93SOs42gXgGv17OPUtdaTKspGJ7COAZ1uiB7S TQo/HUU8qN3Cg== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id B7326180068 for ; Fri, 8 May 2026 12:54:04 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-25) on php-smtp4.php.net X-Spam-Level: X-Spam-Status: No, score=0.6 required=5.0 tests=BAYES_50,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,DMARC_PASS,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_PASS autolearn=no autolearn_force=no version=4.0.1 X-Spam-Virus: No X-Envelope-From: Received: from mail-qv1-f54.google.com (mail-qv1-f54.google.com [209.85.219.54]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by php-smtp4.php.net (Postfix) with ESMTPS for ; Fri, 8 May 2026 12:54:04 +0000 (UTC) Received: by mail-qv1-f54.google.com with SMTP id 6a1803df08f44-8acb3daf2aaso25863146d6.0 for ; Fri, 08 May 2026 05:53:59 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1778244839; cv=none; d=google.com; s=arc-20240605; b=aQ0aMIGA5WDPeWcygzOSGfr4uchar+yRRgIrK8afRebuJV97a6AUrZk8TT5d4VX2i2 /rAzjAzhapxHnkbJ1gBFMjkc5iYFv1r+usTErE/uboxWk+sZLOAHo9wN9BCJcfl8MI5x xM5XTQtwK6P285pptsM6AO7klcMD5XONs3Ihemwm/4ghg8Lo5aW+ExLoWP25UCl55zaW zYGNSG4dw/TI5QAQZQDGPw93hH5RnJJVm6B1C/FhNXHft+tHvQClN0fMdeBIxYhAwxwC qa2jnRKCUc7LSPdLs53HPpHYQCy7b6GGtzEI4B5a+iZ1wQWXjr+o5p6GyUxRhXMctg3y AQEg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=content-transfer-encoding:to:subject:message-id:date:from :in-reply-to:references:mime-version:dkim-signature; bh=ElS+2GsYoYiU3dBTt8k6g5LS4rrX2YhXBvGn1Scg73g=; fh=RFBKMNwdsUBkXmmb8AAjYIg7L3EzMrZygiLbMB7seK8=; b=XXD3VJMm7rKHWnQkXB0GGEXYuRYmjKEIHCfGenx/7gfuMpDZPfwdB69DEz3AkZzd4Z H5wZ3HQARdIG6ijO1hn7LaUfhGE1GEDDcA/9Jo5/wNynhADYxuYxtFPGCMYy81uRP2rl Y4GvDuDpm9H1cwuEgn288i4zOwqlXSLkMPLweGJ/851+tcbjmuVsxoQnlPJ3c+aMQBPJ nYEXRYI7cHo6DEgxkhLEEXxXBhEcpQNLtkhg6/tjPdGx5XETgATHfUZkDNORNHpAJ4Xa mm18hV9tZYehgWHAlGJ8x28dpNVHhmRZsdwJThG0mjF9zzbQ8c2WMCDYGPM2x8p+qeVB kvnw==; darn=lists.php.net ARC-Authentication-Results: i=1; mx.google.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1778244839; x=1778849639; darn=lists.php.net; h=content-transfer-encoding:to:subject:message-id:date:from :in-reply-to:references:mime-version:from:to:cc:subject:date :message-id:reply-to; bh=ElS+2GsYoYiU3dBTt8k6g5LS4rrX2YhXBvGn1Scg73g=; b=VGUMiOSQyNsZvyoffcM2byZa+3pmE1Gw/ou/WDPjhA6Pt+DwKBAque64Taw/o02p7a /M40IkAVCae9YonBI0uLrkmt45DKPRwvkQrkRVfw9pEf7L6yjEKPpNp0EVudjW3je1O0 ix9OBDXsYkIYM6+MvNhb0YEB344dBl5MUYLhjwBwV5B5yO1ET0rIaV2Tp6wrHhO+RcIZ uYsUbSFCZhGFl+HTMpM5yTLiRGRR+5ktzHUOumzTgTT336iYTusDeG0Wg1uXaOhpouZw Bv+wCvtH8qZ7I39gJYUFNZbBffRsurwFvBK65b4/6hdlIFUX/gMuSbjTwMlGYTW/cZZ2 jy2Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1778244839; x=1778849639; h=content-transfer-encoding:to:subject:message-id:date:from :in-reply-to:references:mime-version:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=ElS+2GsYoYiU3dBTt8k6g5LS4rrX2YhXBvGn1Scg73g=; b=CtUDpYSmdk/Fbge7IZ21lse604nNR85B58moPfzRtHi+8KG8PTMYO86T09J+pN0z53 SeLUYMKkHSrKrStLOnNoT2Orp1XtSZvmcM5wPQfUMcthsXm5RGvTWHi1Jn2hPmKckQOi 5XX3W6e1Yfb0XHpypzRhgq9BMpkxxoLPNL2UnscFlkWpel/FfKOKFh0CcJD2sepe/CCn hUfhTOSw2nPAXiMpd72U+vxSz4Zd0R70RI2W9QWaTia8vQIZQ6JCSpRvee6zZvUIISoG YC8LUg8YE8aOPzBzCxcf3dQPHMkH7NMIR2AaveLXmphKgh6RCdrTDK1tVCoOaqsctayI 7oog== X-Gm-Message-State: AOJu0YzKo21aPPn9srZ1wNRaKvYiQ+Yv7oZIPae9o4aGVaP+H/oQPN8Z QN1Yvm2JUIPXPAlaWWgZmaPxrXViTQnO3smfnADvXWkB9qU7Ob/SK6tYEinpH52LLFndSNIyd80 0VxuylXSRMQtZAVrygYCLux8hmXzUFziUeJN3ZniFlA== X-Gm-Gg: Acq92OGY24PYEcJLBYxe4C+JBf3B3NlFqxpyr5+bxbYNPyFvg4XqLHZbCUPcYXTceLx /a1SwpDlwqPlR0DXS4MLJ8Bj9ipsidHfRuZzfiX+mjOwV69mNWHP+XOb4iL3lVtdwZiWVzawj8w 7Z+6zb9+XHKo1u40V0Sx52WWU8GBsMxkqBWl5P+20+iTqPsQ8l8OFglg64lc+sb1Vn8ELt34KXk 7+DKo5Uh9Qdq5osSi946Ylvyt9Z+efVb9vJuCCMR5NAw/dAA3KL/uzGofZdln3JaOt7zAkLXAOp Nh5QiD0vjKXjLdBrSeQMPn1UEkEglTmdgoMigJ/sgnfdZbP4+QdNLjjJYW3bq/LDbMQpNfsM5qW rNbGQWquMlLKbsZVM4C+GLM5aoxauPUPsdCQipg== X-Received: by 2002:a05:6214:4407:b0:8b1:f784:7ec8 with SMTP id 6a1803df08f44-8bc463fa04emr195872056d6.47.1778244838482; Fri, 08 May 2026 05:53:58 -0700 (PDT) Precedence: list list-help: list-unsubscribe: list-post: List-Id: x-ms-reactions: disallow MIME-Version: 1.0 References: In-Reply-To: Date: Fri, 8 May 2026 14:53:47 +0200 X-Gm-Features: AVHnY4Jm82ffZwmbOooy-K6vdLJ4aORdSmIT3gjr7qaIi30XtcoW1YkQgOrGWhA Message-ID: Subject: Re: [PHP-DEV] [RFC] __exists(), a magic method for distinguishing "missing" from "set to null" To: PHP Internals List Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable From: tovilo.ilija@gmail.com (Ilija Tovilo) Hi Nicolas Thanks for your proposal. I have some unpolished thoughts. On Fri, May 1, 2026 at 11:38=E2=80=AFAM Nicolas Grekas wrote: > > https://wiki.php.net/rfc/exists-magic-method From what I can tell there are two primary objectives stated in the RFC: 1. Solve the "null or undefined" ambiguity problem. 2. Allow materializing properties within the "property existence check" magic method, whether that be __isset() or __exists(), and avoiding the __get() call that normally follows. As for objective 1, it seems quite odd to me that __exists() indicates "the property is declared and may or may not be null", when is then used for all the constructs that ask the distinct question "is the property defined and not null?", namely for isset(), empty() (negated) and ??. That's the question already precisely answered by __isset(). The behavior for disagreeing __isset() and __get() methods is odd, but IMO this is a clear userland bug. The other stated benefit is having the ability to check whether a property exists even if it may be null by calling __exists() directly. IMO the use-cases are narrow. For declared properties, there's a slightly unconventional solution: `array_key_exists('property', (array)$object)`. For virtual properties; fair enough. Though these could also use hooks nowadays. As for objective 2, you've mentioned this is possible to implement for __isset() but was rejected in GH-12695 due to complexity and performance concerns. IMO a new method does not address these concerns, it just moves them. If the __exists() method is intended to replace __isset() long-term, then, once all code has migrated, performance will not differ from adding the check to __isset(). [1] Similarly, complexity for implementing the __isset() and __exists() should be roughly equivalent. You solved the soundness issues mentioned in the RFC by avoiding repetition of the entire function and copying the relevant paths. I believe something similar should work for __isset(). It's also worth noting the main objection in GH-12695 was to treat it as a bug and change behavior in stable versions. To summarize, in my personal opinion it's better to go back to the original idea and add another property existence check after the __isset() call that avoids calling __get() if the property has materialized. From what I can tell, the has_property handler will also need the same adjustments. I don't think the stated benefits are enough to warrant a full migration to a new method. Ilija [1] We also concluded in the issue that performance isn't a real issue anyway. __exists() would also perform worse due to having to call __get() to verify the value is not null. This does make sure the functions are in agreement, at the cost of an unnecessary call for correct code.