Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:127521 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 1E2211A00BC for ; Sun, 1 Jun 2025 07:17:52 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1748762146; bh=K2kE4CRm9SmEO8mFIuYbYNwIWUHQBIZ65ErmPg9Tf5I=; h=Date:From:To:In-Reply-To:References:Subject:From; b=MmUaBv3k7WeQxH32dTkVjd0NQkwfIoZ211bYw0crPFKIfvgOyd+mGCWIeDn14HZxR HTXmyF7Uc+xwxI7IPBqQpSDGQLm3KQlxsEIt23vk+sK6AastsdWiODEMmByvW0FO7P V8rEGE6lkx8hDBuIAHAjD/HYSEehzZVzqpibacu29YkalKyQTVow3Cad3vOWemHRrY Cz+JoiWPZgCjv5130hm4/Jw0m+HpG6rorbgIFuD+gZIsJk1WPJxca+zgtQJw4eWLPP tKeUz7m5S+QHE0IMKCw/IIZz9fvCkUjdG6cdoIH6r0P2H0TGnpVz3pnfzHX8S6RnGF HHJmYmBtUS/7g== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 7974318006C for ; Sun, 1 Jun 2025 07:15:45 +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=-1.4 required=5.0 tests=BAYES_05,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,DMARC_MISSING,HTML_MESSAGE, RCVD_IN_DNSWL_LOW,SPF_HELO_PASS,SPF_PASS autolearn=no autolearn_force=no version=4.0.1 X-Spam-Virus: Error (Cannot connect to unix socket '/var/run/clamav/clamd.ctl': connect: Connection refused) X-Envelope-From: Received: from fout-b1-smtp.messagingengine.com (fout-b1-smtp.messagingengine.com [202.12.124.144]) (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, 1 Jun 2025 07:15:45 +0000 (UTC) Received: from phl-compute-05.internal (phl-compute-05.phl.internal [10.202.2.45]) by mailfout.stl.internal (Postfix) with ESMTP id 915F31140110 for ; Sun, 1 Jun 2025 03:17:49 -0400 (EDT) Received: from phl-imap-05 ([10.202.2.95]) by phl-compute-05.internal (MEProxy); Sun, 01 Jun 2025 03:17:49 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bottled.codes; h=cc:content-type:content-type:date:date:from:from:in-reply-to :in-reply-to:message-id:mime-version:references:reply-to:subject :subject:to:to; s=fm2; t=1748762269; x=1748848669; bh=FxoU17SfXz Mpgc2Nhdn1iNBp7KiKOHqMgUY2XHzRtXE=; b=OpsGOqgWVrYUmPhvSwSkpHhtLR kZYrlRRD85ZUkDQ91ikGvr4ikbep5H7p8A6wWpGu73KkZM1eXMzggyfyKAw11aBc i/0Ull9bGco8qfMHKC0kCSYa6v4pkruhR7yBGRTwFUE5RNVfpJzeTb2thMf9wbTP CLyDs1tv/Og86Ju/zoXoyIpOYWKujJ6FL9Nmdv+MnUU8nV7ybb1Mo4Utrl6jQmFx Gz3as/Q19fOZD3axgDUm+4v1G6xfCmbYcpWi7Y2MuxCHJ9uqihqzD2WJh8dBiW7Z ni7JUrFlMheW/GE0JZcZJUHUFwNNPlKjujMwIrMRKrjkKWZ/K9rZ27ZTyLDQ== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-type:content-type:date:date :feedback-id:feedback-id:from:from:in-reply-to:in-reply-to :message-id:mime-version:references:reply-to:subject:subject:to :to:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s=fm1; t= 1748762269; x=1748848669; bh=FxoU17SfXzMpgc2Nhdn1iNBp7KiKOHqMgUY 2XHzRtXE=; b=fVJZyeR9qeg/Rpcnby2byupjTFSmuh2Es+mUB7wEG5w8u67Ruhb 57vbcC6eRwAAZP4hZibefeJ+42tWDVy1Qs17HdMIu+5Bxu837g6PCY+gAjmRIC+o 6cEK/muTw8Wmkrd8JJ/mZGRVTMfSiu5XkphIzrYq7ojW0jpMruianc30ftUuUkw7 ne0dgFlLNdEny9Fxf511vowGJPJAbc4M4CyU3OhXV95hurkDB0ulp21x7CzjrINE kMilQvqkadHfvMlffG1ammdfCqNwXOc72NnfD+QIn1a8V8SQetmd7jOMvupKR9+C 8FST98taE2vTpGlBqYdkowrDMlFwsStKN/w== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeeffedrtddtgdefgeduieculddtuddrgeefvddrtd dtmdcutefuodetggdotefrodftvfcurfhrohhfihhlvgemucfhrghsthforghilhdpggft fghnshhusghstghrihgsvgdpuffrtefokffrpgfnqfghnecuuegrihhlohhuthemuceftd dtnecunecujfgurhepofggfffhvffkjghfufgtsegrtderreertdejnecuhfhrohhmpedf tfhosgcunfgrnhguvghrshdfuceorhhosgessghothhtlhgvugdrtghouggvsheqnecugg ftrfgrthhtvghrnhepleekhedtgfefhfelieelgfegiefhkedvleefjedtffelhfehheff gfduteduuddtnecuffhomhgrihhnpehphhhprdhnvghtnecuvehluhhsthgvrhfuihiivg eptdenucfrrghrrghmpehmrghilhhfrhhomheprhhosgessghothhtlhgvugdrtghouggv shdpnhgspghrtghpthhtohepuddpmhhouggvpehsmhhtphhouhhtpdhrtghpthhtohepih hnthgvrhhnrghlsheslhhishhtshdrphhhphdrnhgvth X-ME-Proxy: Feedback-ID: ifab94697:Fastmail Received: by mailuser.phl.internal (Postfix, from userid 501) id 0545A1820064; Sun, 1 Jun 2025 03:17:48 -0400 (EDT) X-Mailer: MessagingEngine.com Webmail Interface Precedence: bulk list-help: list-post: List-Id: internals.lists.php.net x-ms-reactions: disallow MIME-Version: 1.0 X-ThreadId: T018bd9ffc60205f7 Date: Sun, 01 Jun 2025 09:17:27 +0200 To: internals@lists.php.net Message-ID: <6cbfb0ca-5be3-4c00-94ba-4595cfad3738@app.fastmail.com> In-Reply-To: References: <78641D8B-AF1D-4912-920A-D75A37C32F05@rwec.co.uk> <354cb888-97c4-4f8c-a0da-359d1e63c0f9@rwec.co.uk> <10D95B6E-094B-4EAE-A18A-AF6B795CB352@rwec.co.uk> <2adbff61-5e11-4d39-ab5c-d7950a4550a6@app.fastmail.com> <79E7FA26-2F5A-470C-B1DF-12CC46A08FE5@rwec.co.uk> <1c6dcd84-9016-48e1-971f-de7749cbdce8@rwec.co.uk> <44F59416-3922-4AF4-881A-C64F2C4E9345@rwec.co.uk> <7F11844A-A98C-4843-BC94-815FBCD2B73F@garsi.de> <7840468C-F60C-4A44-AE40-16F9007EF428@rwec.co.uk> <160E9B1D-9AF6-479B-A628-A73C618D7C1B@garsi.de> Subject: Re: [PHP-DEV] Module or Class Visibility, Season 2 Content-Type: multipart/alternative; boundary=4405eec7b267483da531745cddc54dad From: rob@bottled.codes ("Rob Landers") --4405eec7b267483da531745cddc54dad Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable On Sun, Jun 1, 2025, at 07:26, Michael Morris wrote: > Ok, the conversation is getting sidetracked, but I think some progress= is being made. >=20 > I started this latest iteration last year with a thread about introduc= ing something similar to the ES module system of JavaScript to PHP. What= attracts me to this particular model is that it should already be famil= iar to the vast majority of PHP users. Prior to ES modules browsers had = no natural module import mechanic. Prior to ES modules all symbols were= attached to the window. You can see this if you serve open this index.h= tml from a server (Note that opening the file locally will result in the= js being blocked by modern browser security. ) >=20 > ```html > > > > > > > > > > ``` > The above spits 1234 into the console twice. Second example - let's p= ut a module in. >=20 > ```html > > > > > > > > > > > ``` > This outputs 1234 twice and an error is raised about b being undefined. >=20 > I bring the above up to demonstrate that is the desired behavior of wh= at I originally called a PHP module and have been bullied over and taken= to task about not understanding the meaning of "module". Rowain seems t= o be more comfortable characterizing this as containers. If everyone is = happy with that term I really don't care - I just want a way to isolate = a code block so that whatever happens in there stays in there unless I e= xplicitly export it out, and the only way I see things in that scope is = if I bring them in. >=20 > The other thing that was done with ES is that the syntax for the modul= es was tightened. JavaScripters cannot dictate what browser a user choos= es, so the bad decisions of the early days of JS never really went away = until ES came along which enforced their strict mode by default. PHP ha= s no such strict mode - it has a strict types mode but that isn't the sa= me thing. There are multiple behaviors in PHP that can't go away becaus= e of backwards compatibility problems, and one of those might indeed be = how namespaces are handled. In PHP a namespace is just a compile shortcu= t for resolving symbol names. The namespace is prefixed to the start of = every symbol within it. Unlike Java or C#, PHP has no concept of namespa= ce visibility. At the end of the day it's a shortcut and its implementat= ion happens entirely at compile time. >=20 > Previously in the discussion Alwin Garside made a long but insightful = post on namespaces and their workings that I've been thinking on and try= ing to digest for the last several days. What I've arrived at is the dis= cussions about composer and autoloaders are indeed a red herring to the = discussion. At the end of the day, PHP's include statements are a means = to separate the php process into multiple files. In his email he explore= d some of the rewriting that could be done, and myself and Rowain have a= lso explored this in the form of namespace pathing and aliasing. >=20 > We've gotten away from the original focus of containing this code and = how that would work. So once again this moron is going to take a stab at= it. >=20 > Container modules are created with require_module('file/path'). All co= de that executes as a result of this call is isolated to its container. = That includes the results of any require or include calls made by the mo= dule file itself or any file it requires. >=20 > Since the module file is cordoned off to its own container from the re= st of the application whatever namespaces it uses are irrelevant to outs= ide code. Any symbols created in the module will not be established in t= he script that made the require_module() call. Since it is coming into b= eing with a new require mechanism it could be subjected to more efficien= t parsing rules if that is desired, but that's a massive can of worms fo= r later discussion. One of those will be necessary - it will need to ret= urn something to the php code that called it. The simplest way to go ab= out this is to just require that it have a return. So... >=20 > $myModule =3D require_module('file/path'); >=20 > or perhaps >=20 > const myModule =3D require_module('file/path'); >=20 > The module probably should return a static class or class instance, bu= t it could return a closure. In JavaScript the dynamic import() stateme= nt returns a module object that is most similar to PHP's static classes,= with each export being a member or method of the module object. >=20 > Circling back to a question I know will be asked - what about autoload= ers? To which I answer, what about them? If the module wants to use an = autoloader it has to require one just as the initial php file that requi= red it had to have done at some point. The container module is for all = intents and purposes its own php process that returns some interface to = allow it to talk to the process that spawned it.=20 >=20 > Will this work? I think yes. Will it be efficient? Hell no. Can it be = optimized somehow? I don't know. >=20 This could work! I have a couple of critiques, but they aren=E2=80=99t n= egative: I think I like it. It might be worth pointing out that JavaScript "hoist= s" the imports to file-level during compilation =E2=80=94 even if you ha= ve the import statement buried deep in a function call. Or, at least it = used to. I haven=E2=80=99t kept track of the language that well in the l= ast 10 years, so I wouldn=E2=80=99t be surprised if it changed; or didn=E2= =80=99t. I don=E2=80=99t think this is something we need to worry about = too much here. It=E2=80=99s also worth pointing out that when PHP compiles a file, ever= y file has either an explicit or implicit return. https://www.php.net/ma= nual/en/function.include.php#:~:text=3DHandling%20Returns%3A,from%20incl= uded%20files. So, in other words, what is it about require_module that is different fr= om `require` or `include`? Personally, I would then change PHP from "com= pile file" mode when parsing the file to "compile module" mode. From a t= otally naive point-of-view, this would cause PHP to: 1. if we already have a module from that file; return the module instea= d of compiling it again. 2. swap out symbol tables to the module=E2=80=99s symbol table. 3. start compiling the given file. 4. concatenate all files as included/required. 5. compile the resulting huge file. 6. switch back to the calling symbol table (which may be another module= ). 7. return the module. For a v1, I wouldn=E2=80=99t allow autoloading from inside a module =E2=80= =94 or any autoloaded code automatically isn=E2=80=99t considered to be = part of the module (it would be the responsibility of the main program t= o handle autoloading). This is probably something that needs to be solve= d, but I think it would need a whole new approach to autoloading which s= hould be out of scope for the module RFC (IMHO). In other words, you can simply include/require a module to load the enti= re module into your current symbol table; or use require_module to "cont= ain" it. As for what should a module return? I like your idea of just returning a= n object or closure. =E2=80=94 Rob --4405eec7b267483da531745cddc54dad Content-Type: text/html; charset=utf-8 Content-Transfer-Encoding: quoted-printable


On Sun, Jun 1, 2025, at 07:26, Michael Morris wrote:
Ok, the conversation is getting sidetracked, but I think some progress = is being made.

I started this latest iteration = last year with a thread about introducing something similar to the ES mo= dule system of JavaScript to PHP. What attracts me to this particular mo= del is that it should already be familiar to the vast majority of PHP us= ers. Prior to ES modules browsers had no natural module import mechanic.=   Prior to ES modules all symbols were attached to the window. You = can see this if you serve open this index.html from a server (Note that = opening the file locally will result in the js being blocked by modern b= rowser security. )

```html
<!= DOCTYPE html>
<html>
  <head>
    <script>
      var = a =3D 1234
    </script>
  <= /head>
  <body>
    <scri= pt>
      console.log(a)
  &n= bsp;   console.log(window.a)
    </script>= ;
  </body>
</html>
```
The above spits 1234 into the console twice.  Second= example - let's put a module in.

```html
=
<!DOCTYPE html>
<html>
  = <head>
    <script>
  &nb= sp;   var a =3D 1234
    </script>
<= div>    <script type=3D"module">
   =   const a =3D 5678
      var b =3D 9123
    </script>
  </head>
  <body>
    <script>
=
      console.log(a)
      = console.log(window.a)
      console.log(b)
    </script>
  </body>
=
</html>
```
This outputs 1234 twice= and an error is raised about b being undefined.

I bring the above up to demonstrate that is the desired behavior of wh= at I originally called a PHP module and have been bullied over and taken= to task about not understanding the meaning of "module". Rowain seems t= o be more comfortable characterizing this as containers. If everyone is = happy with that term I really don't care - I just want a way to isolate = a code block so that whatever happens in there stays in there unless I e= xplicitly export it out, and the only way I see things in that scope is = if I bring them in.

The other thing that was do= ne with ES is that the syntax for the modules was tightened. JavaScripte= rs cannot dictate what browser a user chooses, so the bad decisions of t= he early days of JS never really went away until ES came along which enf= orced their strict mode by default.  PHP has no such strict mode - = it has a strict types mode but that isn't the same thing.  There ar= e multiple behaviors in PHP that can't go away because of backwards comp= atibility problems, and one of those might indeed be how namespaces are = handled. In PHP a namespace is just a compile shortcut for resolving sym= bol names. The namespace is prefixed to the start of every symbol within= it. Unlike Java or C#, PHP has no concept of namespace visibility. At t= he end of the day it's a shortcut and its implementation happens entirel= y at compile time.

Previously in the discussion= Alwin Garside made a long but insightful post on namespaces and their w= orkings that I've been thinking on and trying to digest for the last sev= eral days. What I've arrived at is the discussions about composer a= nd autoloaders are indeed a red herring to the discussion. At the end of= the day, PHP's include statements are a means to separate the php proce= ss into multiple files. In his email he explored some of the rewriting t= hat could be done, and myself and Rowain have also explored this in the = form of namespace pathing and aliasing.

We've g= otten away from the original focus of containing this code and how that = would work. So once again this moron is going to take a stab at it.

Container modules are created with require_module('= file/path'). All code that executes as a result of this call is isolated= to its container. That includes the results of any require or include c= alls made by the module file itself or any file it requires.
<= br>
Since the module file is cordoned off to its own container= from the rest of the application whatever namespaces it uses are irrele= vant to outside code. Any symbols created in the module will not be esta= blished in the script that made the require_module() call. Since it is c= oming into being with a new require mechanism it could be subjected to m= ore efficient parsing rules if that is desired, but that's a massiv= e can of worms for later discussion. One of those will be necessary= - it will need to return something to the php code that called it. = ; The simplest way to go about this is to just require that it have a re= turn. So...

$myModule =3D require_module('file/= path');

or perhaps

con= st myModule =3D require_module('file/path');

Th= e module probably should return a static class or class instance, but it= could return a closure.  In JavaScript the dynamic import() statem= ent returns a module object that is most similar to PHP's static cl= asses, with each export being a member or method of the module object.

Circling back to a question I know will be asked= - what about autoloaders?  To which I answer, what about them? If = the module wants to use an autoloader it has to require one just as the = initial php file that required it had to have done at some point.  = The container module is for all intents and purposes its own php process= that returns some interface to allow it to talk to the process tha= t spawned it. 

Will this work? I thin= k yes. Will it be efficient? Hell no. Can it be optimized somehow? I don= 't know.


This= could work! I have a couple of critiques, but they aren=E2=80=99t negat= ive:

I think I like it. It might be worth point= ing out that JavaScript "hoists" the imports to file-level during compil= ation =E2=80=94 even if you have the import statement buried deep in a f= unction call. Or, at least it used to. I haven=E2=80=99t kept track of t= he language that well in the last 10 years, so I wouldn=E2=80=99t be sur= prised if it changed; or didn=E2=80=99t. I don=E2=80=99t think this is s= omething we need to worry about too much here.

= It=E2=80=99s also worth pointing out that when PHP compiles a file, ever= y file has either an explicit or implicit return. https://www.php.net/manual/en/function.inc= lude.php#:~:text=3DHandling%20Returns%3A,from%20included%20files.

So, in other words, what is it about require_modu= le that is different from `require` or `include`? Personally, I would th= en change PHP from "compile file" mode when parsing the file to "compile= module" mode. From a totally naive point-of-view, this would cause PHP = to:
  1. if we already have a module from that file; return = the module instead of compiling it again.
  2. swap out symbol tables= to the module=E2=80=99s symbol table.
  3. start compiling the given= file.
  4. concatenate all files as included/required.
  5. compi= le the resulting huge file.
  6. switch back to the calling symbol ta= ble (which may be another module).
  7. return the module.
<= div>For a v1, I wouldn=E2=80=99t allow autoloading from inside a module = =E2=80=94 or any autoloaded code automatically isn=E2=80=99t considered = to be part of the module (it would be the responsibility of the main pro= gram to handle autoloading). This is probably something that needs to be= solved, but I think it would need a whole new approach to autoloading w= hich should be out of scope for the module RFC (IMHO).

In other words, you can simply include/require a module to load = the entire module into your current symbol table; or use require_module = to "contain" it.

As for what should a module re= turn? I like your idea of just returning an object or closure.
=

=E2=80=94 Rob
--4405eec7b267483da531745cddc54dad--