THRIFT-4474: Use PSR-4 autoloader by default

Client: php

This closes #1479
diff --git a/compiler/cpp/src/thrift/generate/t_php_generator.cc b/compiler/cpp/src/thrift/generate/t_php_generator.cc
index ea28011..6ab6bf8 100644
--- a/compiler/cpp/src/thrift/generate/t_php_generator.cc
+++ b/compiler/cpp/src/thrift/generate/t_php_generator.cc
@@ -62,7 +62,7 @@
     validate_ = false;
     json_serializable_ = false;
     nsglobal_ = ""; // by default global namespace is empty
-    psr4_ = false;
+    classmap_ = false;
     for (iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) {
       if (iter->first.compare("inlined") == 0) {
         binary_inline_ = true;
@@ -78,8 +78,14 @@
         json_serializable_ = true;
       } else if (iter->first.compare("nsglobal") == 0) {
         nsglobal_ = iter->second;
+      } else if (iter->first.compare("classmap") == 0) {
+        classmap_ = true;
       } else if (iter->first.compare("psr4") == 0) {
-        psr4_ = true;
+        if(classmap_){
+          throw "psr4 and classmap are mutually exclusive.";
+        } else {
+          pwarning(0, "psr4 is default option! needn't add psr4 option!\n");
+        }
       } else {
         throw "unknown option php:" + iter->first;
       }
@@ -376,9 +382,9 @@
   bool oop_;
 
   /**
-   * Whether to hold each class in separate file to allow PSR4-autoloading
+   * Whether to generate old-style PHP file to use classmap autoloading
    */
-  bool psr4_;
+  bool classmap_;
 
   /**
    * Whether to generate validator code
@@ -419,8 +425,8 @@
     MKDIR(package_dir_.c_str());
   }
 
-  // Prepare output file for all the types in non-psr4 mode
-  if (!psr4_) {
+  // Prepare output file for all the types in classmap mode
+  if (classmap_) {
     // Make output file
     string f_types_name = package_dir_ + "Types.php";
     f_types_.open(f_types_name.c_str());
@@ -453,7 +459,7 @@
  * Close up (or down) some filez.
  */
 void t_php_generator::close_generator() {
-  if (!psr4_) {
+  if (classmap_) {
     // Close types file
     f_types_.close();
   }
@@ -504,7 +510,7 @@
  */
 void t_php_generator::generate_enum(t_enum* tenum) {
   std::ofstream& f_enum = f_types_;
-  if (psr4_) {
+  if (!classmap_) {
     string f_enum_name = package_dir_ + tenum->get_name() + ".php";
     f_enum.open(f_enum_name.c_str());
     generate_program_header(f_enum);
@@ -541,7 +547,7 @@
   indent_down();
 
   f_enum << "}" << endl << endl;
-  if (psr4_) {
+  if (!classmap_) {
     f_enum.close();
   }
 }
@@ -558,7 +564,7 @@
   if (consts.size() > 0) {
 
     std::ofstream& f_consts = f_types_;
-    if (psr4_) {
+    if (!classmap_) {
       string f_consts_name = package_dir_ + "Constant.php";
       f_consts.open(f_consts_name.c_str());
       generate_program_header(f_consts);
@@ -596,7 +602,7 @@
 
     indent_down();
     f_consts << "}" << endl;
-    if (psr4_) {
+    if (!classmap_) {
       f_consts.close();
     }
   }
@@ -725,13 +731,13 @@
  */
 void t_php_generator::generate_php_struct(t_struct* tstruct, bool is_exception) {
   std::ofstream& f_struct = f_types_;
-  if (psr4_) {
+  if (!classmap_) {
     string f_struct_name = package_dir_ + tstruct->get_name() + ".php";
     f_struct.open(f_struct_name.c_str());
     generate_program_header(f_struct);
   }
   generate_php_struct_definition(f_struct, tstruct, is_exception);
-  if (psr4_) {
+  if (!classmap_) {
     f_struct.close();
   }
 }
@@ -1244,7 +1250,7 @@
  * @param tservice The service definition
  */
 void t_php_generator::generate_service(t_service* tservice) {
-  if(!psr4_) {
+  if(classmap_) {
     string f_service_name = package_dir_ + service_name_ + ".php";
     f_service_.open(f_service_name.c_str());
     generate_service_header(tservice, f_service_);
@@ -1261,7 +1267,7 @@
     generate_service_processor(tservice);
   }
 
-  if(!psr4_) {
+  if(classmap_) {
     // Close service file
     f_service_ << endl;
     f_service_.close();
@@ -1275,7 +1281,7 @@
  */
 void t_php_generator::generate_service_processor(t_service* tservice) {
   std::ofstream& f_service_processor = f_service_;
-  if (psr4_) {
+  if (!classmap_) {
     string f_service_processor_name = package_dir_ + service_name_ + "Processor.php";
     f_service_processor.open(f_service_processor_name.c_str());
     generate_service_header(tservice, f_service_processor);
@@ -1370,7 +1376,7 @@
   indent_down();
   f_service_processor << "}" << endl;
 
-  if (psr4_) {
+  if (!classmap_) {
     f_service_processor.close();
   }
 }
@@ -1539,7 +1545,7 @@
   vector<t_function*>::iterator f_iter;
 
   std::ofstream& f_struct_definition = f_service_;
-  if (!psr4_) {
+  if (classmap_) {
     f_struct_definition << "// HELPER FUNCTIONS AND STRUCTURES" << endl << endl;
   }
 
@@ -1548,14 +1554,14 @@
     string name = ts->get_name();
     ts->set_name(service_name_ + "_" + name);
 
-    if (psr4_) {
+    if (!classmap_) {
       string f_struct_definition_name = package_dir_ + service_name_ + "_" + name + ".php";
       f_struct_definition.open(f_struct_definition_name.c_str());
       generate_service_header(tservice, f_struct_definition);
     }
 
     generate_php_struct_definition(f_struct_definition, ts);
-    if (psr4_) {
+    if (!classmap_) {
       f_struct_definition.close();
     }
 
@@ -1585,13 +1591,13 @@
     }
 
     std::ofstream& f_struct_helper = f_service_;
-    if (psr4_) {
+    if (!classmap_) {
       string f_struct_helper_name = package_dir_ + result.get_name() + ".php";
       f_struct_helper.open(f_struct_helper_name.c_str());
       generate_service_header(tservice, f_struct_helper);
     }
     generate_php_struct_definition(f_struct_helper, &result, false, true);
-    if (psr4_) {
+    if (!classmap_) {
       f_struct_helper.close();
     }
   }
@@ -1604,7 +1610,7 @@
  */
 void t_php_generator::generate_service_interface(t_service* tservice) {
   std::ofstream& f_service_interface = f_service_;
-  if (psr4_) {
+  if (!classmap_) {
     string f_service_interface_name = package_dir_ + service_name_ + "If.php";
     f_service_interface.open(f_service_interface_name.c_str());
     generate_service_header(tservice, f_service_interface);
@@ -1633,7 +1639,7 @@
   f_service_interface << "}" << endl;
 
   // Close service interface file
-  if (psr4_) {
+  if (!classmap_) {
     f_service_interface.close();
   }
 }
@@ -1643,7 +1649,7 @@
  */
 void t_php_generator::generate_service_rest(t_service* tservice) {
   std::ofstream& f_service_rest = f_service_;
-  if (psr4_) {
+  if (!classmap_) {
     string f_service_rest_name = package_dir_ + service_name_ + "Rest.php";
     f_service_rest.open(f_service_rest_name.c_str());
     generate_service_header(tservice, f_service_rest);
@@ -1712,7 +1718,7 @@
 
   // Close service rest file
   f_service_rest << endl;
-  if (psr4_) {
+  if (!classmap_) {
     f_service_rest.close();
   }
 }
@@ -1724,7 +1730,7 @@
  */
 void t_php_generator::generate_service_client(t_service* tservice) {
   std::ofstream& f_service_client = f_service_;
-  if (psr4_) {
+  if (!classmap_) {
     string f_service_client_name = package_dir_ + service_name_ + "Client.php";
     f_service_client.open(f_service_client_name.c_str());
     generate_service_header(tservice, f_service_client);
@@ -1979,7 +1985,7 @@
   f_service_client << "}" << endl;
 
   // Close service client file
-  if (psr4_) {
+  if (!classmap_) {
     f_service_client.close();
   }
 }
@@ -2772,7 +2778,7 @@
     "    inlined:         Generate PHP inlined files\n"
     "    server:          Generate PHP server stubs\n"
     "    oop:             Generate PHP with object oriented subclasses\n"
-    "    psr4:            Generate each PHP class in separate file (allows PSR4 autoloading)\n"
+    "    classmap:        Generate old-style PHP files (use classmap autoloading)\n"
     "    rest:            Generate PHP REST processors\n"
     "    nsglobal=NAME:   Set global namespace\n"
     "    validate:        Generate PHP validator methods\n"
diff --git a/lib/php/README.md b/lib/php/README.md
index c24ee2c..7170104 100644
--- a/lib/php/README.md
+++ b/lib/php/README.md
@@ -1,7 +1,6 @@
 Thrift PHP Software Library
 
-License
-=======
+# License
 
 Licensed to the Apache Software Foundation (ASF) under one
 or more contributor license agreements. See the NOTICE file
@@ -20,8 +19,7 @@
 specific language governing permissions and limitations
 under the License.
 
-Using Thrift with PHP
-=====================
+# Using Thrift with PHP
 
 Thrift requires PHP 5. Thrift makes as few assumptions about your PHP
 environment as possible while trying to make some more advanced PHP
@@ -29,25 +27,34 @@
 
 To use Thrift in your PHP codebase, take the following steps:
 
-#1) Copy all of thrift/lib/php/lib into your PHP codebase
-#2) Configure Symfony Autoloader (or whatever you usually use)
+1. Copy all of thrift/lib/php/lib into your PHP codebase
+2. Configure Symfony Autoloader (or whatever you usually use)
 
 After that, you have to manually include the Thrift package
 created by the compiler:
 
+```
 require_once 'packages/Service/Service.php';
 require_once 'packages/Service/Types.php';
+```
 
-Dependencies
-============
+# Dependencies
 
 PHP_INT_SIZE
 
-  This built-in signals whether your architecture is 32 or 64 bit and is
-  used by the TBinaryProtocol to properly use pack() and unpack() to
-  serialize data.
+    This built-in signals whether your architecture is 32 or 64 bit and is
+    used by the TBinaryProtocol to properly use pack() and unpack() to
+    serialize data.
 
 apc_fetch(), apc_store()
 
-  APC cache is used by the TSocketPool class. If you do not have APC installed,
-  Thrift will fill in null stub function definitions.
+    APC cache is used by the TSocketPool class. If you do not have APC installed,
+    Thrift will fill in null stub function definitions.
+
+# Breaking Changes
+
+## 0.12.0
+
+1. [PSR-4](https://www.php-fig.org/psr/psr-4/) loader is now the default. If you want to use class maps instead, use `-gen php:classmap`.
+
+2. If using PSR-4, use `$thriftClassLoader->registerNamespace('namespace', '<path>')` instead of `$thriftClassLoader->registerDefinition('namespace', '<path>')`.
diff --git a/lib/php/test/JsonSerialize/JsonSerializeTest.php b/lib/php/test/JsonSerialize/JsonSerializeTest.php
index 8c64595..c668652 100644
--- a/lib/php/test/JsonSerialize/JsonSerializeTest.php
+++ b/lib/php/test/JsonSerialize/JsonSerializeTest.php
@@ -22,9 +22,8 @@
 
 use PHPUnit\Framework\TestCase;
 use stdClass;
-use Thrift\ClassLoader\ThriftClassLoader;
 
-require_once __DIR__ . '/../../../../vendor/autoload.php';
+require __DIR__ . '/../../../../vendor/autoload.php';
 
 /**
  * @runTestsInSeparateProcesses
@@ -36,9 +35,9 @@
         if (version_compare(phpversion(), '5.4', '<')) {
             $this->markTestSkipped('Requires PHP 5.4 or newer!');
         }
-        $loader = new ThriftClassLoader();
-        $loader->registerDefinition('ThriftTest', __DIR__ . '/../packages/phpjs');
-        $loader->register();
+        /** @var \Composer\Autoload\ClassLoader $loader */
+        $loader = require __DIR__ . '/../../../../vendor/autoload.php';
+        $loader->addPsr4('', __DIR__ . '/../packages/phpjs');
     }
 
     public function testEmptyStruct()
diff --git a/lib/php/test/Makefile.am b/lib/php/test/Makefile.am
index 5c86e35..4824688 100755
--- a/lib/php/test/Makefile.am
+++ b/lib/php/test/Makefile.am
@@ -20,8 +20,8 @@
 PHPUNIT=php $(top_srcdir)/vendor/bin/phpunit
 
 stubs: ../../../test/ThriftTest.thrift  TestValidators.thrift
-	mkdir -p ./packages
-	$(THRIFT) --gen php -r --out ./packages ../../../test/ThriftTest.thrift
+	mkdir -p ./packages/php
+	$(THRIFT) --gen php -r --out ./packages/php ../../../test/ThriftTest.thrift
 	mkdir -p ./packages/phpv
 	mkdir -p ./packages/phpvo
 	mkdir -p ./packages/phpjs
diff --git a/lib/php/test/Protocol/BinarySerializerTest.php b/lib/php/test/Protocol/BinarySerializerTest.php
index 7e87280..71b0bb5 100644
--- a/lib/php/test/Protocol/BinarySerializerTest.php
+++ b/lib/php/test/Protocol/BinarySerializerTest.php
@@ -24,10 +24,9 @@
 namespace Test\Thrift\Protocol;
 
 use PHPUnit\Framework\TestCase;
-use Thrift\ClassLoader\ThriftClassLoader;
 use Thrift\Serializer\TBinarySerializer;
 
-require_once __DIR__ . '/../../../../vendor/autoload.php';
+require __DIR__ . '/../../../../vendor/autoload.php';
 
 /***
  * This test suite depends on running the compiler against the
@@ -42,9 +41,9 @@
 {
     public function setUp()
     {
-        $loader = new ThriftClassLoader();
-        $loader->registerDefinition('ThriftTest', __DIR__ . '/../packages');
-        $loader->register();
+        /** @var \Composer\Autoload\ClassLoader $loader */
+        $loader = require __DIR__ . '/../../../../vendor/autoload.php';
+        $loader->addPsr4('', __DIR__ . '/../packages/php');
     }
 
     /**
diff --git a/lib/php/test/Protocol/TJSONProtocolTest.php b/lib/php/test/Protocol/TJSONProtocolTest.php
index bab4389..bf0ecce 100644
--- a/lib/php/test/Protocol/TJSONProtocolTest.php
+++ b/lib/php/test/Protocol/TJSONProtocolTest.php
@@ -25,11 +25,10 @@
 
 use PHPUnit\Framework\TestCase;
 use Test\Thrift\Fixtures;
-use Thrift\ClassLoader\ThriftClassLoader;
 use Thrift\Protocol\TJSONProtocol;
 use Thrift\Transport\TMemoryBuffer;
 
-require_once __DIR__ . '/../../../../vendor/autoload.php';
+require __DIR__ . '/../../../../vendor/autoload.php';
 
 /***
  * This test suite depends on running the compiler against the
@@ -47,9 +46,9 @@
 
     public static function setUpBeforeClass()
     {
-        $loader = new ThriftClassLoader();
-        $loader->registerDefinition('ThriftTest', __DIR__ . '/../packages');
-        $loader->register();
+        /** @var \Composer\Autoload\ClassLoader $loader */
+        $loader = require __DIR__ . '/../../../../vendor/autoload.php';
+        $loader->addPsr4('', __DIR__ . '/../packages/php');
 
         Fixtures::populateTestArgs();
         TJSONProtocolFixtures::populateTestArgsJSON();
diff --git a/lib/php/test/Protocol/TSimpleJSONProtocolTest.php b/lib/php/test/Protocol/TSimpleJSONProtocolTest.php
index ec64321..e4a1373 100644
--- a/lib/php/test/Protocol/TSimpleJSONProtocolTest.php
+++ b/lib/php/test/Protocol/TSimpleJSONProtocolTest.php
@@ -25,11 +25,10 @@
 
 use PHPUnit\Framework\TestCase;
 use Test\Thrift\Fixtures;
-use Thrift\ClassLoader\ThriftClassLoader;
 use Thrift\Protocol\TSimpleJSONProtocol;
 use Thrift\Transport\TMemoryBuffer;
 
-require_once __DIR__ . '/../../../../vendor/autoload.php';
+require __DIR__ . '/../../../../vendor/autoload.php';
 
 /***
  * This test suite depends on running the compiler against the
@@ -47,9 +46,10 @@
 
     public static function setUpBeforeClass()
     {
-        $loader = new ThriftClassLoader();
-        $loader->registerDefinition('ThriftTest', __DIR__ . '/../packages');
-        $loader->register();
+
+        /** @var \Composer\Autoload\ClassLoader $loader */
+        $loader = require __DIR__ . '/../../../../vendor/autoload.php';
+        $loader->addPsr4('', __DIR__ . '/../packages/php');
 
         Fixtures::populateTestArgs();
         TSimpleJSONProtocolFixtures::populateTestArgsSimpleJSON();
diff --git a/lib/php/test/Validator/ValidatorTest.php b/lib/php/test/Validator/ValidatorTest.php
index ace3075..fa6c7a9 100644
--- a/lib/php/test/Validator/ValidatorTest.php
+++ b/lib/php/test/Validator/ValidatorTest.php
@@ -20,7 +20,7 @@
 
 namespace Test\Thrift;
 
-require_once __DIR__ . '/../../../../vendor/autoload.php';
+require __DIR__ . '/../../../../vendor/autoload.php';
 
 use Thrift\ClassLoader\ThriftClassLoader;
 
@@ -34,9 +34,8 @@
 {
     public function setUp()
     {
-        $loader = new ThriftClassLoader();
-        $loader->registerDefinition('ThriftTest', __DIR__ . '/../packages/phpv');
-        $loader->registerDefinition('TestValidators', __DIR__ . '/../packages/phpv');
-        $loader->register();
+        /** @var \Composer\Autoload\ClassLoader $loader */
+        $loader = require __DIR__ . '/../../../../vendor/autoload.php';
+        $loader->addPsr4('', __DIR__ . '/../packages/phpv');
     }
 }
diff --git a/lib/php/test/Validator/ValidatorTestOop.php b/lib/php/test/Validator/ValidatorTestOop.php
index 5a8e3bf..93bca4d 100644
--- a/lib/php/test/Validator/ValidatorTestOop.php
+++ b/lib/php/test/Validator/ValidatorTestOop.php
@@ -34,9 +34,8 @@
 {
     public function setUp()
     {
-        $loader = new ThriftClassLoader();
-        $loader->registerDefinition('ThriftTest', __DIR__ . '/../packages/phpvo');
-        $loader->registerDefinition('TestValidators', __DIR__ . '/../packages/phpvo');
-        $loader->register();
+        /** @var \Composer\Autoload\ClassLoader $loader */
+        $loader = require __DIR__ . '/../../../../vendor/autoload.php';
+        $loader->addPsr4('', __DIR__ . '/../packages/phpvo');
     }
 }
diff --git a/test/php/Makefile.am b/test/php/Makefile.am
index 28357f6..72f7fc5 100755
--- a/test/php/Makefile.am
+++ b/test/php/Makefile.am
@@ -20,8 +20,8 @@
 stubs: ../ThriftTest.thrift
 	$(THRIFT) --gen php ../ThriftTest.thrift
 	$(THRIFT) --gen php:inlined ../ThriftTest.thrift
-	$(MKDIR_P) gen-php-psr4
-	$(THRIFT) -out gen-php-psr4 --gen php:psr4 ../ThriftTest.thrift
+	$(MKDIR_P) gen-php-classmap
+	$(THRIFT) -out gen-php-classmap --gen php ../ThriftTest.thrift
 
 php_ext_dir:
 	mkdir -p php_ext_dir
@@ -33,7 +33,7 @@
 check: stubs php_ext_dir
 
 clean-local:
-	$(RM) -r gen-php gen-phpi gen-php-psr4 php_ext_dir
+	$(RM) -r gen-php gen-phpi gen-php-classmap php_ext_dir
 
 client: stubs php_ext_dir
 	php TestClient.php
diff --git a/test/php/TestPsr4.php b/test/php/TestClassmap.php
similarity index 96%
rename from test/php/TestPsr4.php
rename to test/php/TestClassmap.php
index d30bf1c..6fd1594 100644
--- a/test/php/TestPsr4.php
+++ b/test/php/TestClassmap.php
@@ -18,6 +18,6 @@
  */
 
 <?php
-$GEN_DIR = 'gen-php-psr4';
+$GEN_DIR = 'gen-php-classmap';
 include_once('TestClient.php');
 ?>
diff --git a/test/php/TestClient.php b/test/php/TestClient.php
index aa42e09..acd901d 100755
--- a/test/php/TestClient.php
+++ b/test/php/TestClient.php
@@ -2,7 +2,8 @@
 
 namespace test\php;
 
-require_once __DIR__.'/../../vendor/autoload.php';
+/** @var \Composer\Autoload\ClassLoader $loader */
+$loader = require __DIR__ . '/../../vendor/autoload.php';
 
 use Thrift\ClassLoader\ThriftClassLoader;
 
@@ -13,13 +14,14 @@
   $MODE = 'normal';
 }
 
-$loader = new ThriftClassLoader();
-if ($GEN_DIR === 'gen-php-psr4') {
-  $loader->registerNamespace('ThriftTest', $GEN_DIR);
+
+if ($GEN_DIR == 'gen-php') {
+  $loader->addPsr4('', $GEN_DIR);
 } else {
+  $loader = new ThriftClassLoader();
   $loader->registerDefinition('ThriftTest', $GEN_DIR);
+  $loader->register();
 }
-$loader->register();
 
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
@@ -93,7 +95,7 @@
     $MODE = substr($arg, 12);
   } else if (substr($arg, 0, 11) == '--protocol=') {
     $PROTO = substr($arg, 11);
-  } 
+  }
 }
 
 $hosts = array('localhost');