Newsgroups: php.internals
Path: news.php.net
Xref: news.php.net php.internals:123342
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 qa.php.net (Postfix) with ESMTPS id D3DDC1A009C
	for <internals@lists.php.net>; Sat, 18 May 2024 09:19:51 +0000 (UTC)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail;
	t=1716024045; bh=Vo7QdM3dTJ81fd3rr7vWtaXpbHlkdlZaj+D/H9egS2Q=;
	h=References:In-Reply-To:From:Date:Subject:To:Cc:From;
	b=Dc3SIKQ4tmkVrXkwSXn3RoqCujc5j1tpSn3d42Y+Chc63h+6CYjy9dOM0fjDrJQoG
	 4xHie5RtECf7aofTOjiqOQhZGqi/x5EE23DJk7KHyuZBVdv9jF5Cs3A29PafCdrJeg
	 V5QO3S1IZZ33u/K2KoHf5VMeDCRJ2CsUY+cLkxEQGfMjmRBFHwoqZwTlQuirZkDAY3
	 iIuYFVfChjUS3sG4WpSXL73ovp5xRz2kB+G8zZVESUmSua7E0Aq0WneWdPCvzow0Fx
	 YuHUXFgStfIEQpHFUgdkEsUeuzVh0UOnGskyCjZ26tj6KvVqTzczwnxo4tSfhqweeD
	 t1vEMXrDwJv/w==
Received: from php-smtp4.php.net (localhost [127.0.0.1])
	by php-smtp4.php.net (Postfix) with ESMTP id 392C118003B
	for <internals@lists.php.net>; Sat, 18 May 2024 09:20:44 +0000 (UTC)
X-Spam-Checker-Version: SpamAssassin 4.0.0 (2022-12-13) 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,
	T_SCC_BODY_TEXT_LINE autolearn=no autolearn_force=no version=4.0.0
X-Spam-Virus: Error (Cannot connect to unix socket
	'/var/run/clamav/clamd.ctl': connect: Connection refused)
