Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:130811 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 325341A00BC for ; Fri, 8 May 2026 21:48:05 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1778276889; bh=TD9WZUX+BURSlKZ7G9t9TLNMoyYTap3LBa9x0OS8Oyc=; h=References:In-Reply-To:From:Date:Subject:To:Cc:From; b=gOwfgbLfBpoXJ5Cm2lN6M93EcicbcaZls0EWWWoGrqw6eMuqO2UHAF7r7ztPpvzCb cvFyKks5rGvk/xkLwgpDnLCRq8SapHhjrT17kTZcMmlbkKjucCMrdUlhNpVicJ8w9Q b2Q9OCZmAUXHD4DlAAZLwmLaTxWsWuVajyiby5LDFKTn8CFWZNJulYqCwD3l+UneT+ v8B8UtclSDYsKiGtQ2YYDL+kJv+5aJfKgnwDeiITmZVP8wPMZyXoWWyYbyZ8VSkU8d CbUTQ/keTM0ZPXGjP0LNZwphXjsd8Jh4OQgWtyJ7Vus/qYlmOg8nKQxhLOS5gT+LZa sr/9kPxp6hIBw== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 0D436180057 for ; Fri, 8 May 2026 21:48:09 +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, HTML_MESSAGE,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-yw1-f173.google.com (mail-yw1-f173.google.com [209.85.128.173]) (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 21:48:08 +0000 (UTC) Received: by mail-yw1-f173.google.com with SMTP id 00721157ae682-7982c3b7da9so22453067b3.1 for ; Fri, 08 May 2026 14:48:03 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1778276883; cv=none; d=google.com; s=arc-20240605; b=RNUOsgxvBBYaxNicWwd54TzYI4j/eIzGQYVGh8QkI3kCFmASJsv9zYTkU4JJmQux5Q H6k2cqd8SFu+n3v1PCfLUHIiGVOyK0VNJLVo60yZNYCrhshwOpmQgYohZ93JpRvpNSYE k6yg+itiU7YfGBPBvmN2W7b7CtmiUJkidz0llpDVHMRlMYfkAtwDjzU3ddLMGKz7cOaZ 1R/Jzt0vETYZ6XHkSyjVKRnfsVEuUGImM54va5Dq4cERI/+YdDB4Mdy/xp9zk5gWbdpo HLP9nvlqhs23+J2j+0TP+sABpD9bxopyYlJragOu3Hrv8P9slUe/ISPdXacEYhLGG0tx 9RVw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:dkim-signature; bh=IH8TCjiPhyXbQ9QOOLVbGD+EN2HgXQvuZ3RYRm7+V4w=; fh=Fz+yaYq/ipmcxJxrsXZuonPjV0mCvB6tkNJiJs3sSQA=; b=G/WyyTAz65Lu7sVMTvQlmm1hlTBtJJYnnT+atYLnFS81M92hmrCPchfWuKafEKk/Zf mzeXVXNmS3FS6x/NZrURKXtl1e8yzvlFBAEqHTQt1OUDyqDk6iOYOwMQbXE3N+vRmbKo IQyOiJMbiNmLBxBbis77wlPQ23FG98C43ACAtwYJ7thoWOJQbC/zo5T5OyF1Ir39FetZ K6Y80LEo9J+Fcjb8RXO3aZ76pD5MTSCeca/jMFm+5xrbDR16dIvbfsWFenbA8DzHBYKI se2KxP30Bwad8iYK9NHvTKPdj5q+Bjky0ZWaCKe2NU842/zvfXra4HAZRwNnhpoTsVbR 9ytA==; 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=1778276883; x=1778881683; darn=lists.php.net; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:from:to:cc:subject:date:message-id:reply-to; bh=IH8TCjiPhyXbQ9QOOLVbGD+EN2HgXQvuZ3RYRm7+V4w=; b=LiQTeBirlnqVG8wlyyQvjOL9gcLs4m4jKL1xDAfBPZqKPkm46GCzSC+NDzV8xzAb9f Q0Svg1KyEXoSXVYLYxsbXHkSDinycbEXU7KFgMoZVaHgLQ1hUph1J7W7gqZIreLzd+IW qrJHywpDSxiAlcbPNyzmdJW2+jAxK4PoeAQZWt8QhPK/cjGWG/Y9JnWHFoDAAl/rlpL3 9/ZjQj1DQ7axuKGIGb/xQDxYplUGqsXJbK3f0lSWoY9EeQB4VxH+jCgfX8JDTXXi0cWG kmtnQJavSGQzme469dmPs/d4w0LVXrdhNkC3HjgKq7Mfil66zBf8mxZc6gAJezVtYDVG 37HA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1778276883; x=1778881683; h=cc: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=IH8TCjiPhyXbQ9QOOLVbGD+EN2HgXQvuZ3RYRm7+V4w=; b=T2/TFpb2RDl19byv76xk4hb0g5A77M0TerHaq/zR7uTBq9kXM36YEnZawErkGULXXu G7CUfYh/XfugTA1bcorSscbcMbjtlymhZbvTFSAsFGKpXsQ/ueT/BWhLtAirQXgQ9SNX 8V595nEmRpUCBNexh+m8/Z0Mmx+FbRp2NiuQJ+9mwLrdCG7nJYTMyGUxNapGfbmBOGob 9JpkwfisLslOzimAkUnBWE01QD+V9ZAikZQwxFlghg4euxb6ZRFKQpePwyz7YkCM8zel y+IVKFnmQwJCZgAE4A3wXBlqILcSw9iARIBtmyFOuLbllad6RjxPoQQgVwT7ySTtKzlP 6t1Q== X-Forwarded-Encrypted: i=1; AFNElJ/MnjOFa1y7yT8I3KaGIU2UFIFcv7y1tn4O9KJ2P+GR2OBr14XKbklWN9nI+e/9F7C6w7QoVOVKlFM=@lists.php.net X-Gm-Message-State: AOJu0YxKD/kffVR45Yby+tkAqeNd2OySZeRQC8be6Qc4nE7aCsmIH34J ABZpSvNUopDR0jNw4Poa8+y2hGTHO2pcBNiXTya0VxigF8OqrJqKEm4fBYxD9gcY0aCyRxrRAjW GAd2Mnfg5eXo8zP35/wgjIf+qLvThJu+pWhsu X-Gm-Gg: Acq92OFb7lvGQKpYuf3QuBXsqIr18XUXhUuP2wRFMROPZXyhlCoO0duZqQD2lVIcU0j 6dx2UeZqLYcAtlWsicNKs37kgbrtxVhnJcL8tsFuGYXjHkoju/S8MP1t4JPKzJnHu6x6k+5qSid fzmN0m3WMmSK8zzfeeDhIKPBk403p2ffVMXr8s5NqhpGeyWTOGykggMRvKL4DabPAUVzstMwXYw p/GXzYIc0WsH59cma6vXSb6LKxeVhJ+8zzjzQtei9XzekA8yL+YZbcV4ckWpQnGgxjxY1OTcEwf o2bum6c= X-Received: by 2002:a05:690c:368f:b0:7b7:de6:336f with SMTP id 00721157ae682-7bdf5eeea23mr155849097b3.40.1778276882993; Fri, 08 May 2026 14:48:02 -0700 (PDT) Precedence: list list-help: list-unsubscribe: list-post: List-Id: x-ms-reactions: disallow MIME-Version: 1.0 References: <5686cf60-1920-4f0f-b8f3-9df788f759bf@app.fastmail.com> In-Reply-To: Date: Fri, 8 May 2026 14:47:27 -0700 X-Gm-Features: AVHnY4LZGHKDaPJO0TS4iAMcWNKwc8lrl0vMved9gmLyYCnrLUyGJGp8tnnZLuA Message-ID: Subject: Re: [PHP-DEV] Pre-RFC discussion about adding friendship to PHP To: Max Semenik Cc: Larry Garfield , php internals Content-Type: multipart/alternative; boundary="000000000000ec56df06515559e2" From: daniel.e.scherzer@gmail.com (Daniel Scherzer) --000000000000ec56df06515559e2 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable On Fri, May 8, 2026 at 2:42=E2=80=AFPM Max Semenik = wrote: > On Thu, Apr 30, 2026 at 5:10=E2=80=AFPM Larry Garfield > wrote: > >> class User { >> friend UserFactory; >> >> public friend(set) string $name; >> } >> >> class UserFactory { >> public function makeUser($name) { >> $u =3D new User(); >> $u->name =3D $name; // This is OK, because UserFactory is a friend. >> return $u; >> } >> } > > > This seems like an overcomplication, in current PHP this would work just > fine: > > class User { > public function __construct( > public readonly string $name, > ) {} > } > > Some of C++ OOP features have always felt like kludges to me, and > friendships are a good example. A well-written class shouldn't care what > other classes are using it, as long as they respect its contract. > > -- > Best regards, > Max Semenik > That example works for users with just a name, but what about users with both a name and user id, with the class invariant that the user with the given name has that specific ID? A class like ``` class User { public function __construct( public readonly string $name, public readonly int $id, ) {} } ``` means that the requirement is on *callers* to get it right, on pain of breaking a whole bunch of things that assume the user id and username correspond to the same record. And while you could do that, it makes it a lot easier to break things. Instead, you would want to have the constructor private. But then, how to create new instances of the User class when you have properly looked up the user id and name in the database? You could add a public static method on User, which would be able to call the constructor, but static methods present other complications with dependency injection and unit testing. And once you move to a separate UserFactory, you wind up with the original issue this seeks to address - how can UserFactory interact with the internals of the User class. Other than making those internals public (which we don't want to do) the only option is to use reflection (which is generally frowned upon). Hence, the proposal to add friends. -Daniel --000000000000ec56df06515559e2 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
On Fri, May 8, 2026 at 2:42=E2=80=AFPM Ma= x Semenik <maxsem.wiki@gmail.co= m> wrote:
On Thu, Apr 30, 2026 at 5:10=E2=80=AFPM Larry Garfield <larry@garfieldtech.com= > wrote:
class User {
=C2=A0 friend UserFactory;

=C2=A0 public friend(set) string $name;
}

class UserFactory {
=C2=A0 public function makeUser($name) {
=C2=A0 =C2=A0 $u =3D new User();
=C2=A0 =C2=A0 $u->name =3D $name; // This is OK, because UserFactory is = a friend.
=C2=A0 =C2=A0 return $u;
=C2=A0 }
}

This seems like an overcomplication, in c= urrent PHP this would work just fine:

class User {=
=C2=A0 =C2=A0 public function __construct(
=C2=A0 =C2= =A0 =C2=A0 =C2=A0 public readonly string $name,
=C2=A0 =C2=A0 ) {= }
}

Some of C++ OOP features have = always felt like kludges to me, and friendships are a good example. A well-= written class shouldn't care what other classes are using it, as long a= s they respect its contract.

--
Best regards,
Max Semenik
=

That example works for users with just a n= ame, but what about users with both a name and user id, with the class inva= riant that the user with the given name has that specific ID? A class like<= /div>

```
class User {
=C2=A0 = =C2=A0 public function __construct(
=C2=A0 =C2=A0 =C2=A0 =C2=A0 p= ublic readonly string $name,
=C2=A0 =C2=A0 =C2=A0 =C2=A0 public r= eadonly int $id,
=C2=A0 =C2=A0 ) {}
}
`= ``

means that the requirement is on *callers* to g= et it right, on pain of breaking a whole bunch of things that assume the us= er id and username correspond to the same record. And while you could do th= at, it makes it a lot easier to break things. Instead, you would want to ha= ve the constructor private.

But then, how to creat= e new instances of the User class when you have properly looked up the user= id and name in the database? You could add a public static method on User,= which would be able to call the constructor, but static methods present ot= her complications with dependency injection and unit testing. And once you = move to a separate UserFactory, you wind up with the original issue this se= eks to address - how can UserFactory interact with the internals of the Use= r class. Other than making those internals public (which we don't want = to do) the only option is to use reflection (which is generally frowned upo= n).

Hence, the proposal to add friends.
=
-Daniel
=C2=A0
--000000000000ec56df06515559e2--