rfc:source_files_without_opening_tag

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
rfc:source_files_without_opening_tag [2012/04/10 12:29] – [Changelog] boutellrfc:source_files_without_opening_tag [2017/09/22 13:28] (current) – external edit 127.0.0.1
Line 1: Line 1:
 +====== ABANDONED ======
 +
 +I have abandoned this proposal. I have come to feel it changes the spirit of PHP too much, offering too little gain for the degree of unhappiness it inspires and the potential for confusion it creates. I am leaving it here for historical purposes. -Tom Boutell
 +
 ====== Request for Comments: Source Files Without Opening Tag ====== ====== Request for Comments: Source Files Without Opening Tag ======
-  * Version: 1.0 +  * Version: 1.1.1 
-  * Date: 2012-04-08+  * Date: 2012-04-16
   * Author: Thomas Boutell <tom@punkave.com>   * Author: Thomas Boutell <tom@punkave.com>
   * Status: Under Discussion   * Status: Under Discussion
Line 11: Line 15:
 ===== Introduction ===== ===== Introduction =====
  
-The purpose of this RFC is to provide a way to support source files that do not begin with ''<?php'' while maintaining backwards compatibility. +The purpose of this RFC is to provide a way to support source files that do not begin with ''<?php'' while maintaining full backwards compatibility with files that do.
  
 ==== Why is this desirable? ==== ==== Why is this desirable? ====
  
 In modern framework development and larger projects in general, it is often considered good practice to implement PHP classes in files which contain only In modern framework development and larger projects in general, it is often considered good practice to implement PHP classes in files which contain only
-PHP code and typically contain no "raw HTML" (no code which is not wrapped by ''<?php'' and ''?>'')at least not outside the context of function or method. In such files, typing ''<?php'' at the top is:+PHP code. If methods of such classes do have a desire for HTML templatingthey accomplish it by requiring separate template file. In such "pure code" files, typing ''<?php'' at the top is:
  
 1. Error-prone in a subtle and hard-to-debug way: if any whitespace is introduced before ''<?php'', the code still runs, but your XHTML doctype fails to be recognized, your ''header()'' calls fail, etc. Since you may not use these features in every situation the bug is often not spotted until an inopportune time. 1. Error-prone in a subtle and hard-to-debug way: if any whitespace is introduced before ''<?php'', the code still runs, but your XHTML doctype fails to be recognized, your ''header()'' calls fail, etc. Since you may not use these features in every situation the bug is often not spotted until an inopportune time.
Line 22: Line 26:
 2. Tedious. There is a small but real frustration involved in this redundancy. Small but real frustrations can contribute to long-term disenchantment with a programming language. 2. Tedious. There is a small but real frustration involved in this redundancy. Small but real frustrations can contribute to long-term disenchantment with a programming language.
  
-However these same projects and frameworks may advocate the use of "raw HTML" in PHP files intended as templates for rendering pages, forms and the like. This is a longstanding feature of PHP (indeed the original feature of PHP). Support for it should be maintained, and may perhaps be improved in future to address PHP's current limitations as a templating language. This proposal aims not to close any doors in this regard.+However these same projects and frameworks may advocate the use of "raw HTML" in PHP files intended as templates for rendering pages, forms and the like. This is a longstanding feature of PHP (indeed the original feature of PHP). Support for it should be maintained, and may perhaps be improved in future to address PHP's current limitations as a templating language. The two modes should not be mutually exclusive as this makes it impossible for code to interoperate. This proposal aims not to close any doors in this regard.
  
 ==== Related RFC ==== ==== Related RFC ====
Line 30: Line 34:
 ===== Proposal ===== ===== Proposal =====
  
-=== Part 1: Introduce require_path ===+=== Part 1: Enhance the include, include_once, require and require_once keywords ===
  
-The following new keyword will be introduced:+These keywords will be enhanced with a second, optional parameter introduced by the "AS" keyword.
  