X-Envelope-From: <landers.robert@gmail.com>
Received: from mail-lj1-f172.google.com (mail-lj1-f172.google.com [209.85.208.172])
	(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 <internals@lists.php.net>; Sat, 18 May 2024 09:20:43 +0000 (UTC)
Received: by mail-lj1-f172.google.com with SMTP id 38308e7fff4ca-2e716e302bdso4894791fa.1
        for <internals@lists.php.net>; Sat, 18 May 2024 02:19:49 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=gmail.com; s=20230601; t=1716023988; x=1716628788; darn=lists.php.net;
        h=content-transfer-encoding:cc:to:subject:message-id:date:from
         :in-reply-to:references:mime-version:from:to:cc:subject:date
         :message-id:reply-to;
        bh=DoM3/rg0i1VZeM/Gw84z1OOZIFZ6EXT04ISDWRwPaFc=;
        b=TWfrwNEZaiXv599HfE4vQ7DUGGucqqs/BRxOL2RYTwJwAHUnYXYePVws6BIzBY0w5m
         koGZke/eRqSw2aWoOWgUe3QAlOnM2PEOMiYG88nIUQDmZpPkCi5p2Tx4yWgHHwBdn+N7
         +juaiBEfTXlpGDyHp0j2AOb4BBGilGIb0eRA7GNIM+9sjstxkFGVRlC/2S5Yo7VEAAgl
         X442iOD+dcDoN6hCuGB32KMDERppMHwSQJqcbE4qsXOK9Bb3/atNStHGsc2r9dnlVogi
         7WucOZjatFaMBVpPq0tG0uOjtwimz2cZpb2f1nNUbphWmJqCFLOi8G4T2WIvyvim6EtQ
         cpJQ==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=1e100.net; s=20230601; t=1716023988; x=1716628788;
        h=content-transfer-encoding:cc:to:subject:message-id:date:from
         :in-reply-to:references:mime-version:x-gm-message-state:from:to:cc
         :subject:date:message-id:reply-to;
        bh=DoM3/rg0i1VZeM/Gw84z1OOZIFZ6EXT04ISDWRwPaFc=;
        b=YGCLSCN9YQx6b9+j1HIC3rY82VPGtuNS1N+l/Q4R3Rdrl2AvWsc+AG9gOXLUMuM2vs
         KNEHEOgOWZZLm7mOtVTntjtrw8To7OW5lAR9F4alBobArW31J8YAhGNg7ViQid2PegnH
         9Okmny72Ne2Ux6+wLDoVUq3UzFsPmQEgMcsymeZWlKGuOnwQJge2tKTt62dRMqqsRsYv
         w3yHv7eNIKqpfs3HQCUwgNrpyWvLOQt8eO9Tzy581bxT/B48d+mdTTVQkKR25iw4kYu8
         1UHx3XNXOddKYpgvtaMP9frRctXE6yIrwguM9waP4fl5pX9k9iTn9LFW0b4fkdfK8g2B
         7iQw==
X-Gm-Message-State: AOJu0YyPI0ZK5tRb+hGNxDHWRHo61Pg6U8weI6+uBR2zdADCuNJPPML9
	5LfhKCY/1gKTR3ea5/QBMdTT7AGrufyp7CRhy1owCAoAmQLBU5l+ZSJ4N3CimxMaErL4x93ni4Z
	SdNvb1Booj9VPydhY4m16viJkKaw=
X-Google-Smtp-Source: AGHT+IER1FmNceSjuacDjgWfjb8W9BcNVbFx3CWdvOMsRc1jEWH1ZXZkxzlv2p77veF5rneeqvaN7Tw5IjKJYpfPAJ4=
X-Received: by 2002:a05:6512:e8a:b0:51d:b7fc:29a6 with SMTP id
 2adb3069b0e04-5220fc735a0mr18316135e87.7.1716023987993; Sat, 18 May 2024
 02:19:47 -0700 (PDT)
Precedence: bulk
list-help: <mailto:internals+help@lists.php.net
list-unsubscribe: <mailto:internals+unsubscribe@lists.php.net>
list-post: <mailto:internals@lists.php.net>
List-Id: internals.lists.php.net
MIME-Version: 1.0
References: <CAAX=eQNH0xyoRkMDThvG_aNS5Hub3tFD52v4PY3OZKT_zWaMmg@mail.gmail.com>
In-Reply-To: <CAAX=eQNH0xyoRkMDThvG_aNS5Hub3tFD52v4PY3OZKT_zWaMmg@mail.gmail.com>
Date: Sat, 18 May 2024 11:19:34 +0200
Message-ID: <CAPzBOBN1M3H-ueqUtzfb_HPv2jZeDaYVTvXideVnx9QYG6LKeA@mail.gmail.com>
Subject: Re: [PHP-DEV] [DISCUSSION] Checking uninitialized class properties
To: Luigi Cardamone <cardamoneluigi@gmail.com>
Cc: internals@lists.php.net
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
From: landers.robert@gmail.com (Robert Landers)

On Fri, May 17, 2024 at 11:43=E2=80=AFPM Luigi Cardamone
<cardamoneluigi@gmail.com> wrote:
>
> Hello Internals,
> during last PHPDay in Verona I discussed this topic with some of
> you and it was suggested to me to send an email here.
>
> Here is an example to describe my problem. Imagine a simple
> DTO like this:
>
> class MyDTO{
>     public ?int $propA;
>     public ?int $propB;
> }
>
> Imagine that a Form processor or a generic mapper fill some of
> these fields with a null value:
>
> $dto =3D new MyDTO();
> $dto->propA =3D null;
>
> Sometimes we use DTOs to handle PATCH requests and not all
> the properties are mapped with a value. In a scenario like this,
> "null" is often a valid value.
>
> At this point, I need a way to find if a property was initialized or
> not but unfortunately "isset" is not a solution. When I write:
>
> echo isset($dto->propA) ? 'init' : 'not-init';
>
> I get "not-init" since isset returns true only if the variable is set
> and different from null.
>
> Full example: https://3v4l.org/4cCj0
>
> Is the language missing a clean way to check if a property is
> initialized or not? Is there any solution to this problem?
>
> The only alternative is using reflection but I need to pass the
> property name as a string losing static analysis.
> Proposing a new language syntax like
> "is_initialized($dto->propA)" can be an interesting solution?
>
> Thank you in advance.
>
> Luigi Cardamone
> Backend developer
> Italy

I wouldn't rely on checking initialized or not. Instead, use a sentinel val=
ue:

class NotSet {}

define("NotSet", new NotSet());

class MyAwesomeValue {
    public NotSet|null|string $aValue =3D NotSet;
}

This way, even programmers can "unset" a property by simply setting
$value->aValue =3D NotSet without having to rely on the weird PHP
semantics of unsetting a property. You can also use this to
declaratively encode which properties cannot be unset, without having
to define it in your mapping code.

Robert Landers
Software Engineer
Utrecht NL