Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:123634 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 0CEED1A009C for ; Sun, 16 Jun 2024 13:32:51 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1718544842; bh=5/4xDMYDecR7IeqP0iDPyYAXJlvzXhpNkWynjc2/jfU=; h=From:Subject:Date:In-Reply-To:Cc:To:References:From; b=YGLSbVQsM6RWg+6zYTBkS6CqhdgMAwMuq6E3fVNXwcVAUZ/bndYRLdlpqDRopf/dZ mWpUDaUKOTlX2fPkoIWKAZWf2MZeO68MEFcCUyI54BAsQ+/Di0YM1eZB11xlQz04E/ Qy4WaZ3YKYPkYZIbcj74XaH7WmWNP3taMlsEnV5BlOPs0nV1K6lO3OxG7zNv+2KQPp ZtLrJvtiDXl6icv2MNc6BbLW9LagwRWvN/swY+2KPCUvsJ+Ml5ARBD5KEQ89zEYA7j 4lz98s/ZnEAF0IJlXKI4sSI83GL4cxHJlyPfo8IqFLpGyCg8UH9+zdeh6uRPgMkrAT NhcJD1W/gjLwg== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 84C1518005A for ; Sun, 16 Jun 2024 13:34:00 +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.8 required=5.0 tests=BAYES_50,DKIM_SIGNED, DKIM_VALID,DMARC_MISSING,HTML_MESSAGE,RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_NONE,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-yw1-f175.google.com (mail-yw1-f175.google.com [209.85.128.175]) (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 ; Sun, 16 Jun 2024 13:34:00 +0000 (UTC) Received: by mail-yw1-f175.google.com with SMTP id 00721157ae682-627efad69b4so34294327b3.3 for ; Sun, 16 Jun 2024 06:32:48 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=newclarity-net.20230601.gappssmtp.com; s=20230601; t=1718544768; x=1719149568; darn=lists.php.net; h=references:to:cc:in-reply-to:date:subject:mime-version:message-id :from:from:to:cc:subject:date:message-id:reply-to; bh=USqLppxe41eN+6g32zf4yBj/wPcZFxsBJeGddh2mhCw=; b=p5NGjxWQdT0e/zZ6UXEkIAnPjkTAIDfL5OjXdq7XjyjykRu5CVXO1P2HnPQc+BbvKy b0i4S0RmkgPTq+y0DpaVNs93LoKrc7cSUSR1fLvSgLwP6ACpFi8ubYp14Q39s2fiIFOG Bb9hcHydiA87pfuuGrdp0IyxCagkoCM1mrvvo2nkwc0ainUMKSjb+AKaT4eCK97nATlK zRWuYFhIfjy3EE1JUUi5YyiwXqbtDP99uXk5IOcbExCVVxcXnCkEdkNn1ORbbvi46/PF +19OoZAr2UEDZB5XM+fk6qDfMcx7nGkWU/xXvmjUaE+xyZqGq7L3k3+eCx3lBPinJ3XV J7ig== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1718544768; x=1719149568; h=references:to:cc:in-reply-to:date:subject:mime-version:message-id :from:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=USqLppxe41eN+6g32zf4yBj/wPcZFxsBJeGddh2mhCw=; b=U6EV5EvvSD0lqdzm4ssOy77JOuz/x8DQU5Z+HyjVc1RZFrlzwBAmkKa3iub+CARC/h RYj3c573Sog3ciIHAD08kIOWYncj+IM1p5+pMNfQ9cdNKfeeXHnoUzdLlaj4+qfDeg4K 2lv+NI3DHXJ+tCGoZaX+VE3XU0/8Qj8UOBpUOXyxCmwGt+8MknjhIX5hVGFPJzZRrcdH I1diwq7RRSyZpoFlIBzPWe7iFlyMXlYAKkUQxH8M2oZPR9Was2CzplbUz0Rh2jEh75Wr GT73fzgX2nXBQC7S2WEWPnf7wCFjVC5etuvZX54GA2m8lqBBmUHKX7PETH7kLkwq8kwg stNg== X-Gm-Message-State: AOJu0YwJIhYS+giX5mY/ILvlHg9Hc+XvwKlVYUNhqvNM8mjyjvzq+Cdp Eit11ItR/JHjxVQsPb6OTAN4eb53EIuhVe/bRIRydM5FO5DJ1y6TYHA0/3Q4UyTwtxcWEyMVv4q v4xY= X-Google-Smtp-Source: AGHT+IFrvu366MnumGzJpPZkQRQ0rUnKTB776lVaTfFAD4z/peHFmyNsD3T4yXqAsMRir2/VZaJcCg== X-Received: by 2002:a0d:c087:0:b0:630:2749:2f4d with SMTP id 00721157ae682-6322480f694mr70711887b3.36.1718544768042; Sun, 16 Jun 2024 06:32:48 -0700 (PDT) Received: from smtpclient.apple (c-98-252-216-111.hsd1.ga.comcast.net. [98.252.216.111]) by smtp.gmail.com with ESMTPSA id 00721157ae682-631189a7e4dsm10874877b3.38.2024.06.16.06.32.46 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Sun, 16 Jun 2024 06:32:46 -0700 (PDT) Message-ID: <82601236-3228-491E-B776-457331B41C6B@newclarity.net> Content-Type: multipart/alternative; boundary="Apple-Mail=_FD87F9D8-D129-459A-A7FA-73CF224F9794" Precedence: bulk list-help: list-post: List-Id: internals.lists.php.net Mime-Version: 1.0 (Mac OS X Mail 16.0 \(3696.120.41.1.8\)) Subject: Re: [PHP-DEV] Static class Date: Sun, 16 Jun 2024 09:32:44 -0400 In-Reply-To: <04ae10a2-ceae-4996-a7fe-9b38d2f81ca2@scriptfusion.com> Cc: internals@lists.php.net To: Bilge References: <0cf69a14-f1b5-4077-9d91-d7b579485eec@scriptfusion.com> <936e1aa3-48cc-4552-9f68-676ebcdeb596@rwec.co.uk> <04ae10a2-ceae-4996-a7fe-9b38d2f81ca2@scriptfusion.com> X-Mailer: Apple Mail (2.3696.120.41.1.8) From: mike@newclarity.net (Mike Schinkel) --Apple-Mail=_FD87F9D8-D129-459A-A7FA-73CF224F9794 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=utf-8 > On Jun 16, 2024, at 5:17 AM, Bilge wrote: >=20 > Let's start getting specific so we can make some progress. >=20 > The goals of this RFC are fairly straightforward: > Introduce the `static` keyword at the class level to preclude the need = to create a private constructor. That is, `__construct` would be invalid = in a static class. > Prohibit instantiation of a static class with a language-level error. > Prohibit declaration of instance members in a static class with a = language-level error. > However, as ever, there's a devil in the details. In particular, we = need to consider the following: >=20 To start, any limitations imposed on these new static classes that = current classes can do that are not intrinsically linked to their = "staticness" would result in developers grudgingly writing a class = "statically" that is not declared as static. Imposing restrictions on = features that developers use in the wild would certainly cause them to = consider the feature to be dubiously excluded.=20 Not supporting all features used in the wild would result in developers = not being able to use static classes for new and/or refactored code if = they believe they need those excluded features. This would stop = developers from signaling their intent to readers of their code and = would stop developers from being able to rely on reflection to discern = static classes for new and/or refactored code when that otherwise could = have been possible.=20 Disabling existing features just for static classes would result in = creating two forms of static classes =E2=80=94 explicit and implicit =E2=80= =94 and that IMO would be a miss for the addition of static classes. =20 That said... > 1. Since a "static class" implies all members are static, should we = still allow explicit static method declarations with the `static` = keyword? >=20 Yes, but optional.=20 Supporting the static `keyword` for members would ease the transition = for tooling, and support those who prefer to be explicit in all the = things. OTOH, of all the things I mention below, this is my least firmly-held = opinion. > 2. Should `static` imply `final`? >=20 No.=20 The primary PHP framework I wrote before I quite working professionally = in PHP =E2=80=94 although others still use it =E2=80=94 has a series of = implied static classes, all of which inherit from a base implied static = class that provided services to all other implied static classes. To = update this library to a newer version of PHP with static classes would = not be possible if static classes are assumed to be `final`. Further, Laravel =E2=80=94 which I have never used but is simultaneously = the most beloved framework in PHP but also the most hated, depending on = who you ask =E2=80=94 has a base `Model` class that Eloquent models = inherit from, and a `BaseController` for custom controllers. Enforcing = `final` would leave Laravel out in the lurch for classes that are = exactly the type of classes that should be declared static. If a developer wants their declared static class to be final they should = be required to use the `final` keyword, IMO. BTW, see #4 and #5 why this is important. > 3. Should a "static class" prohibit inheritance? >=20 Isn't #3 just a rewording of #2? =20 > 4. Should a "static class" permit state? >=20 Absolutely, without a doubt. My PHP library uses static properties to keep track of certain data = which I treated as immutable =E2=80=94 registering business information = for use by static factory methods, and in some cases the factory methods = use arrays to store instances they create for processing and/or = dispensing on demand late by other static methods. Laravel uses static properties in their service containers such as = `Illuminate\Support\Facades\App`, their Cache facade uses static = properties, Eloquent models maintain state in static properties, and = developer written factory classes often use static properties to track = instances. While we can ignore my library it would be much harder to ignore = Laravel's use of state in static properties. > 5. Should traits be permitted in a static class? >=20 Of course. =20 Laravel makes extensive use of traits in their implied static classes, = in their core framework and in Eloquent models, and they encourage = Laravel application developers to use traits in their applications. Traits are a valuable code structuring mechanism as an alternate to = inheritance more like containment, and not supporting traits would, = again, be leaving developers depending on it out in the cold. Also, final/inheritance might not be as critical to support if it were = not for one capability that PHP's traits are glaringly missing and that = is their inability to allow developers to declare properties and methods = as private to the trait itself. Of course if we add trait-private to traits then it would be less = problematic to implied `final`/not support inheritance, but I doubt we'd = want to couple this potential RFC with one that hasn't even been = considered yet.=20 Even so, not supporting inheritance would mean not allowing implied = static classes that use inheritance to be refactored to use the static = declaration. > 6. Which magic methods (if any) should be valid in a static class? >=20 Unless I am mistaken, the only magic method that support static function = calls is `__callStatic()` as everything else deals with instances, so I = assume that it is the only one that needs to be supported. And yes, IMO it is critical to support `__callStatic()` since Laravel = Facades (as well as my own library) make use of it, and in Laravel's = case, extensive use. =20 Of course there may(?) be newer PHP features on the horizon that are an = alternate to `__callStatic()` but supporting `__callStatic()` would make = it easier for developers to move to static classes as even automated = tooling could make the conversion if `__callStatic()` and all other = features used in the wild are supported.=20 Anyway, that is my take. #fwiw -Mike P.S. To learn about Laravel's uses of implied static classes I asked = ChatGPT[1], so if I got anything wrong about Laravel I apologize as I = was relying on ChatGPT not to hallucinate on this topic. I assumed it = was unlikely to hallucinate given there was so much info on the web = there is regarding Laravel for ChatGPT to train on. [1] https://chatgpt.com/share/79eb330b-69ae-4104-b2ac-6e77955ec914= --Apple-Mail=_FD87F9D8-D129-459A-A7FA-73CF224F9794 Content-Transfer-Encoding: quoted-printable Content-Type: text/html; charset=utf-8
On = Jun 16, 2024, at 5:17 AM, Bilge <bilge@scriptfusion.com> wrote:

=20 =20
Let's start getting specific so we = can make some progress.

The goals of this RFC are fairly straightforward:
  • Introduce the `static` keyword at the class level = to preclude the need to create a private constructor. That is, `__construct` would be invalid in a static class.
  • Prohibit instantiation of a static class with a language-level error.
  • Prohibit declaration of instance members in a = static class with a language-level error.

However, as ever, there's a devil in the = details. In particular, we need to consider the following:

To start, any limitations imposed on these new = static classes that current classes can do that are not intrinsically = linked to their "staticness" would result in developers grudgingly = writing a class "statically" that is not declared as static. Imposing = restrictions on features that developers use in the wild would certainly = cause them to consider the feature to be dubiously = excluded. 

Not supporting all = features used in the wild would result in developers not being able to = use static classes for new and/or refactored code if they believe they = need those excluded features. This would stop developers from signaling = their intent to readers of their code and would stop developers from = being able to rely on reflection to discern static classes for new = and/or refactored code when that otherwise could have been = possible. 

Disabling existing = features just for static classes would result in creating two = forms of static classes =E2=80=94 explicit and implicit =E2=80=94 = and that IMO would be a miss for the addition of static classes. =  

That = said...

  1. Since a "static class" implies all = members are static, should we still allow explicit static method declarations with the `static` keyword?

Yes, but optional. 

Supporting the static `keyword` for members would = ease the transition for tooling, and support those who prefer to be = explicit in all the things.

OTOH, of = all the things I mention below, this is my least firmly-held = opinion.

  2. Should `static` imply `final`?

No. 

The = primary PHP framework I wrote before I quite working professionally in = PHP =E2=80=94 although others still use it =E2=80=94 has a series of = implied static classes, all of which inherit from a base implied static = class that provided services to all other implied static classes. =  To update this library to a newer version of PHP with static = classes would not be possible if static classes are assumed to be = `final`.

Further, Laravel =E2=80=94 = which I have never used but is simultaneously the most beloved framework = in PHP but also the most hated, depending on who you ask =E2=80=94 has a = base `Model` class that Eloquent models inherit from, and a = `BaseController` for custom controllers.  Enforcing `final` would = leave Laravel out in the lurch for classes that are exactly the type of = classes that should be declared static.

If a developer wants their declared static class = to be final they should be required to use the `final` keyword, = IMO.

BTW, see #4 and #5 why this is = important.

  3. Should a "static class" prohibit inheritance?

Isn't #3 just a rewording of #2? =  

  4. Should a "static class" permit state?

Absolutely, without a doubt.

My PHP library uses static properties to keep = track of certain data which I treated as immutable =E2=80=94 registering = business information for use by static factory methods, and in some = cases the factory methods use arrays to store instances they create for = processing and/or dispensing on demand late by other static = methods.

Laravel uses static = properties in their service containers such as = `Illuminate\Support\Facades\App`, their Cache facade uses static = properties, Eloquent models maintain state in static properties, and = developer written factory classes often use static properties to track = instances.

While we can ignore my = library it would be much harder to ignore Laravel's use of state in = static properties.

  5. Should traits be permitted in a static class?

Of course.  

Laravel makes extensive use of traits in their = implied static classes, in their core framework and in Eloquent models, = and they encourage Laravel application developers to use traits in their = applications.

Traits are a = valuable code structuring mechanism as an alternate to inheritance more = like containment, and not supporting traits would, again, be leaving = developers depending on it out in the cold.

Also, final/inheritance might not be as critical = to support if it were not for one capability that PHP's traits are = glaringly missing and that is their inability to allow developers to = declare properties and methods as private to the trait = itself.

Of course if we add = trait-private to traits then it would be less problematic to implied = `final`/not support inheritance, but I doubt we'd want to couple this = potential RFC with one that hasn't even = been considered yet. 

Even so, not supporting inheritance would mean not = allowing implied static classes that use inheritance to be refactored to = use the static = declaration.

  6. Which magic methods = (if any) should be valid in a static class?

Unless I am mistaken, the only magic method that = support static function calls is `__callStatic()` as everything else = deals with instances, so I assume that it is the only one that needs to = be supported.

And yes, IMO it is = critical to support `__callStatic()` since Laravel Facades (as well as = my own library) make use of it, and in Laravel's case, extensive use. =  

Of course there may(?) be = newer PHP features on the horizon that are an alternate to = `__callStatic()` but supporting `__callStatic()` would make it easier = for developers to move to static classes as even automated tooling could = make the conversion if `__callStatic()` and all other features used in = the wild are supported. 

Anyway, = that is my take. #fwiw

-Mike

P.S. To learn about = Laravel's uses of implied static classes I asked ChatGPT[1], so if I got = anything wrong about Laravel I apologize as I was relying on ChatGPT not = to hallucinate on this topic. I assumed it was unlikely = to hallucinate given there was so much info on the web there is = regarding Laravel for ChatGPT to train on.

[1] https://chatgpt.com/share/79eb330b-69ae-4104-b2ac-6e77955ec914<= /a>= --Apple-Mail=_FD87F9D8-D129-459A-A7FA-73CF224F9794--