Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:123344 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 43A5D1A009C for ; Sat, 18 May 2024 12:34:33 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1716035727; bh=Tx7blDboUGeslz0JPQCn9WTU3Vs+PKbhxsA9LCer7YI=; h=References:In-Reply-To:From:Date:Subject:To:Cc:From; b=SWvzEAe2HqrPtFXY0robvv1fd8TOG6/NEf/T6iLXfDYeVj2NeDkhb4uSncY4+q2q5 7zeONrRB1T4P57gVOf0Nrbx2qltYPbkqPVEWgotB6gnuzI65yzS+pFKUo7ZtIz7D/h Y83JcRzG51AAeeWiUuVWuJ34dVFKn5ZJxxrFhLEnMhPR4aVjWAAX6t/iXHE44JSwvV py83fflTprnAjoI4cos1L/Om2wAsSkBsaog8wLszOV2eEsj5fsfgOcgW60pbtcj/tK cIDDfu1zrzTJ3ZrjMuNYadSVYapulbUxC8nyOz09Gj9ZCjOOkvVQeHAMV8N+1gtMy/ 0CbGIfGY3/WWQ== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 8FB9A18006E for ; Sat, 18 May 2024 12:35:25 +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: Received: from mail-lf1-f41.google.com (mail-lf1-f41.google.com [209.85.167.41]) (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 ; Sat, 18 May 2024 12:35:25 +0000 (UTC) Received: by mail-lf1-f41.google.com with SMTP id 2adb3069b0e04-51f2ebbd8a7so3494082e87.2 for ; Sat, 18 May 2024 05:34:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1716035670; x=1716640470; 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=yqpE1uz5E4Zz/0KeVYrcisTVvL4COCtNP2LHjstPFgA=; b=XXwMXLg8POefu1uJ8By7zxI3FwLcZzZ0zuH0t3qpkRrg/Gb1rajp5X2LfEQOUB4QN8 FoxXf4HuKyB1UVh0IwO3vX3jKqsMTEBlk9+IcJyfcdSxDyLJiJ2nRSYXz6snkmG6QFVD LQrDA/nQea2hiVylDGFhNHO6DzD1daQZ7ocnnQVis2y7ngFs1IpWaLpWG6UP4qnNRnli 7Zv6xJBf5ALmYbvzFOILTietdf4LDw8wviwvjxgeJWLj38IvdT1Csao3ZgTfhoIeBSVc IbRJj8b2/VeFOhzlvUs/6SK9GImHbOCOpzJqYZ0T0D1nbnoKhYP9YRKgBA4OKlgOgivX IPeQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1716035670; x=1716640470; 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=yqpE1uz5E4Zz/0KeVYrcisTVvL4COCtNP2LHjstPFgA=; b=bCN3JvK2FY67mmLx2Um2Lootumyci1Xq6EKv/zYSL6DnUIFtCc0342XTT3AIKv7xJv PaUpLiSuPnakt42xNJdzghrFl8772rpTUT/MXchtqKO4rWGfy3GIjS/R+VIK4Cz5hZfS B9PCDWK0PETSRRGumkQTXPgU08zkkteGomo0IAVF02kXzFtnKvyAuauwu21UGGyQegXO 66E09fXCBm7Pdi6LAyNVrQv7ipK5K0pUWy34ojZtsLv02zK8J99wbgW3A0FsIZKXQANS 6hPOdY890W1suyoq50GEQWeGJ/qCzefmDCk8RtiHKmAeMwj1O2fLbVH4+eOWvbViuUVD Ip1w== X-Gm-Message-State: AOJu0YzHiRgG3q+dR12rFKTD470VqGsnJNUwUHk+RzlxT7wSsa+Vi1fQ UHtaCHLUpgoWaBwefvc6cAhhiPypvVxcrf5iE0JFICEtfeCQuavC4+VTYDgjVtGaqvkkZHFe3G+ H8rQDnuN32IwvJ6JtNw/rkT3mMqs= X-Google-Smtp-Source: AGHT+IFqGQZaAu2cWFZ8CAjBtw6Ertdoy8LG1xIsNQVSJbnwqYv9fh9YZsekn+2zzVELcj47780FI7H8JA3v5jFmhHM= X-Received: by 2002:a05:6512:2809:b0:51f:5760:dd34 with SMTP id 2adb3069b0e04-5220ff70be8mr20071570e87.55.1716035669538; Sat, 18 May 2024 05:34:29 -0700 (PDT) Precedence: bulk list-help: list-post: List-Id: internals.lists.php.net MIME-Version: 1.0 References: In-Reply-To: Date: Sat, 18 May 2024 14:34:16 +0200 Message-ID: Subject: Re: [PHP-DEV] [DISCUSSION] Checking uninitialized class properties To: Luigi Cardamone 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 Sat, May 18, 2024 at 12:52=E2=80=AFPM Luigi Cardamone wrote: > > Thank you for your feedback. > > I am already using a solution like the one > proposed by Robert: it works but it > leaves some doubts since each project > can have a different name for NotSet > while it seems a general concept of the > language. > > Besides the example I proposed, I think > that there are many cases where you > can check if the property is initialised > or not and for consistency "null" should > be considered a valid initialization value. > > Are there any downsides in adding a > specific syntax to check if a property > is initialized with any value? > > Thank you. > > Luigi Cardamone > Backend developer > Italy > > Il Sab 18 Mag 2024, 11:19 Robert Landers ha sc= ritto: >> >> On Fri, May 17, 2024 at 11:43=E2=80=AFPM Luigi Cardamone >> 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 = value: >> >> 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 Please remember to bottom post! > it works but it > leaves some doubts since each project > can have a different name for NotSet > while it seems a general concept of the > language. Why does it need to be consistent between projects? Most languages simply set uninitialized values as `null`, and every project across all languages will have to solve this differently, specific to their project. For PHP projects, it really depends on how you want to handle it in your project. I have a project where an uninitialized value during serialization/deserialization is an error because that means someone forgot to map something or the end-user forgot a field in their request. In another project, values are uninitialized on purpose and accessing properties goes through __set and __get. I don't think there's a silver bullet here. > I think > that there are many cases where you > can check if the property is initialised > or not and for consistency "null" should > be considered a valid initialization value. Well, that depends on your application's business logic and model. A bank account probably shouldn't be allowed to have a null balance, a player have a null position, or a farmer have null goats. > Are there any downsides in adding a > specific syntax to check if a property > is initialized with any value? Personally, I've used such a check so rarely and when I've done so, it has been in the context of reflection, for which there is a method on ReflectionProperty (https://www.php.net/manual/en/reflectionproperty.isinitialized.php) to check for it. I've never needed to know the difference between uninitialized and null during regular runtime and $value ?? $default has always been what I've needed. In your case, this would probably be all you need: https://3v4l.org/p1nAHJ I guess this is a pretty good use case for nameof which keeps staying down near the bottom of todo list lately... Robert Landers Software Engineer Utrecht NL