Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:127405 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 931391A00BC for ; Tue, 20 May 2025 14:05:02 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1747749773; bh=30Nh4hiRF74TECtkWm21jpdJQzNNphUd+0mQKKemd2E=; h=References:In-Reply-To:From:Date:Subject:To:From; b=l+9GW0q1my+PSGiPIuDHwARZksZWQ6Hndho94SSq5ORDsp5XdUxKLhyefNKDu7Vn9 P3pwZXKZoJagffAl3SCFkPUXfC8GSehVeQoSaAI7RjunwnJJiaTV1hGImrE6UOAnfn Ufa8vefMWcNo5WCNsyfGWci7+K9cpuEG2Ml0ZScX3dtNHmHIZPcbwOxEy1HOx/EVNu R/7t9VLPpUhvI88+M4NtBHQ3zdf59DZ4TY5j5XPnJx+EnGtehCUHLZm9xB0UL0chrZ QIU95svQH/4FuPf6UTsot2WQ5bZNSEX7R5gPraKj6mw4aSVG0ab1W06U/ywucfYbaD LhbVKDAjpJlTw== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 65B2C180080 for ; Tue, 20 May 2025 14:02:52 +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, HTML_MESSAGE,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_HELO_NONE, SPF_PASS 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-qv1-f45.google.com (mail-qv1-f45.google.com [209.85.219.45]) (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 ; Tue, 20 May 2025 14:02:52 +0000 (UTC) Received: by mail-qv1-f45.google.com with SMTP id 6a1803df08f44-6f8d663fa22so32849736d6.0 for ; Tue, 20 May 2025 07:05:01 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1747749900; x=1748354700; darn=lists.php.net; h=to:subject:message-id:date:from:in-reply-to:references:mime-version :from:to:cc:subject:date:message-id:reply-to; bh=W5bE+d0rCZv7iZ/Sq2GxiRARpkJX8ciL9/5PhkVJ1UE=; b=a2tlCmnTu8JZ9W69qXa0BDzRMFdBZSr5V0LN9xRYxTn+QOByVkquJZCFyTG0V7bwCh AOuTMzsqP5cyUN/5RQlf5dv9zhi2o8VlNHs4swc7dF4qQ7fqvnnf3Y13tsHe0bIOB9p/ 77HecJDAYci11jpGhlrUwnmwCuK8UV/gdUApDo643jdGSI/AQQ+H6z0ziqrQzUBC0ov5 R3LmXiXiiCgt6Nt4eyUWUqHnFesV1njkgMNEUzBMlvxZZ+VAxXArO7Br4lsbU3mAaphB Z+wz/yOVY7XcOgasD0GLstbJJJiVvBImWF/gQTssKBsc7FW9fidDyH+p0w0h8iytHkGh y2UA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1747749900; x=1748354700; h=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=W5bE+d0rCZv7iZ/Sq2GxiRARpkJX8ciL9/5PhkVJ1UE=; b=KXaefHNtC0fco3GnLAeD0noYpONaJv6o39usJc+4ioI9ZM1bgbWbI4n761vKs+NTwf KrH799AJBmoGj7FgUjcUwJfPVcJzdXfsSDRjNoC/buAR6/OmBPVsqpQVHHUCfT38L3bZ 54ZNIBAqJ8E50+sTD4LUqQTduFptGtIfM49QzYfJy9A22j5QHOR9oybondhWHE25v4Fa 23Zu/QfFKSOMm56IzrrODXMxz6izZpxhKZtGeGE4nIC8XlQVqfaxLZYOd1p9TtresFUA U6x8d20b2jW103IPX0U/31HWP5l/eXvfh7xJOInFsGSA9ho12kGi9cw2tEVtKF25+xa/ D+Qg== X-Gm-Message-State: AOJu0Yw2a5EpcCvJbFWw5pZWaD1J5Gm2kbnaCD2p+x1miTCTfdmWmV6F SS3UjjEEEVX7Enp150kcyDha2p4xK/talBgCnbZJmcKs/mpUowhdnDs17VIYbnbVzLdE6TsodeU XgkhuergqCYbS6hTgYd8O59q4v3HSvdQLCQ== X-Gm-Gg: ASbGncv5VrbqQul9W4BKRATZ8PfhlbuhrO09gcGvhnopWTt7ZchOo2scij2ghzPiTvM b+f4kejzBscd/9Tq57nmU+XIr8+nC/Ri2AUj6HQDsth+F/xX60vjs+H0u4hH3vETAMKPOSUs6eF yOBKZYwQ3xUgAxUlYksWs1C/WJA/V54dHmhfZ963r6d/W5P9oYB6q/lMIqIGwMaAs= X-Google-Smtp-Source: AGHT+IEdzC1jWe3DXdtOVQe1uqL1BrU7D3h8nOOANwSGoeYO6k7ZX3wFZGnhgVqyAsCfjHgALv7Kmcdm1NnmdAqsWPM= X-Received: by 2002:a05:6214:124c:b0:6f5:3e38:6127 with SMTP id 6a1803df08f44-6f8b2d3ccc8mr273427266d6.42.1747749899632; Tue, 20 May 2025 07:04:59 -0700 (PDT) Precedence: bulk list-help: list-post: List-Id: internals.lists.php.net x-ms-reactions: disallow MIME-Version: 1.0 References: <3ae9a6ea-f135-472b-b2bf-e6cd6ebad299@app.fastmail.com> <9A26F72B-D0EF-414F-B193-BED3CAB26A0B@rwec.co.uk> <9f6a0d6e-27c3-4f77-aed6-e55147442b6f@app.fastmail.com> <673fd2db-b07f-439b-a4f2-e9519108d159@app.fastmail.com> In-Reply-To: <673fd2db-b07f-439b-a4f2-e9519108d159@app.fastmail.com> Date: Tue, 20 May 2025 10:04:49 -0400 X-Gm-Features: AX0GCFsFM168Mn_ft1WDFxuziz6gmHpYmznw8lOe3BA98LM6nCHcykLFSkW3_34 Message-ID: Subject: Re: [PHP-DEV] Module or Class Visibility, Season 2 To: internals@lists.php.net Content-Type: multipart/alternative; boundary="000000000000ec8268063591bb16" From: tendoaki@gmail.com (Michael Morris) --000000000000ec8268063591bb16 Content-Type: text/plain; charset="UTF-8" The Problem: Interoperability. That's really it. Scenario Alice provides whatchamacallit A that depends on other whatchamacallit D to work. Bob provides whatchamacallit B that also depends on D. Charles is using A and B. D gets updated with a new incompatible API to its prior version. Alice publishes an update which includes a security fix. Bob retired. Charles, who can't program, can't update to Alice's latest code. His site eventually gets pwned. That's the problem. Packages with dependencies are not interoperable at this time. They must be self contained. This is why WordPress doesn't support Composer at all. Drupal, Laravel et al bypass this problem by forcing all their whachamacallits to stay on the same version. This has limited their market penetration compared to WordPress because, despite being significantly superior codebases in all respects, they aren't user friendly to someone who doesn't code at all. The Solution (10,000 overview) Composer could be made to allow interoperable packages, but it will need support at the language level to do so. Specifically, it needs to know who wants what. It can then make decisions based on that information. Composer's primary link to the language is the autoload closure it provides. That closure currently takes one argument - the fully qualified name of the symbol to be loaded - currently almost always classes as for various reasons function autoloading isn't a thing. Can it not take a second argument to modify its behavior? The current behavior is to flat require the file if it is found in accordance to whichever schema is in use. Perhaps we don't want that anymore - perhaps we want to return the file path to use. This allows the engine to make decisions about how exactly to include the file, including the possibility of monkey typing it as can be done in userland, though when done in userland this effectively generates a new package. (5,000 ft. overview) Suppose we have a whatchamacallit that declares its namespace as a new root independent of / . If a file inclusion happens in this namespace, this namespace prepends everything in the included file. So if I do a file include in the \MyPlugin namespace and that file declares its namespace as Twig, it will become \MyPlugin\Twig. That works, but direct file include is no longer the PHP norm though. Autoloading is. So we need to tell the Autoloader that we want a file path returned - do NOT require the file yourself in your namespace. This could be as simple as a boolean flag of true sent to the autoloader. BUT it isn't - the autoloader (usually composer) needs to know the identity of this requestor because by configuration in the package json (the details of which are wildly out of scope) it might change which file path it returns. When the engine gets the path it does the include and the prepending business on the fly that Strauss and similar packages already do in userland. (2,500 ft overview) The above I think would more or less work, but it would lead to massive code duplication as Whatchamacallit A and B now have their own D's at \A\D and \B\D (assuming namespaces match whatchamacallit names). Here's what I think would prevent that: A asks the autoloader for D. The autoloader returns a file path and the engine mounts to \D B asks for D. The autoloader returns a different file path so the engine mounts to B\D and rewrites the D file with the new namespace the same way Stauss would have done. This works except for the problem of who had the older version, A or B? and what order are A and B going to be asking - cause depending on the application's architecture this order is not guaranteed. To solve this the autoloader can tell the engine it is safe to mount the file on root using an array return of [path, true] and mount on the whatchamacallit's namespace if [path, false]. So A asks for D. Autoloader returns [path, false]. Engine maps to \A\D and monkey types D as needed. B asks for D. Autoloader returns [path, true]. Engine maps to \D Non whatchamacallit code at namespace C asks for D. It will get the same version B is using and the autoloader shouldn't be queried unless C makes this ask before B. When C asks the autoloader gets (string RequestedSymbol, null) so it can either do the require itself or return a string, either will work (and it has to be this way for backwards compat). When B asks the autoloader gets ( Requested, 'B' ) and it should return [path, true] I hope the above is followable. It's more of a morning brainstorm than a spec. --000000000000ec8268063591bb16 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
The Problem: Interoperability.=C2=A0

That's really it.=C2=A0 Scenario=C2=A0
Alice provide= s whatchamacallit A that depends on other whatchamacallit D to work.=C2=A0<= /div>
Bob provides whatchamacallit B that also depends on D.
= Charles is using A and B.
D gets updated with a new incompatible = API to its prior version.
Alice publishes an update which include= s a security fix.
Bob retired.
Charles, who can't p= rogram, can't update to Alice's latest code. His site eventually ge= ts pwned.

That's the=C2=A0problem. Packages wi= th dependencies are not interoperable at this time. They must be self conta= ined. This is why WordPress doesn't support Composer at all.
=
Drupal, Laravel et al bypass this problem by forcing all the= ir whachamacallits=C2=A0to stay on the same version. This has limited their= market penetration compared to WordPress because, despite being significan= tly superior codebases in all respects, they aren't user friendly to so= meone who doesn't code at all.


= The Solution (10,000 overview)
Composer could be made to allow in= teroperable packages, but it will need support at the=C2=A0language level t= o do so.=C2=A0 Specifically, it needs to know who wants what. It can then m= ake decisions based on that information.

Composer&= #39;s primary link to the language is the autoload closure it provides. Tha= t closure currently takes one argument - the fully qualified name of the sy= mbol to be loaded - currently almost always classes as for various reasons = function autoloading isn't a thing.=C2=A0 Can it not take a second argu= ment to modify its behavior?=C2=A0 The current behavior is to flat require = the file if it is found in accordance to whichever schema is in use.=C2=A0 = Perhaps we don't want that anymore - perhaps we want to return the file= path to use. This allows the engine to make decisions about how exactly to= include the file, including the possibility of monkey typing it as can be = done in userland, though when done in userland this effectively generates a= new package.


(5,000 ft. overview)<= /div>
Suppose we have a whatchamacallit that declares its namespace as = a new root independent of / .=C2=A0 If a file inclusion happens in this nam= espace, this namespace prepends everything in the included file. So if I do= a file include in the \MyPlugin namespace and that file declares its names= pace as Twig, it will become \MyPlugin\Twig.

That = works, but direct file include=C2=A0is no longer the PHP norm though. Autol= oading is. So we need to tell the Autoloader that we want a file path retur= ned - do NOT require the file yourself in your namespace.=C2=A0 This could = be as simple as a boolean flag of true sent to the autoloader. BUT it isn&#= 39;t - the autoloader (usually composer) needs to know the identity of this= requestor because by configuration in the package json (the details of whi= ch are wildly out of scope) it might change which file path it returns.

When the engine gets the path it does the include and= the prepending business on the fly that=C2=A0Strauss and similar packages = already=C2=A0do in=C2=A0userland.

(2,500 ft overvi= ew)

The above I think would more or less work, but= it would lead to massive code duplication as Whatchamacallit A and B now h= ave their own D's at \A\D and \B\D (assuming namespaces match whatchama= callit=C2=A0names).

Here's what I think would = prevent that:

A asks the autoloader for D. The aut= oloader returns a file path and the engine mounts to \D
B asks fo= r D. The autoloader returns a different file path so the engine mounts to B= \D and rewrites the D file with the new namespace the same way Stauss would= have done.

This works except for the problem of w= ho had the older version, A or B? and what order are A and B going to be as= king - cause depending on the application's architecture this order is = not guaranteed.=C2=A0

To solve this the autoloader= can tell the engine it is safe to mount the file on root using an array re= turn of [path, true] and mount on the whatchamacallit's=C2=A0namespace = if [path, false]. So

A asks for D. Autoloader retu= rns [path, false]. Engine maps to \A\D and monkey types=C2=A0D as=C2=A0need= ed.
B asks for D. Autoloader returns [path, true]. Engine maps to= \D=C2=A0

Non whatchamacallit=C2=A0code at namespa= ce C asks for D. It will get the same version B is using and the autoloader= shouldn't be queried unless C makes this ask before B.=C2=A0

When C asks the autoloader gets (string RequestedSymbol, nu= ll) so it can either do the require itself or return a string, either will = work (and it has to be this way for backwards compat).
When B ask= s the autoloader gets ( Requested, 'B' ) and it should return [path= , true]


I hope the above is followa= ble. It's more of a morning brainstorm than a spec.

--000000000000ec8268063591bb16--