-''require_path''+The first parameter (the URL/filename to the file to be included) does not change.
  
-This keyword has two parameters of which the second is optional. The first parameter is the path (filename or URLto be required, and behaves exactly as the sole parameter of the require keyword behaves. The second parameter is an associative array+The second parameter is a combination of integer flags, combined in the usual way with the OR operator (''|'').
  
-If this second parameter is absent, ''require_path'' behaves exactly like ''require''+If this second parameter is absent, the four keywords behave exactly as they do now.
  
-If the second parameter is present, the following keys may optionally be present in the array, with the following effects:+When the second parameter is present, it may be a bitwise OR of zero or more of the following constants which add to (but never subtract from) the existing behavior of each keyword:
  
-If ''once'' is present and true, the specified path is loaded no more than onceexactly like ''require_once''.+If ''INCLUDE_PURE_CODE'' is present, the parser begins reading the included file as if the ''<?php'' tag had already been encounteredand any occurrence of the ''?>'' and ''<?php'' tokens later in that file is a fatal error. This rule does NOT extend to other files included and/or required later. Files required in INCLUDE_PURE_CODE mode can still require template files that do contain ''<?php'' and ''?>''.
  
-If ''warn'' is present and true, a loading or compilation error results in ''E_WARNING'' (per the current behavior of the include keyword). If warn is absent or false, a loading or compilation error results in ''E_COMPILE_ERROR'' (per the current behavior of the require keyword).+If ''INCLUDE_ONCE'' is present or the ''include_once'' or ''require_once'' keyword was used, the file is not included if it has already been included once (like the normal behavior of ''include_once'' and ''require_once''). Note that the use of either of the ''_once'' keywords implicitly turns on this bit regardless.
  
-If code is present and true, the parser begins reading the file as if a ''<?php'' open tag had already been encounteredIf code is absent or falsethe parser reads the file beginning in "HTML mode," exactly as the require keyword does today.+If ''INCLUDE_ERROR_ON_FAILURE'' is present, or the ''require'' or ''require_once'' keyword was used, an ''E_COMPILE_ERROR'' fatal error is generated if the file cannot be included (exactly like failure of the ''require'' keyword)Otherwise an ''E_WARNING'' is generated, as is normal for the ''include'' keyword with no second parameter. Note that the use of either of the ''require_'' keywords implicitly turns on this bit regardless.
  
 Examples: Examples:
  
 +  // Absolutely no change to existing behavior
 +  require 'filename.php';
 +  
 +  // Load filename.phpp. This file must consist purely of source code, no <?php or ?> tokens needed or permitted
 +  require 'filename.phpp' AS INCLUDE_PURE_CODE;
 +   
 +  // Behaves just like include_once
 +  include 'filename.php' AS INCLUDE_ONCE;
 +   
   // Behaves just like require   // Behaves just like require
-  require_path 'filename.php'; +  include 'template.php' AS INCLUDE_ERROR_ON_FAILURE
- +    
-  // Behaves just like include_once +  // Combine them all: includes only once, with a fatal error on failure, parsing in "code mode" 
-  require_path 'filename.php', array('warn' => true, 'once=> true)+  include 'filename.phppAS INCLUDE_PURE_CODE | INCLUDE_ONCE | INCLUDE_ERROR_ON_FAILURE
- +    
-  // Loads a file starting out in "PHP mode" so the opening <?php is not required +  // Exactly the same as previous example 
-  require_path 'filename.php', array('code' => true)+  require_once 'filename.phppAS INCLUDE_PURE_CODE
 +  
 === Part 2: Filename Convention === === Part 2: Filename Convention ===
  
-Although this proposal gives implementers flexibility in how they decide when to apply the `code` flag, it is still desirable in most cases to have a commonly recognized convention to distinguish files that should be read starting in "PHP mode" from legacy and template files that should be read starting in "HTML mode." The following convention is proposed for environments in which file extensions are a relevant and useful concept:+Although this proposal gives implementers flexibility in when and where they use the INCLUDE_PURE_CODE bit, it is still desirable in most cases to have a commonly recognized convention to distinguish files that should be read starting in "PHP mode" from legacy and template files that should be read starting in "HTML mode." The following convention is proposed for environments in which file extensions are a relevant and useful concept:
  
   * Files that should be read starting in HTML mode should have a ''.php'' extension, for backwards compatibility.   * Files that should be read starting in HTML mode should have a ''.php'' extension, for backwards compatibility.
-  * Files that should be read starting in PHP mode should have a ''.phpc'' extension (short for "PHP code")+  * Files that should be read starting in PHP mode should have a ''.phpp'' extension (short for "Pure PHP").
- +
-However enforcement of this convention is NOT proposed. The ''require_path'' keyword does NOT attempt to make inferences from the file extension of the path, if any.+
  
 +However enforcement of this convention is NOT proposed. The choice to apply ''INCLUDE_PURE_CODE'' is made entirely by the programmer (typically the author of a class file autoloader).
  
 ===== Anticipated And Previously Raised Questions ===== ===== Anticipated And Previously Raised Questions =====
Line 77: Line 89:
 No. Code that never uses the new keyword will not be affected in any way. The proposal allows autoloaders to load files the old-fashioned way and to recognize when to do so by a simple common convention or by other local conventions as appropriate. No. Code that never uses the new keyword will not be affected in any way. The proposal allows autoloaders to load files the old-fashioned way and to recognize when to do so by a simple common convention or by other local conventions as appropriate.
  
-**"Isn't the ''require_path'' keyword even more work than typing ''<?php''?"**+**"Isn't the ''INCLUDE_PURE_CODE'' flag even more work than typing ''<?php''?"**
  
-Typically projects that will benefit from the ''code'' option to ''require_path'' also have autoloaders to load classes implicitly when they are first used. So ''require_path'' would be typed once in the autoloader, not many times everywhere.+Typically projects that will benefit from this flag also have autoloaders to load classes implicitly when they are first used. So ''INCLUDE_PURE_CODE'' would be typed once in the autoloader, not many times everywhere.
  
 **"Won't this slow down the autoloader?"** **"Won't this slow down the autoloader?"**
  
-Not really. Even in a worst-case scenario where ''stat()'' calls are slow and the autoloader performs no caching even in a production environment, the autoloader will often be able to assume that only ''.phpc'' files are expected because that is the convention of the library or framework from which they came, so it won't be necessary to ''stat()'' first for ''.phpc'' and then check for ''.php'' as well. It is also possible to prewarm autoloader caches as part of deployment. +Not really. Even in a worst-case scenario where ''stat()'' calls are slow and the autoloader performs no caching even in a production environment, the autoloader will often be able to assume that only ''.phpp'' files are expected because that is the convention of the library or framework from which they came, so it won't be necessary to ''stat()'' first for ''.phpp'' and then check for ''.php'' as well. It is also possible to prewarm autoloader caches as part of deployment. 
  
 **"Won't this break if you try to use the code with an older version of PHP?"** **"Won't this break if you try to use the code with an older version of PHP?"**
  
-Of course. A choice to use this feature implies a choice to support only the supporting version of PHP or newer. But it'll break cleanly with a clear error message, just like code that tries to use traits or other newer features. That is one of the advantages of using new keywords rather than applying special behavior to file extensions automatically or similar.+Of course. A choice to use this feature implies a choice to support only the supporting version of PHP or newer. But it'll break cleanly with a clear error message, just like code that tries to use traits or other newer features.
  
-**"Why doesn'the proposal forbid the use of ''?>'' to get back to HTML mode in a ''.phpc'' file?"**+**"Why does the proposal forbid the use of ''?>'' to get back to HTML mode in a ''.phpp'' file?"**
  
-Two reasons:+The first version of the proposal did permit this as a compromise. However it did not please anyone. Those who want to write "pure PHP" class files are not interested in switching from code to markup in the middle of a method and are still able to ''include'' regular template PHP files as needed, following good MVC separation practices.
  
-1. While it is tempting to be purist about this, those who are creating code generators and the like may sometimes find it useful to leverage HTML mode in a class file (though they also have the option of requiring a regular .php file). It is not the place of this proposal to forbid them from doing what they want if it doesn't interfere with the ability of others to write maintainable, bug-free code more conveniently. Some may find it unsettling to use ''?>'' where you have not explicitly used ''<?php'', but they don't have to use this capability.+**"Why not introduce new keyword rather than enhancing four keywords?"**
  
-2It is suspected that the implementation of the proposal will be simpler and therefore easier to debug and maintain if it is limited simply to setting the initial state of the parser.+A new keyword was proposed and did not go over wellEnhancing the existing keywords, allowing their existing behavior to automatically switch on some of the flag bits, turns out to be both more elegant and more familiar.
  
-**"Why introduce a keyword that takes an array parameter instead of new keywords?"**+**"Why three flags instead of one? Aren't the other two redundant?"**
  
-Using new keywords would require doubling the number of variations on ''require'' from four to eight. Other proposals being aired to alter and enhance PHP's functionality as a template language would increase this number even more. An associative array is a sustainable solution which will potentially allow for other enhancements if approved. And since this keyword will primarily be used in autoloaders it does not represent lot of tedious typing in many places (although the new short array syntax already included in PHP 5.4 would help if you did choose to use this keyword frequently).+While the ''INCLUDE_ONCE'' and ''INCLUDE_FATAL_ERROR_ON_FAILURE'' flags are technically redundant, if a developer chooses to start with the ''include'' keyword they can decide which of the flags to apply at runtime, which was not possible before without series of if/else clauses.
  
 +**"Why bitwise flags instead of an associative array of options?"**
  
-===== Changelog =====+Bitwise flags are faster and also provide built-in error checking: use of a constant not defined by a particular version of PHP will generate a notice. Require statements are something PHP executes quite often, so generating unnecessary arrays and testing array values is an unnecessary performance hit.
  
-  2011-04-09 Yasuo Ohgaki: Added related RFC. +**"Why is the AS keyword necessary? Why not a comma?"** 
-  2011-04-10 Thomas Boutell: removed misleading word "Optionfrom parts 1 and 2which are not meant to be mutually exclusive (see the original text).+ 
 +Since these keywords are language constructsnot functions, and their parameters are not enclosed in parentheses, the meaning is ambiguous with a comma. Right now ''foo(include 'baz', INCLUDE_ONCE)'' would pass two separate values to the ''foo'' function. Changing this in the grammar would be problematic. The use of the AS keyword removes the ambiguity. 
 + 
 +===== Changelog =====
  
 +  * 2012-05-06 Thomas Boutell: formally abandoned by original proponent.
 +  * 2012-04-09 Yasuo Ohgaki: Added related RFC.
 +  * 2012-04-10 Thomas Boutell: removed misleading word "Option" from parts 1 and 2, which are not meant to be mutually exclusive (see the original text).
 +  * 2012-04-10 Thomas Boutell: version 1.1. Replaced ''require_path'' with enhancements to the standard ''include''/''require'' family of keywords. Replaced an array of options with a bitwise OR of options. Forbade the use of ''?>'' entirely in pure PHP files (without restricting it at all in other PHP files).
 +  * 2012-04-16 Thomas Boutell: added Nikita Popov's "AS" keyword as a workaround for the fact that a comma can't be introduced between the two parameters without creating an ambiguity in the grammar.
  
rfc/source_files_without_opening_tag.1334060959.txt.gz · Last modified: 2017/09/22 13:28 (external edit)