PHP namespaces for nested messages and enums (#4536)

* uses namespaces for nested messages and enums

* fixes namespaces for PHP dist

* fixes namespace for Descriptors, adds Cardinality and Kind

* fixes nested namespaces for reserved words and adds tests

* adds tests and generator fix for php class prefixes

* fixes escaping of protobuf packages, enum comments, misc others

* nice refactor of generated code

* adds class files for backwards compatibility

* simplifies code with templates

* adds compatibility files to makefile

* cleanup of generator and fixes nested namespace bug

* regenerates proto types

* remove internal BC classes

* adds deprecated warning, adds methods back

* simplifies if statement

* fixes dist files

* addresses review comments

* adds back TYPE_URL_PREFIX constant

* adds @deprecated to old nested class files

* skips tests which require a separate process when protobuf.so is enabled

* Adds tests for legacy nested classes that do not require separate processes to test

* uses legacy names for GPBUtil message check

* adds block for IDE @deprecated message

* Namespace for nested message/enum in c extension

* Remove unused code
diff --git a/php/ext/google/protobuf/def.c b/php/ext/google/protobuf/def.c
index 8140fe4..cb2c720 100644
--- a/php/ext/google/protobuf/def.c
+++ b/php/ext/google/protobuf/def.c
@@ -718,6 +718,170 @@
 #endif
 }
 
+static size_t classname_len_max(const char *fullname,
+                                const char *package,
+                                const char *php_namespace,
+                                const char *prefix) {
+  size_t fullname_len = strlen(fullname);
+  size_t package_len = 0;
+  size_t prefix_len = 0;
+  size_t namespace_len = 0;
+  size_t length = fullname_len;
+  int i, segment, classname_start = 0;
+
+  if (package != NULL) {
+    package_len = strlen(package);
+  }
+  if (prefix != NULL) {
+    prefix_len = strlen(prefix);
+  }
+  if (php_namespace != NULL) {
+    namespace_len = strlen(php_namespace);
+  }
+
+  // Process package
+  if (package_len > 0) {
+    segment = 1;
+    for (i = 0; i < package_len; i++) {
+      if (package[i] == '.') {
+        segment++;
+      }
+    }
+    // In case of reserved name in package.
+    length += 3 * segment;
+
+    classname_start = package_len + 1;
+  }
+
+  // Process class name
+  segment = 1;
+  for (i = classname_start; i < fullname_len; i++) {
+    if (fullname[i] == '.') {
+      segment++;
+    }
+  }
+  if (prefix_len == 0) {
+    length += 3 * segment;
+  } else {
+    length += prefix_len * segment;
+  }
+
+  // The additional 2, one is for preceding '.' and the other is for trailing 0.
+  return length + namespace_len + 2;
+}
+
+static bool is_reserved(const char *segment, int length) {
+  bool result;
+  char* lower = ALLOC_N(char, length + 1);
+  memcpy(lower, segment, length);
+  int i = 0;
+  while(lower[i]) {
+    lower[i] = (char)tolower(lower[i]);
+    i++;
+  }
+  lower[length] = 0;
+  result = is_reserved_name(lower);
+  FREE(lower);
+  return result;
+}
+
+static char* fill_prefix(const char *segment, int length,
+                         const char *prefix_given,
+                         const char *package_name, char *classname) {
+  size_t i;
+
+  if (prefix_given != NULL && strcmp(prefix_given, "") != 0) {
+    size_t prefix_len = strlen(prefix_given);
+    memcpy(classname, prefix_given, strlen(prefix_given));
+    classname += prefix_len;
+  } else {
+    if (is_reserved(segment, length)) {
+      if (package_name != NULL &&
+          strcmp("google.protobuf", package_name) == 0) {
+        memcpy(classname, "GPB", 3);
+        classname += 3;
+      } else {
+        memcpy(classname, "PB", 2);
+        classname += 2;
+      }
+    }
+  }
+  return classname;
+}
+
+static char* fill_segment(const char *segment, int length,
+                          char *classname, bool use_camel) {
+  memcpy(classname, segment, length);
+  if (use_camel && (segment[0] < 'A' || segment[0] > 'Z')) {
+    classname[0] += 'A' - 'a';
+  }
+  return classname + length;
+}
+
+static char* fill_namespace(const char *package, const char *namespace_given,
+                            char *classname) {
+  if (namespace_given != NULL) {
+    size_t namespace_len = strlen(namespace_given);
+    memcpy(classname, namespace_given, namespace_len);
+    classname += namespace_len;
+    *classname = '\\';
+    classname++;
+  } else if (package != NULL) {
+    int i = 0, j, offset = 0;
+    size_t package_len = strlen(package);
+    while (i < package_len) {
+      j = i;
+      while (j < package_len && package[j] != '.') {
+        j++;
+      }
+      classname = fill_prefix(package + i, j - i, "", package, classname);
+      classname = fill_segment(package + i, j - i, classname, true);
+      classname[0] = '\\';
+      classname++;
+      i = j + 1;
+    }
+  }
+  return classname;
+}
+
+static char* fill_classname(const char *fullname,
+                            const char *package,
+                            const char *namespace_given,
+                            const char *prefix, char *classname) {
+  int classname_start = 0;
+  if (package != NULL) {
+    size_t package_len = strlen(package);
+    classname_start = package_len == 0 ? 0 : package_len + 1;
+  }
+  size_t fullname_len = strlen(fullname);
+  classname = fill_prefix(fullname + classname_start,
+                          fullname_len - classname_start,
+                          prefix, package, classname);
+
+  int i = classname_start, j;
+  while (i < fullname_len) {
+    j = i;
+    while (j < fullname_len && fullname[j] != '.') {
+      j++;
+    }
+    classname = fill_segment(fullname + i, j - i, classname, false);
+    if (j != fullname_len) {
+      *classname = '_';
+      classname++;
+    }
+    i = j + 1;
+  }
+  return classname;
+}
+
+static char* fill_qualified_classname(const char *fullname,
+                                      const char *package,
+                                      const char *namespace_given,
+                                      const char *prefix, char *classname) {
+  classname = fill_namespace(package, namespace_given, classname);
+  return fill_classname(fullname, package, namespace_given, prefix, classname);
+}
+
 static void classname_no_prefix(const char *fullname, const char *package_name,
                                 char *class_name) {
   size_t i = 0, j;
@@ -736,89 +900,6 @@
   }
 }
 
-static const char *classname_prefix(const char *classname,
-                                    const char *prefix_given,
-                                    const char *package_name) {
-  size_t i;
-  bool is_reserved = false;
-
-  if (prefix_given != NULL && strcmp(prefix_given, "") != 0) {
-    return prefix_given;
-  }
-
-  char* lower = ALLOC_N(char, strlen(classname) + 1);
-  i = 0;
-  while(classname[i]) {
-    lower[i] = (char)tolower(classname[i]);
-    i++;
-  }
-  lower[i] = 0;
-
-  is_reserved = is_reserved_name(lower);
-  FREE(lower);
-
-  if (is_reserved) {
-    if (package_name != NULL && strcmp("google.protobuf", package_name) == 0) {
-      return "GPB";
-    } else {
-      return "PB";
-    }
-  }
-
-  return "";
-}
-
-static void convert_to_class_name_inplace(const char *package,
-                                          const char *namespace_given,
-                                          const char *prefix, char *classname) {
-  size_t prefix_len = prefix == NULL ? 0 : strlen(prefix);
-  size_t classname_len = strlen(classname);
-  int i = 0, j;
-  bool first_char = true;
-
-  size_t package_len = package == NULL ? 0 : strlen(package);
-  size_t namespace_given_len =
-      namespace_given == NULL ? 0 : strlen(namespace_given);
-  bool use_namespace_given = namespace_given != NULL;
-  size_t namespace_len =
-      use_namespace_given ? namespace_given_len : package_len;
-
-  int offset = namespace_len != 0 ? 2 : 0;
-
-  for (j = 0; j < classname_len; j++) {
-    classname[namespace_len + prefix_len + classname_len + offset - 1 - j] =
-        classname[classname_len - j - 1];
-  }
-
-  if (namespace_len != 0) {
-    classname[i++] = '\\';
-    for (j = 0; j < namespace_len; j++) {
-      if (use_namespace_given) {
-        classname[i++] = namespace_given[j];
-        continue;
-      }
-      // php packages are divided by '\'.
-      if (package[j] == '.') {
-        classname[i++] = '\\';
-        first_char = true;
-      } else if (first_char) {
-        // PHP package uses camel case.
-        if (package[j] < 'A' || package[j] > 'Z') {
-          classname[i++] = package[j] + 'A' - 'a';
-        } else {
-          classname[i++] = package[j];
-        }
-        first_char = false;
-      } else {
-        classname[i++] = package[j];
-      }
-    }
-    classname[i++] = '\\';
-  }
-
-  memcpy(classname + i, prefix, prefix_len);
-}
-
 void internal_add_generated_file(const char *data, PHP_PROTO_SIZE data_len,
                                  InternalDescriptorPool *pool TSRMLS_DC) {
   upb_filedef **files;
@@ -858,20 +939,14 @@
      * bytes allocated, one for '.', one for trailing 0, and 3 for 'GPB' if    \
      * given message is google.protobuf.Empty.*/                               \
     const char *fullname = upb_##def_type_lower##_fullname(def_type_lower);    \
+    const char *package = upb_filedef_package(files[0]);                       \
     const char *php_namespace = upb_filedef_phpnamespace(files[0]);            \
     const char *prefix_given = upb_filedef_phpprefix(files[0]);                \
-    size_t classname_len = strlen(fullname) + 5;                               \
-    if (prefix_given != NULL) {                                                \
-      classname_len += strlen(prefix_given);                                   \
-    }                                                                          \
-    if (php_namespace != NULL) {                                               \
-      classname_len += strlen(php_namespace);                                  \
-    }                                                                          \
+    size_t classname_len = classname_len_max(fullname, package,                \
+                                             php_namespace, prefix_given);     \
     char *classname = ecalloc(sizeof(char), classname_len);                    \
-    const char *package = upb_filedef_package(files[0]);                       \
-    classname_no_prefix(fullname, package, classname);                         \
-    const char *prefix = classname_prefix(classname, prefix_given, package);   \
-    convert_to_class_name_inplace(package, php_namespace, prefix, classname);  \
+    fill_qualified_classname(fullname, package, php_namespace,                 \
+                             prefix_given, classname);                         \
     PHP_PROTO_CE_DECLARE pce;                                                  \
     if (php_proto_zend_lookup_class(classname, strlen(classname), &pce) ==     \
         FAILURE) {                                                             \
diff --git a/php/ext/google/protobuf/message.c b/php/ext/google/protobuf/message.c
index 5a8734b..6901287 100644
--- a/php/ext/google/protobuf/message.c
+++ b/php/ext/google/protobuf/message.c
@@ -858,7 +858,7 @@
 zend_class_entry* field_cardinality_type;
 
 // Init class entry.
-PHP_PROTO_INIT_ENUMCLASS_START("Google\\Protobuf\\Field_Cardinality",
+PHP_PROTO_INIT_ENUMCLASS_START("Google\\Protobuf\\Field\\Cardinality",
                                 Field_Cardinality, field_cardinality)
   zend_declare_class_constant_long(field_cardinality_type,
                                    "CARDINALITY_UNKNOWN", 19, 0 TSRMLS_CC);
@@ -868,6 +868,8 @@
                                    "CARDINALITY_REQUIRED", 20, 2 TSRMLS_CC);
   zend_declare_class_constant_long(field_cardinality_type,
                                    "CARDINALITY_REPEATED", 20, 3 TSRMLS_CC);
+  const char *alias = "Google\\Protobuf\\Field_Cardinality";
+  zend_register_class_alias_ex(alias, strlen(alias), field_cardinality_type TSRMLS_CC);
 PHP_PROTO_INIT_ENUMCLASS_END
 
 // -----------------------------------------------------------------------------
@@ -881,7 +883,7 @@
 zend_class_entry* field_kind_type;
 
 // Init class entry.
-PHP_PROTO_INIT_ENUMCLASS_START("Google\\Protobuf\\Field_Kind",
+PHP_PROTO_INIT_ENUMCLASS_START("Google\\Protobuf\\Field\\Kind",
                                 Field_Kind, field_kind)
   zend_declare_class_constant_long(field_kind_type,
                                    "TYPE_UNKNOWN", 12, 0 TSRMLS_CC);
@@ -921,6 +923,8 @@
                                    "TYPE_SINT32", 11, 17 TSRMLS_CC);
   zend_declare_class_constant_long(field_kind_type,
                                    "TYPE_SINT64", 11, 18 TSRMLS_CC);
+  const char *alias = "Google\\Protobuf\\Field_Kind";
+  zend_register_class_alias_ex(alias, strlen(alias), field_kind_type TSRMLS_CC);
 PHP_PROTO_INIT_ENUMCLASS_END
 
 // -----------------------------------------------------------------------------
diff --git a/php/src/GPBMetadata/Google/Protobuf/Internal/Descriptor.php b/php/src/GPBMetadata/Google/Protobuf/Internal/Descriptor.php
index 7057384..e6362f2 100644
--- a/php/src/GPBMetadata/Google/Protobuf/Internal/Descriptor.php
+++ b/php/src/GPBMetadata/Google/Protobuf/Internal/Descriptor.php
@@ -46,13 +46,13 @@
             ->repeated('reserved_name', \Google\Protobuf\Internal\GPBType::STRING, 10)
             ->finalizeToPool();
 
-        $pool->addMessage('google.protobuf.internal.DescriptorProto.ExtensionRange', \Google\Protobuf\Internal\DescriptorProto_ExtensionRange::class)
+        $pool->addMessage('google.protobuf.internal.DescriptorProto.ExtensionRange', \Google\Protobuf\Internal\DescriptorProto\ExtensionRange::class)
             ->optional('start', \Google\Protobuf\Internal\GPBType::INT32, 1)
             ->optional('end', \Google\Protobuf\Internal\GPBType::INT32, 2)
             ->optional('options', \Google\Protobuf\Internal\GPBType::MESSAGE, 3, 'google.protobuf.internal.ExtensionRangeOptions')
             ->finalizeToPool();
 
-        $pool->addMessage('google.protobuf.internal.DescriptorProto.ReservedRange', \Google\Protobuf\Internal\DescriptorProto_ReservedRange::class)
+        $pool->addMessage('google.protobuf.internal.DescriptorProto.ReservedRange', \Google\Protobuf\Internal\DescriptorProto\ReservedRange::class)
             ->optional('start', \Google\Protobuf\Internal\GPBType::INT32, 1)
             ->optional('end', \Google\Protobuf\Internal\GPBType::INT32, 2)
             ->finalizeToPool();
@@ -114,7 +114,7 @@
             ->repeated('reserved_name', \Google\Protobuf\Internal\GPBType::STRING, 5)
             ->finalizeToPool();
 
-        $pool->addMessage('google.protobuf.internal.EnumDescriptorProto.EnumReservedRange', \Google\Protobuf\Internal\EnumDescriptorProto_EnumReservedRange::class)
+        $pool->addMessage('google.protobuf.internal.EnumDescriptorProto.EnumReservedRange', \Google\Protobuf\Internal\EnumDescriptorProto\EnumReservedRange::class)
             ->optional('start', \Google\Protobuf\Internal\GPBType::INT32, 1)
             ->optional('end', \Google\Protobuf\Internal\GPBType::INT32, 2)
             ->finalizeToPool();
@@ -242,7 +242,7 @@
             ->optional('aggregate_value', \Google\Protobuf\Internal\GPBType::STRING, 8)
             ->finalizeToPool();
 
-        $pool->addMessage('google.protobuf.internal.UninterpretedOption.NamePart', \Google\Protobuf\Internal\UninterpretedOption_NamePart::class)
+        $pool->addMessage('google.protobuf.internal.UninterpretedOption.NamePart', \Google\Protobuf\Internal\UninterpretedOption\NamePart::class)
             ->required('name_part', \Google\Protobuf\Internal\GPBType::STRING, 1)
             ->required('is_extension', \Google\Protobuf\Internal\GPBType::BOOL, 2)
             ->finalizeToPool();
@@ -251,7 +251,7 @@
             ->repeated('location', \Google\Protobuf\Internal\GPBType::MESSAGE, 1, 'google.protobuf.internal.SourceCodeInfo.Location')
             ->finalizeToPool();
 
-        $pool->addMessage('google.protobuf.internal.SourceCodeInfo.Location', \Google\Protobuf\Internal\SourceCodeInfo_Location::class)
+        $pool->addMessage('google.protobuf.internal.SourceCodeInfo.Location', \Google\Protobuf\Internal\SourceCodeInfo\Location::class)
             ->repeated('path', \Google\Protobuf\Internal\GPBType::INT32, 1)
             ->repeated('span', \Google\Protobuf\Internal\GPBType::INT32, 2)
             ->optional('leading_comments', \Google\Protobuf\Internal\GPBType::STRING, 3)
@@ -263,7 +263,7 @@
             ->repeated('annotation', \Google\Protobuf\Internal\GPBType::MESSAGE, 1, 'google.protobuf.internal.GeneratedCodeInfo.Annotation')
             ->finalizeToPool();
 
-        $pool->addMessage('google.protobuf.internal.GeneratedCodeInfo.Annotation', \Google\Protobuf\Internal\GeneratedCodeInfo_Annotation::class)
+        $pool->addMessage('google.protobuf.internal.GeneratedCodeInfo.Annotation', \Google\Protobuf\Internal\GeneratedCodeInfo\Annotation::class)
             ->repeated('path', \Google\Protobuf\Internal\GPBType::INT32, 1)
             ->optional('source_file', \Google\Protobuf\Internal\GPBType::STRING, 2)
             ->optional('begin', \Google\Protobuf\Internal\GPBType::INT32, 3)
diff --git a/php/src/Google/Protobuf/Any.php b/php/src/Google/Protobuf/Any.php
index f027b05..a992854 100644
--- a/php/src/Google/Protobuf/Any.php
+++ b/php/src/Google/Protobuf/Any.php
@@ -5,9 +5,9 @@
 namespace Google\Protobuf;
 
 use Google\Protobuf\Internal\GPBType;
-use Google\Protobuf\Internal\GPBUtil;
 use Google\Protobuf\Internal\Message;
 use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
 
 /**
  * `Any` contains an arbitrary serialized protocol buffer message along with a
@@ -37,6 +37,14 @@
  *     if any.Is(Foo.DESCRIPTOR):
  *       any.Unpack(foo)
  *       ...
+ *  Example 4: Pack and unpack a message in Go
+ *      foo := &pb.Foo{...}
+ *      any, err := ptypes.MarshalAny(foo)
+ *      ...
+ *      foo := &pb.Foo{}
+ *      if err := ptypes.UnmarshalAny(any, foo); err != nil {
+ *        ...
+ *      }
  * The pack methods provided by protobuf library will by default use
  * 'type.googleapis.com/full.type.name' as the type URL and the unpack
  * methods only use the fully qualified type name after the last '/'
@@ -71,15 +79,16 @@
 class Any extends \Google\Protobuf\Internal\Message
 {
     /**
-     * A URL/resource name whose content describes the type of the
-     * serialized protocol buffer message.
-     * For URLs which use the scheme `http`, `https`, or no scheme, the
-     * following restrictions and interpretations apply:
+     * A URL/resource name that uniquely identifies the type of the serialized
+     * protocol buffer message. The last segment of the URL's path must represent
+     * the fully qualified name of the type (as in
+     * `path/google.protobuf.Duration`). The name should be in a canonical form
+     * (e.g., leading "." is not accepted).
+     * In practice, teams usually precompile into the binary all types that they
+     * expect it to use in the context of Any. However, for URLs which use the
+     * scheme `http`, `https`, or no scheme, one can optionally set up a type
+     * server that maps type URLs to message definitions as follows:
      * * If no scheme is provided, `https` is assumed.
-     * * The last segment of the URL's path must represent the fully
-     *   qualified name of the type (as in `path/google.protobuf.Duration`).
-     *   The name should be in a canonical form (e.g., leading "." is
-     *   not accepted).
      * * An HTTP GET on the URL must yield a [google.protobuf.Type][]
      *   value in binary format, or produce an error.
      * * Applications are allowed to cache lookup results based on the
@@ -87,6 +96,9 @@
      *   lookup. Therefore, binary compatibility needs to be preserved
      *   on changes to types. (Use versioned type names to manage
      *   breaking changes.)
+     * Note: this functionality is not currently available in the official
+     * protobuf release, and it is not used for type URLs beginning with
+     * type.googleapis.com.
      * Schemes other than `http`, `https` (or the empty scheme) might be
      * used with implementation specific semantics.
      *
@@ -102,21 +114,55 @@
 
     const TYPE_URL_PREFIX = 'type.googleapis.com/';
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type string $type_url
+     *           A URL/resource name that uniquely identifies the type of the serialized
+     *           protocol buffer message. The last segment of the URL's path must represent
+     *           the fully qualified name of the type (as in
+     *           `path/google.protobuf.Duration`). The name should be in a canonical form
+     *           (e.g., leading "." is not accepted).
+     *           In practice, teams usually precompile into the binary all types that they
+     *           expect it to use in the context of Any. However, for URLs which use the
+     *           scheme `http`, `https`, or no scheme, one can optionally set up a type
+     *           server that maps type URLs to message definitions as follows:
+     *           * If no scheme is provided, `https` is assumed.
+     *           * An HTTP GET on the URL must yield a [google.protobuf.Type][]
+     *             value in binary format, or produce an error.
+     *           * Applications are allowed to cache lookup results based on the
+     *             URL, or have them precompiled into a binary to avoid any
+     *             lookup. Therefore, binary compatibility needs to be preserved
+     *             on changes to types. (Use versioned type names to manage
+     *             breaking changes.)
+     *           Note: this functionality is not currently available in the official
+     *           protobuf release, and it is not used for type URLs beginning with
+     *           type.googleapis.com.
+     *           Schemes other than `http`, `https` (or the empty scheme) might be
+     *           used with implementation specific semantics.
+     *     @type string $value
+     *           Must be a valid serialized protocol buffer of the above specified type.
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Google\Protobuf\Any::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**
-     * A URL/resource name whose content describes the type of the
-     * serialized protocol buffer message.
-     * For URLs which use the scheme `http`, `https`, or no scheme, the
-     * following restrictions and interpretations apply:
+     * A URL/resource name that uniquely identifies the type of the serialized
+     * protocol buffer message. The last segment of the URL's path must represent
+     * the fully qualified name of the type (as in
+     * `path/google.protobuf.Duration`). The name should be in a canonical form
+     * (e.g., leading "." is not accepted).
+     * In practice, teams usually precompile into the binary all types that they
+     * expect it to use in the context of Any. However, for URLs which use the
+     * scheme `http`, `https`, or no scheme, one can optionally set up a type
+     * server that maps type URLs to message definitions as follows:
      * * If no scheme is provided, `https` is assumed.
-     * * The last segment of the URL's path must represent the fully
-     *   qualified name of the type (as in `path/google.protobuf.Duration`).
-     *   The name should be in a canonical form (e.g., leading "." is
-     *   not accepted).
      * * An HTTP GET on the URL must yield a [google.protobuf.Type][]
      *   value in binary format, or produce an error.
      * * Applications are allowed to cache lookup results based on the
@@ -124,6 +170,9 @@
      *   lookup. Therefore, binary compatibility needs to be preserved
      *   on changes to types. (Use versioned type names to manage
      *   breaking changes.)
+     * Note: this functionality is not currently available in the official
+     * protobuf release, and it is not used for type URLs beginning with
+     * type.googleapis.com.
      * Schemes other than `http`, `https` (or the empty scheme) might be
      * used with implementation specific semantics.
      *
@@ -136,15 +185,16 @@
     }
 
     /**
-     * A URL/resource name whose content describes the type of the
-     * serialized protocol buffer message.
-     * For URLs which use the scheme `http`, `https`, or no scheme, the
-     * following restrictions and interpretations apply:
+     * A URL/resource name that uniquely identifies the type of the serialized
+     * protocol buffer message. The last segment of the URL's path must represent
+     * the fully qualified name of the type (as in
+     * `path/google.protobuf.Duration`). The name should be in a canonical form
+     * (e.g., leading "." is not accepted).
+     * In practice, teams usually precompile into the binary all types that they
+     * expect it to use in the context of Any. However, for URLs which use the
+     * scheme `http`, `https`, or no scheme, one can optionally set up a type
+     * server that maps type URLs to message definitions as follows:
      * * If no scheme is provided, `https` is assumed.
-     * * The last segment of the URL's path must represent the fully
-     *   qualified name of the type (as in `path/google.protobuf.Duration`).
-     *   The name should be in a canonical form (e.g., leading "." is
-     *   not accepted).
      * * An HTTP GET on the URL must yield a [google.protobuf.Type][]
      *   value in binary format, or produce an error.
      * * Applications are allowed to cache lookup results based on the
@@ -152,6 +202,9 @@
      *   lookup. Therefore, binary compatibility needs to be preserved
      *   on changes to types. (Use versioned type names to manage
      *   breaking changes.)
+     * Note: this functionality is not currently available in the official
+     * protobuf release, and it is not used for type URLs beginning with
+     * type.googleapis.com.
      * Schemes other than `http`, `https` (or the empty scheme) might be
      * used with implementation specific semantics.
      *
@@ -269,3 +322,4 @@
         return $this->type_url === $type_url;
     }
 }
+
diff --git a/php/src/Google/Protobuf/Api.php b/php/src/Google/Protobuf/Api.php
index d0dda3c..db37ffb 100644
--- a/php/src/Google/Protobuf/Api.php
+++ b/php/src/Google/Protobuf/Api.php
@@ -83,9 +83,49 @@
      */
     private $syntax = 0;
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type string $name
+     *           The fully qualified name of this interface, including package name
+     *           followed by the interface's simple name.
+     *     @type \Google\Protobuf\Method[]|\Google\Protobuf\Internal\RepeatedField $methods
+     *           The methods of this interface, in unspecified order.
+     *     @type \Google\Protobuf\Option[]|\Google\Protobuf\Internal\RepeatedField $options
+     *           Any metadata attached to the interface.
+     *     @type string $version
+     *           A version string for this interface. If specified, must have the form
+     *           `major-version.minor-version`, as in `1.10`. If the minor version is
+     *           omitted, it defaults to zero. If the entire version field is empty, the
+     *           major version is derived from the package name, as outlined below. If the
+     *           field is not empty, the version in the package name will be verified to be
+     *           consistent with what is provided here.
+     *           The versioning schema uses [semantic
+     *           versioning](http://semver.org) where the major version number
+     *           indicates a breaking change and the minor version an additive,
+     *           non-breaking change. Both version numbers are signals to users
+     *           what to expect from different versions, and should be carefully
+     *           chosen based on the product plan.
+     *           The major version is also reflected in the package name of the
+     *           interface, which must end in `v<major-version>`, as in
+     *           `google.feature.v1`. For major versions 0 and 1, the suffix can
+     *           be omitted. Zero major versions must only be used for
+     *           experimental, non-GA interfaces.
+     *     @type \Google\Protobuf\SourceContext $source_context
+     *           Source context for the protocol buffer service represented by this
+     *           message.
+     *     @type \Google\Protobuf\Mixin[]|\Google\Protobuf\Internal\RepeatedField $mixins
+     *           Included interfaces. See [Mixin][].
+     *     @type int $syntax
+     *           The source syntax of the service.
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Google\Protobuf\Api::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**
diff --git a/php/src/Google/Protobuf/BoolValue.php b/php/src/Google/Protobuf/BoolValue.php
index c28bf94..13872eb 100644
--- a/php/src/Google/Protobuf/BoolValue.php
+++ b/php/src/Google/Protobuf/BoolValue.php
@@ -23,9 +23,19 @@
      */
     private $value = false;
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type bool $value
+     *           The bool value.
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Google\Protobuf\Wrappers::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**
diff --git a/php/src/Google/Protobuf/BytesValue.php b/php/src/Google/Protobuf/BytesValue.php
index d6a6b2e..f1b3817 100644
--- a/php/src/Google/Protobuf/BytesValue.php
+++ b/php/src/Google/Protobuf/BytesValue.php
@@ -23,9 +23,19 @@
      */
     private $value = '';
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type string $value
+     *           The bytes value.
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Google\Protobuf\Wrappers::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**
diff --git a/php/src/Google/Protobuf/DoubleValue.php b/php/src/Google/Protobuf/DoubleValue.php
index 6718ce3..236d918 100644
--- a/php/src/Google/Protobuf/DoubleValue.php
+++ b/php/src/Google/Protobuf/DoubleValue.php
@@ -23,9 +23,19 @@
      */
     private $value = 0.0;
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type float $value
+     *           The double value.
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Google\Protobuf\Wrappers::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**
diff --git a/php/src/Google/Protobuf/Duration.php b/php/src/Google/Protobuf/Duration.php
index ca1c4c0..414a186 100644
--- a/php/src/Google/Protobuf/Duration.php
+++ b/php/src/Google/Protobuf/Duration.php
@@ -79,9 +79,28 @@
      */
     private $nanos = 0;
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type int|string $seconds
+     *           Signed seconds of the span of time. Must be from -315,576,000,000
+     *           to +315,576,000,000 inclusive. Note: these bounds are computed from:
+     *           60 sec/min * 60 min/hr * 24 hr/day * 365.25 days/year * 10000 years
+     *     @type int $nanos
+     *           Signed fractions of a second at nanosecond resolution of the span
+     *           of time. Durations less than one second are represented with a 0
+     *           `seconds` field and a positive or negative `nanos` field. For durations
+     *           of one second or more, a non-zero value for the `nanos` field must be
+     *           of the same sign as the `seconds` field. Must be from -999,999,999
+     *           to +999,999,999 inclusive.
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Google\Protobuf\Duration::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**
@@ -149,5 +168,6 @@
 
         return $this;
     }
+
 }
 
diff --git a/php/src/Google/Protobuf/Enum.php b/php/src/Google/Protobuf/Enum.php
index c63efc7..243c40d 100644
--- a/php/src/Google/Protobuf/Enum.php
+++ b/php/src/Google/Protobuf/Enum.php
@@ -46,9 +46,27 @@
      */
     private $syntax = 0;
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type string $name
+     *           Enum type name.
+     *     @type \Google\Protobuf\EnumValue[]|\Google\Protobuf\Internal\RepeatedField $enumvalue
+     *           Enum value definitions.
+     *     @type \Google\Protobuf\Option[]|\Google\Protobuf\Internal\RepeatedField $options
+     *           Protocol buffer options.
+     *     @type \Google\Protobuf\SourceContext $source_context
+     *           The source context.
+     *     @type int $syntax
+     *           The source syntax.
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Google\Protobuf\Type::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**
diff --git a/php/src/Google/Protobuf/EnumValue.php b/php/src/Google/Protobuf/EnumValue.php
index e102c29..1dc3c7a 100644
--- a/php/src/Google/Protobuf/EnumValue.php
+++ b/php/src/Google/Protobuf/EnumValue.php
@@ -34,9 +34,23 @@
      */
     private $options;
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type string $name
+     *           Enum value name.
+     *     @type int $number
+     *           Enum value number.
+     *     @type \Google\Protobuf\Option[]|\Google\Protobuf\Internal\RepeatedField $options
+     *           Protocol buffer options.
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Google\Protobuf\Type::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**
diff --git a/php/src/Google/Protobuf/Field.php b/php/src/Google/Protobuf/Field.php
index 0b560d8..8da43e3 100644
--- a/php/src/Google/Protobuf/Field.php
+++ b/php/src/Google/Protobuf/Field.php
@@ -78,9 +78,39 @@
      */
     private $default_value = '';
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type int $kind
+     *           The field type.
+     *     @type int $cardinality
+     *           The field cardinality.
+     *     @type int $number
+     *           The field number.
+     *     @type string $name
+     *           The field name.
+     *     @type string $type_url
+     *           The field type URL, without the scheme, for message or enumeration
+     *           types. Example: `"type.googleapis.com/google.protobuf.Timestamp"`.
+     *     @type int $oneof_index
+     *           The index of the field type in `Type.oneofs`, for message or enumeration
+     *           types. The first type has index 1; zero means the type is not in the list.
+     *     @type bool $packed
+     *           Whether to use alternative packed wire representation.
+     *     @type \Google\Protobuf\Option[]|\Google\Protobuf\Internal\RepeatedField $options
+     *           The protocol buffer options.
+     *     @type string $json_name
+     *           The field JSON name.
+     *     @type string $default_value
+     *           The string value of the default value of this field. Proto2 syntax only.
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Google\Protobuf\Type::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**
diff --git a/php/src/Google/Protobuf/Field/Cardinality.php b/php/src/Google/Protobuf/Field/Cardinality.php
new file mode 100644
index 0000000..c887f6d
--- /dev/null
+++ b/php/src/Google/Protobuf/Field/Cardinality.php
@@ -0,0 +1,42 @@
+<?php
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: google/protobuf/type.proto
+
+namespace Google\Protobuf\Field;
+
+/**
+ * Whether a field is optional, required, or repeated.
+ *
+ * Protobuf type <code>google.protobuf.Field.Cardinality</code>
+ */
+class Cardinality
+{
+    /**
+     * For fields with unknown cardinality.
+     *
+     * Generated from protobuf enum <code>CARDINALITY_UNKNOWN = 0;</code>
+     */
+    const CARDINALITY_UNKNOWN = 0;
+    /**
+     * For optional fields.
+     *
+     * Generated from protobuf enum <code>CARDINALITY_OPTIONAL = 1;</code>
+     */
+    const CARDINALITY_OPTIONAL = 1;
+    /**
+     * For required fields. Proto2 syntax only.
+     *
+     * Generated from protobuf enum <code>CARDINALITY_REQUIRED = 2;</code>
+     */
+    const CARDINALITY_REQUIRED = 2;
+    /**
+     * For repeated fields.
+     *
+     * Generated from protobuf enum <code>CARDINALITY_REPEATED = 3;</code>
+     */
+    const CARDINALITY_REPEATED = 3;
+}
+
+// Adding a class alias for backwards compatibility with the previous class name.
+class_alias(Cardinality::class, \Google\Protobuf\Field_Cardinality::class);
+
diff --git a/php/src/Google/Protobuf/Internal/FieldDescriptorProto_Type.php b/php/src/Google/Protobuf/Field/Kind.php
similarity index 66%
copy from php/src/Google/Protobuf/Internal/FieldDescriptorProto_Type.php
copy to php/src/Google/Protobuf/Field/Kind.php
index 1b022de..a2bbbde 100644
--- a/php/src/Google/Protobuf/Internal/FieldDescriptorProto_Type.php
+++ b/php/src/Google/Protobuf/Field/Kind.php
@@ -1,107 +1,132 @@
 <?php
 # Generated by the protocol buffer compiler.  DO NOT EDIT!
-# source: google/protobuf/descriptor.proto
+# source: google/protobuf/type.proto
 
-namespace Google\Protobuf\Internal;
+namespace Google\Protobuf\Field;
 
 /**
- * Protobuf enum <code>Google\Protobuf\Internal</code>
+ * Basic field types.
+ *
+ * Protobuf type <code>google.protobuf.Field.Kind</code>
  */
-class FieldDescriptorProto_Type
+class Kind
 {
     /**
-     * 0 is reserved for errors.
-     * Order is weird for historical reasons.
+     * Field type unknown.
+     *
+     * Generated from protobuf enum <code>TYPE_UNKNOWN = 0;</code>
+     */
+    const TYPE_UNKNOWN = 0;
+    /**
+     * Field type double.
      *
      * Generated from protobuf enum <code>TYPE_DOUBLE = 1;</code>
      */
     const TYPE_DOUBLE = 1;
     /**
+     * Field type float.
+     *
      * Generated from protobuf enum <code>TYPE_FLOAT = 2;</code>
      */
     const TYPE_FLOAT = 2;
     /**
-     * Not ZigZag encoded.  Negative numbers take 10 bytes.  Use TYPE_SINT64 if
-     * negative values are likely.
+     * Field type int64.
      *
      * Generated from protobuf enum <code>TYPE_INT64 = 3;</code>
      */
     const TYPE_INT64 = 3;
     /**
+     * Field type uint64.
+     *
      * Generated from protobuf enum <code>TYPE_UINT64 = 4;</code>
      */
     const TYPE_UINT64 = 4;
     /**
-     * Not ZigZag encoded.  Negative numbers take 10 bytes.  Use TYPE_SINT32 if
-     * negative values are likely.
+     * Field type int32.
      *
      * Generated from protobuf enum <code>TYPE_INT32 = 5;</code>
      */
     const TYPE_INT32 = 5;
     /**
+     * Field type fixed64.
+     *
      * Generated from protobuf enum <code>TYPE_FIXED64 = 6;</code>
      */
     const TYPE_FIXED64 = 6;
     /**
+     * Field type fixed32.
+     *
      * Generated from protobuf enum <code>TYPE_FIXED32 = 7;</code>
      */
     const TYPE_FIXED32 = 7;
     /**
+     * Field type bool.
+     *
      * Generated from protobuf enum <code>TYPE_BOOL = 8;</code>
      */
     const TYPE_BOOL = 8;
     /**
+     * Field type string.
+     *
      * Generated from protobuf enum <code>TYPE_STRING = 9;</code>
      */
     const TYPE_STRING = 9;
     /**
-     * Tag-delimited aggregate.
-     * Group type is deprecated and not supported in proto3. However, Proto3
-     * implementations should still be able to parse the group wire format and
-     * treat group fields as unknown fields.
+     * Field type group. Proto2 syntax only, and deprecated.
      *
      * Generated from protobuf enum <code>TYPE_GROUP = 10;</code>
      */
     const TYPE_GROUP = 10;
     /**
-     * Length-delimited aggregate.
+     * Field type message.
      *
      * Generated from protobuf enum <code>TYPE_MESSAGE = 11;</code>
      */
     const TYPE_MESSAGE = 11;
     /**
-     * New in version 2.
+     * Field type bytes.
      *
      * Generated from protobuf enum <code>TYPE_BYTES = 12;</code>
      */
     const TYPE_BYTES = 12;
     /**
+     * Field type uint32.
+     *
      * Generated from protobuf enum <code>TYPE_UINT32 = 13;</code>
      */
     const TYPE_UINT32 = 13;
     /**
+     * Field type enum.
+     *
      * Generated from protobuf enum <code>TYPE_ENUM = 14;</code>
      */
     const TYPE_ENUM = 14;
     /**
+     * Field type sfixed32.
+     *
      * Generated from protobuf enum <code>TYPE_SFIXED32 = 15;</code>
      */
     const TYPE_SFIXED32 = 15;
     /**
+     * Field type sfixed64.
+     *
      * Generated from protobuf enum <code>TYPE_SFIXED64 = 16;</code>
      */
     const TYPE_SFIXED64 = 16;
     /**
-     * Uses ZigZag encoding.
+     * Field type sint32.
      *
      * Generated from protobuf enum <code>TYPE_SINT32 = 17;</code>
      */
     const TYPE_SINT32 = 17;
     /**
-     * Uses ZigZag encoding.
+     * Field type sint64.
      *
      * Generated from protobuf enum <code>TYPE_SINT64 = 18;</code>
      */
     const TYPE_SINT64 = 18;
 }
 
+// Adding a class alias for backwards compatibility with the previous class name.
+class_alias(Kind::class, \Google\Protobuf\Field_Kind::class);
+
diff --git a/php/src/Google/Protobuf/FieldMask.php b/php/src/Google/Protobuf/FieldMask.php
index e18586a..8fb38cb 100644
--- a/php/src/Google/Protobuf/FieldMask.php
+++ b/php/src/Google/Protobuf/FieldMask.php
@@ -162,6 +162,10 @@
  *     }
  * Note that oneof type names ("test_oneof" in this case) cannot be used in
  * paths.
+ * ## Field Mask Verification
+ * The implementation of any API method which has a FieldMask type field in the
+ * request should verify the included field paths, and return an
+ * `INVALID_ARGUMENT` error if any path is duplicated or unmappable.
  *
  * Generated from protobuf message <code>google.protobuf.FieldMask</code>
  */
@@ -174,9 +178,19 @@
      */
     private $paths;
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type string[]|\Google\Protobuf\Internal\RepeatedField $paths
+     *           The set of field mask paths.
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Google\Protobuf\FieldMask::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**
diff --git a/php/src/Google/Protobuf/Field_Cardinality.php b/php/src/Google/Protobuf/Field_Cardinality.php
index 422587c..dff8f89 100644
--- a/php/src/Google/Protobuf/Field_Cardinality.php
+++ b/php/src/Google/Protobuf/Field_Cardinality.php
@@ -4,36 +4,13 @@
 
 namespace Google\Protobuf;
 
-/**
- * Whether a field is optional, required, or repeated.
- *
- * Protobuf enum <code>Google\Protobuf\Field\Cardinality</code>
- */
-class Field_Cardinality
-{
+if (false) {
     /**
-     * For fields with unknown cardinality.
-     *
-     * Generated from protobuf enum <code>CARDINALITY_UNKNOWN = 0;</code>
+     * This class is deprecated. Use Google\Protobuf\Field\Cardinality instead.
+     * @deprecated
      */
-    const CARDINALITY_UNKNOWN = 0;
-    /**
-     * For optional fields.
-     *
-     * Generated from protobuf enum <code>CARDINALITY_OPTIONAL = 1;</code>
-     */
-    const CARDINALITY_OPTIONAL = 1;
-    /**
-     * For required fields. Proto2 syntax only.
-     *
-     * Generated from protobuf enum <code>CARDINALITY_REQUIRED = 2;</code>
-     */
-    const CARDINALITY_REQUIRED = 2;
-    /**
-     * For repeated fields.
-     *
-     * Generated from protobuf enum <code>CARDINALITY_REPEATED = 3;</code>
-     */
-    const CARDINALITY_REPEATED = 3;
+    class Field_Cardinality {}
 }
+class_exists(Field\Cardinality::class);
+@trigger_error('Google\Protobuf\Field_Cardinality is deprecated and will be removed in the next major release. Use Google\Protobuf\Field\Cardinality instead', E_USER_DEPRECATED);
 
diff --git a/php/src/Google/Protobuf/Field_Kind.php b/php/src/Google/Protobuf/Field_Kind.php
index d077497..aa20237 100644
--- a/php/src/Google/Protobuf/Field_Kind.php
+++ b/php/src/Google/Protobuf/Field_Kind.php
@@ -4,126 +4,13 @@
 
 namespace Google\Protobuf;
 
-/**
- * Basic field types.
- *
- * Protobuf enum <code>Google\Protobuf\Field\Kind</code>
- */
-class Field_Kind
-{
+if (false) {
     /**
-     * Field type unknown.
-     *
-     * Generated from protobuf enum <code>TYPE_UNKNOWN = 0;</code>
+     * This class is deprecated. Use Google\Protobuf\Field\Kind instead.
+     * @deprecated
      */
-    const TYPE_UNKNOWN = 0;
-    /**
-     * Field type double.
-     *
-     * Generated from protobuf enum <code>TYPE_DOUBLE = 1;</code>
-     */
-    const TYPE_DOUBLE = 1;
-    /**
-     * Field type float.
-     *
-     * Generated from protobuf enum <code>TYPE_FLOAT = 2;</code>
-     */
-    const TYPE_FLOAT = 2;
-    /**
-     * Field type int64.
-     *
-     * Generated from protobuf enum <code>TYPE_INT64 = 3;</code>
-     */
-    const TYPE_INT64 = 3;
-    /**
-     * Field type uint64.
-     *
-     * Generated from protobuf enum <code>TYPE_UINT64 = 4;</code>
-     */
-    const TYPE_UINT64 = 4;
-    /**
-     * Field type int32.
-     *
-     * Generated from protobuf enum <code>TYPE_INT32 = 5;</code>
-     */
-    const TYPE_INT32 = 5;
-    /**
-     * Field type fixed64.
-     *
-     * Generated from protobuf enum <code>TYPE_FIXED64 = 6;</code>
-     */
-    const TYPE_FIXED64 = 6;
-    /**
-     * Field type fixed32.
-     *
-     * Generated from protobuf enum <code>TYPE_FIXED32 = 7;</code>
-     */
-    const TYPE_FIXED32 = 7;
-    /**
-     * Field type bool.
-     *
-     * Generated from protobuf enum <code>TYPE_BOOL = 8;</code>
-     */
-    const TYPE_BOOL = 8;
-    /**
-     * Field type string.
-     *
-     * Generated from protobuf enum <code>TYPE_STRING = 9;</code>
-     */
-    const TYPE_STRING = 9;
-    /**
-     * Field type group. Proto2 syntax only, and deprecated.
-     *
-     * Generated from protobuf enum <code>TYPE_GROUP = 10;</code>
-     */
-    const TYPE_GROUP = 10;
-    /**
-     * Field type message.
-     *
-     * Generated from protobuf enum <code>TYPE_MESSAGE = 11;</code>
-     */
-    const TYPE_MESSAGE = 11;
-    /**
-     * Field type bytes.
-     *
-     * Generated from protobuf enum <code>TYPE_BYTES = 12;</code>
-     */
-    const TYPE_BYTES = 12;
-    /**
-     * Field type uint32.
-     *
-     * Generated from protobuf enum <code>TYPE_UINT32 = 13;</code>
-     */
-    const TYPE_UINT32 = 13;
-    /**
-     * Field type enum.
-     *
-     * Generated from protobuf enum <code>TYPE_ENUM = 14;</code>
-     */
-    const TYPE_ENUM = 14;
-    /**
-     * Field type sfixed32.
-     *
-     * Generated from protobuf enum <code>TYPE_SFIXED32 = 15;</code>
-     */
-    const TYPE_SFIXED32 = 15;
-    /**
-     * Field type sfixed64.
-     *
-     * Generated from protobuf enum <code>TYPE_SFIXED64 = 16;</code>
-     */
-    const TYPE_SFIXED64 = 16;
-    /**
-     * Field type sint32.
-     *
-     * Generated from protobuf enum <code>TYPE_SINT32 = 17;</code>
-     */
-    const TYPE_SINT32 = 17;
-    /**
-     * Field type sint64.
-     *
-     * Generated from protobuf enum <code>TYPE_SINT64 = 18;</code>
-     */
-    const TYPE_SINT64 = 18;
+    class Field_Kind {}
 }
+class_exists(Field\Kind::class);
+@trigger_error('Google\Protobuf\Field_Kind is deprecated and will be removed in the next major release. Use Google\Protobuf\Field\Kind instead', E_USER_DEPRECATED);
 
diff --git a/php/src/Google/Protobuf/FloatValue.php b/php/src/Google/Protobuf/FloatValue.php
index 68787ef..47ba52e 100644
--- a/php/src/Google/Protobuf/FloatValue.php
+++ b/php/src/Google/Protobuf/FloatValue.php
@@ -23,9 +23,19 @@
      */
     private $value = 0.0;
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type float $value
+     *           The float value.
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Google\Protobuf\Wrappers::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**
diff --git a/php/src/Google/Protobuf/GPBEmpty.php b/php/src/Google/Protobuf/GPBEmpty.php
index 24a93f9..2de9c3b 100644
--- a/php/src/Google/Protobuf/GPBEmpty.php
+++ b/php/src/Google/Protobuf/GPBEmpty.php
@@ -22,9 +22,17 @@
 class GPBEmpty extends \Google\Protobuf\Internal\Message
 {
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Google\Protobuf\GPBEmpty::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
 }
diff --git a/php/src/Google/Protobuf/Int32Value.php b/php/src/Google/Protobuf/Int32Value.php
index d48aff1..d7fd528 100644
--- a/php/src/Google/Protobuf/Int32Value.php
+++ b/php/src/Google/Protobuf/Int32Value.php
@@ -23,9 +23,19 @@
      */
     private $value = 0;
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type int $value
+     *           The int32 value.
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Google\Protobuf\Wrappers::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**
diff --git a/php/src/Google/Protobuf/Int64Value.php b/php/src/Google/Protobuf/Int64Value.php
index a6fb9c5..ca66305 100644
--- a/php/src/Google/Protobuf/Int64Value.php
+++ b/php/src/Google/Protobuf/Int64Value.php
@@ -23,9 +23,19 @@
      */
     private $value = 0;
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type int|string $value
+     *           The int64 value.
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Google\Protobuf\Wrappers::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**
diff --git a/php/src/Google/Protobuf/Internal/DescriptorProto.php b/php/src/Google/Protobuf/Internal/DescriptorProto.php
index 4676269..3b215d5 100644
--- a/php/src/Google/Protobuf/Internal/DescriptorProto.php
+++ b/php/src/Google/Protobuf/Internal/DescriptorProto.php
@@ -82,10 +82,10 @@
      *     @type \Google\Protobuf\Internal\FieldDescriptorProto[]|\Google\Protobuf\Internal\RepeatedField $extension
      *     @type \Google\Protobuf\Internal\DescriptorProto[]|\Google\Protobuf\Internal\RepeatedField $nested_type
      *     @type \Google\Protobuf\Internal\EnumDescriptorProto[]|\Google\Protobuf\Internal\RepeatedField $enum_type
-     *     @type \Google\Protobuf\Internal\DescriptorProto_ExtensionRange[]|\Google\Protobuf\Internal\RepeatedField $extension_range
+     *     @type \Google\Protobuf\Internal\DescriptorProto\ExtensionRange[]|\Google\Protobuf\Internal\RepeatedField $extension_range
      *     @type \Google\Protobuf\Internal\OneofDescriptorProto[]|\Google\Protobuf\Internal\RepeatedField $oneof_decl
      *     @type \Google\Protobuf\Internal\MessageOptions $options
-     *     @type \Google\Protobuf\Internal\DescriptorProto_ReservedRange[]|\Google\Protobuf\Internal\RepeatedField $reserved_range
+     *     @type \Google\Protobuf\Internal\DescriptorProto\ReservedRange[]|\Google\Protobuf\Internal\RepeatedField $reserved_range
      *     @type string[]|\Google\Protobuf\Internal\RepeatedField $reserved_name
      *           Reserved field names, which may not be used by fields in the same message.
      *           A given name may only be reserved once.
@@ -247,12 +247,12 @@
 
     /**
      * Generated from protobuf field <code>repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5;</code>
-     * @param \Google\Protobuf\Internal\DescriptorProto_ExtensionRange[]|\Google\Protobuf\Internal\RepeatedField $var
+     * @param \Google\Protobuf\Internal\DescriptorProto\ExtensionRange[]|\Google\Protobuf\Internal\RepeatedField $var
      * @return $this
      */
     public function setExtensionRange($var)
     {
-        $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\DescriptorProto_ExtensionRange::class);
+        $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\DescriptorProto\ExtensionRange::class);
         $this->extension_range = $arr;
         $this->has_extension_range = true;
 
@@ -331,12 +331,12 @@
 
     /**
      * Generated from protobuf field <code>repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9;</code>
-     * @param \Google\Protobuf\Internal\DescriptorProto_ReservedRange[]|\Google\Protobuf\Internal\RepeatedField $var
+     * @param \Google\Protobuf\Internal\DescriptorProto\ReservedRange[]|\Google\Protobuf\Internal\RepeatedField $var
      * @return $this
      */
     public function setReservedRange($var)
     {
-        $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\DescriptorProto_ReservedRange::class);
+        $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\DescriptorProto\ReservedRange::class);
         $this->reserved_range = $arr;
         $this->has_reserved_range = true;
 
diff --git a/php/src/Google/Protobuf/Internal/DescriptorProto_ExtensionRange.php b/php/src/Google/Protobuf/Internal/DescriptorProto/ExtensionRange.php
similarity index 91%
rename from php/src/Google/Protobuf/Internal/DescriptorProto_ExtensionRange.php
rename to php/src/Google/Protobuf/Internal/DescriptorProto/ExtensionRange.php
index d926ee6..c06a0a6 100644
--- a/php/src/Google/Protobuf/Internal/DescriptorProto_ExtensionRange.php
+++ b/php/src/Google/Protobuf/Internal/DescriptorProto/ExtensionRange.php
@@ -2,7 +2,7 @@
 # Generated by the protocol buffer compiler.  DO NOT EDIT!
 # source: google/protobuf/descriptor.proto
 
-namespace Google\Protobuf\Internal;
+namespace Google\Protobuf\Internal\DescriptorProto;
 
 use Google\Protobuf\Internal\GPBType;
 use Google\Protobuf\Internal\GPBWire;
@@ -13,7 +13,7 @@
 /**
  * Generated from protobuf message <code>google.protobuf.DescriptorProto.ExtensionRange</code>
  */
-class DescriptorProto_ExtensionRange extends \Google\Protobuf\Internal\Message
+class ExtensionRange extends \Google\Protobuf\Internal\Message
 {
     /**
      * Generated from protobuf field <code>optional int32 start = 1;</code>
@@ -133,3 +133,6 @@
 
 }
 
+// Adding a class alias for backwards compatibility with the previous class name.
+class_alias(ExtensionRange::class, \Google\Protobuf\Internal\DescriptorProto_ExtensionRange::class);
+
diff --git a/php/src/Google/Protobuf/Internal/DescriptorProto_ReservedRange.php b/php/src/Google/Protobuf/Internal/DescriptorProto/ReservedRange.php
similarity index 89%
rename from php/src/Google/Protobuf/Internal/DescriptorProto_ReservedRange.php
rename to php/src/Google/Protobuf/Internal/DescriptorProto/ReservedRange.php
index 302eaaa..73c964f 100644
--- a/php/src/Google/Protobuf/Internal/DescriptorProto_ReservedRange.php
+++ b/php/src/Google/Protobuf/Internal/DescriptorProto/ReservedRange.php
@@ -2,7 +2,7 @@
 # Generated by the protocol buffer compiler.  DO NOT EDIT!
 # source: google/protobuf/descriptor.proto
 
-namespace Google\Protobuf\Internal;
+namespace Google\Protobuf\Internal\DescriptorProto;
 
 use Google\Protobuf\Internal\GPBType;
 use Google\Protobuf\Internal\GPBWire;
@@ -17,7 +17,7 @@
  *
  * Generated from protobuf message <code>google.protobuf.DescriptorProto.ReservedRange</code>
  */
-class DescriptorProto_ReservedRange extends \Google\Protobuf\Internal\Message
+class ReservedRange extends \Google\Protobuf\Internal\Message
 {
     /**
      * Inclusive.
@@ -117,3 +117,6 @@
 
 }
 
+// Adding a class alias for backwards compatibility with the previous class name.
+class_alias(ReservedRange::class, \Google\Protobuf\Internal\DescriptorProto_ReservedRange::class);
+
diff --git a/php/src/Google/Protobuf/Internal/EnumDescriptorProto.php b/php/src/Google/Protobuf/Internal/EnumDescriptorProto.php
index 406bb5b..da30fa9 100644
--- a/php/src/Google/Protobuf/Internal/EnumDescriptorProto.php
+++ b/php/src/Google/Protobuf/Internal/EnumDescriptorProto.php
@@ -59,7 +59,7 @@
      *     @type string $name
      *     @type \Google\Protobuf\Internal\EnumValueDescriptorProto[]|\Google\Protobuf\Internal\RepeatedField $value
      *     @type \Google\Protobuf\Internal\EnumOptions $options
-     *     @type \Google\Protobuf\Internal\EnumDescriptorProto_EnumReservedRange[]|\Google\Protobuf\Internal\RepeatedField $reserved_range
+     *     @type \Google\Protobuf\Internal\EnumDescriptorProto\EnumReservedRange[]|\Google\Protobuf\Internal\RepeatedField $reserved_range
      *           Range of reserved numeric values. Reserved numeric values may not be used
      *           by enum values in the same enum declaration. Reserved ranges may not
      *           overlap.
@@ -176,12 +176,12 @@
      * overlap.
      *
      * Generated from protobuf field <code>repeated .google.protobuf.EnumDescriptorProto.EnumReservedRange reserved_range = 4;</code>
-     * @param \Google\Protobuf\Internal\EnumDescriptorProto_EnumReservedRange[]|\Google\Protobuf\Internal\RepeatedField $var
+     * @param \Google\Protobuf\Internal\EnumDescriptorProto\EnumReservedRange[]|\Google\Protobuf\Internal\RepeatedField $var
      * @return $this
      */
     public function setReservedRange($var)
     {
-        $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\EnumDescriptorProto_EnumReservedRange::class);
+        $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\EnumDescriptorProto\EnumReservedRange::class);
         $this->reserved_range = $arr;
         $this->has_reserved_range = true;
 
diff --git a/php/src/Google/Protobuf/Internal/EnumDescriptorProto_EnumReservedRange.php b/php/src/Google/Protobuf/Internal/EnumDescriptorProto/EnumReservedRange.php
similarity index 89%
rename from php/src/Google/Protobuf/Internal/EnumDescriptorProto_EnumReservedRange.php
rename to php/src/Google/Protobuf/Internal/EnumDescriptorProto/EnumReservedRange.php
index 3d7b008..e107958 100644
--- a/php/src/Google/Protobuf/Internal/EnumDescriptorProto_EnumReservedRange.php
+++ b/php/src/Google/Protobuf/Internal/EnumDescriptorProto/EnumReservedRange.php
@@ -2,7 +2,7 @@
 # Generated by the protocol buffer compiler.  DO NOT EDIT!
 # source: google/protobuf/descriptor.proto
 
-namespace Google\Protobuf\Internal;
+namespace Google\Protobuf\Internal\EnumDescriptorProto;
 
 use Google\Protobuf\Internal\GPBType;
 use Google\Protobuf\Internal\GPBWire;
@@ -19,7 +19,7 @@
  *
  * Generated from protobuf message <code>google.protobuf.EnumDescriptorProto.EnumReservedRange</code>
  */
-class EnumDescriptorProto_EnumReservedRange extends \Google\Protobuf\Internal\Message
+class EnumReservedRange extends \Google\Protobuf\Internal\Message
 {
     /**
      * Inclusive.
@@ -119,3 +119,6 @@
 
 }
 
+// Adding a class alias for backwards compatibility with the previous class name.
+class_alias(EnumReservedRange::class, \Google\Protobuf\Internal\EnumDescriptorProto_EnumReservedRange::class);
+
diff --git a/php/src/Google/Protobuf/Internal/FieldDescriptorProto_Label.php b/php/src/Google/Protobuf/Internal/FieldDescriptorProto/Label.php
similarity index 61%
rename from php/src/Google/Protobuf/Internal/FieldDescriptorProto_Label.php
rename to php/src/Google/Protobuf/Internal/FieldDescriptorProto/Label.php
index f2a32fd..b105088 100644
--- a/php/src/Google/Protobuf/Internal/FieldDescriptorProto_Label.php
+++ b/php/src/Google/Protobuf/Internal/FieldDescriptorProto/Label.php
@@ -2,12 +2,12 @@
 # Generated by the protocol buffer compiler.  DO NOT EDIT!
 # source: google/protobuf/descriptor.proto
 
-namespace Google\Protobuf\Internal;
+namespace Google\Protobuf\Internal\FieldDescriptorProto;
 
 /**
- * Protobuf enum <code>Google\Protobuf\Internal</code>
+ * Protobuf type <code>google.protobuf.FieldDescriptorProto.Label</code>
  */
-class FieldDescriptorProto_Label
+class Label
 {
     /**
      * 0 is reserved for errors
@@ -25,3 +25,6 @@
     const LABEL_REPEATED = 3;
 }
 
+// Adding a class alias for backwards compatibility with the previous class name.
+class_alias(Label::class, \Google\Protobuf\Internal\FieldDescriptorProto_Label::class);
+
diff --git a/php/src/Google/Protobuf/Internal/FieldDescriptorProto_Type.php b/php/src/Google/Protobuf/Internal/FieldDescriptorProto/Type.php
similarity index 89%
rename from php/src/Google/Protobuf/Internal/FieldDescriptorProto_Type.php
rename to php/src/Google/Protobuf/Internal/FieldDescriptorProto/Type.php
index 1b022de..ea228a7 100644
--- a/php/src/Google/Protobuf/Internal/FieldDescriptorProto_Type.php
+++ b/php/src/Google/Protobuf/Internal/FieldDescriptorProto/Type.php
@@ -2,12 +2,12 @@
 # Generated by the protocol buffer compiler.  DO NOT EDIT!
 # source: google/protobuf/descriptor.proto
 
-namespace Google\Protobuf\Internal;
+namespace Google\Protobuf\Internal\FieldDescriptorProto;
 
 /**
- * Protobuf enum <code>Google\Protobuf\Internal</code>
+ * Protobuf type <code>google.protobuf.FieldDescriptorProto.Type</code>
  */
-class FieldDescriptorProto_Type
+class Type
 {
     /**
      * 0 is reserved for errors.
@@ -105,3 +105,6 @@
     const TYPE_SINT64 = 18;
 }
 
+// Adding a class alias for backwards compatibility with the previous class name.
+class_alias(Type::class, \Google\Protobuf\Internal\FieldDescriptorProto_Type::class);
+
diff --git a/php/src/Google/Protobuf/Internal/FieldOptions_CType.php b/php/src/Google/Protobuf/Internal/FieldOptions/CType.php
similarity index 60%
rename from php/src/Google/Protobuf/Internal/FieldOptions_CType.php
rename to php/src/Google/Protobuf/Internal/FieldOptions/CType.php
index 0f33072..016197a 100644
--- a/php/src/Google/Protobuf/Internal/FieldOptions_CType.php
+++ b/php/src/Google/Protobuf/Internal/FieldOptions/CType.php
@@ -2,12 +2,12 @@
 # Generated by the protocol buffer compiler.  DO NOT EDIT!
 # source: google/protobuf/descriptor.proto
 
-namespace Google\Protobuf\Internal;
+namespace Google\Protobuf\Internal\FieldOptions;
 
 /**
- * Protobuf enum <code>Google\Protobuf\Internal</code>
+ * Protobuf type <code>google.protobuf.FieldOptions.CType</code>
  */
-class FieldOptions_CType
+class CType
 {
     /**
      * Default mode.
@@ -25,3 +25,6 @@
     const STRING_PIECE = 2;
 }
 
+// Adding a class alias for backwards compatibility with the previous class name.
+class_alias(CType::class, \Google\Protobuf\Internal\FieldOptions_CType::class);
+
diff --git a/php/src/Google/Protobuf/Internal/FieldOptions_JSType.php b/php/src/Google/Protobuf/Internal/FieldOptions/JSType.php
similarity index 64%
rename from php/src/Google/Protobuf/Internal/FieldOptions_JSType.php
rename to php/src/Google/Protobuf/Internal/FieldOptions/JSType.php
index 73bdf3f..f7b78a1 100644
--- a/php/src/Google/Protobuf/Internal/FieldOptions_JSType.php
+++ b/php/src/Google/Protobuf/Internal/FieldOptions/JSType.php
@@ -2,12 +2,12 @@
 # Generated by the protocol buffer compiler.  DO NOT EDIT!
 # source: google/protobuf/descriptor.proto
 
-namespace Google\Protobuf\Internal;
+namespace Google\Protobuf\Internal\FieldOptions;
 
 /**
- * Protobuf enum <code>Google\Protobuf\Internal</code>
+ * Protobuf type <code>google.protobuf.FieldOptions.JSType</code>
  */
-class FieldOptions_JSType
+class JSType
 {
     /**
      * Use the default type.
@@ -29,3 +29,6 @@
     const JS_NUMBER = 2;
 }
 
+// Adding a class alias for backwards compatibility with the previous class name.
+class_alias(JSType::class, \Google\Protobuf\Internal\FieldOptions_JSType::class);
+
diff --git a/php/src/Google/Protobuf/Internal/FileOptions.php b/php/src/Google/Protobuf/Internal/FileOptions.php
index 2315ed5..c6b36bb 100644
--- a/php/src/Google/Protobuf/Internal/FileOptions.php
+++ b/php/src/Google/Protobuf/Internal/FileOptions.php
@@ -278,6 +278,14 @@
      *           Use this option to change the namespace of php generated classes. Default
      *           is empty. When this option is empty, the package name will be used for
      *           determining the namespace.
+     *     @type string $php_metadata_namespace
+     *           Use this option to change the namespace of php generated metadata classes.
+     *           Default is empty. When this option is empty, the proto file name will be used
+     *           for determining the namespace.
+     *     @type string $ruby_package
+     *           Use this option to change the package of ruby generated classes. Default
+     *           is empty. When this option is not set, the package name will be used for
+     *           determining the ruby package.
      *     @type \Google\Protobuf\Internal\UninterpretedOption[]|\Google\Protobuf\Internal\RepeatedField $uninterpreted_option
      *           The parser stores options it doesn't recognize here.
      *           See the documentation for the "Options" section above.
diff --git a/php/src/Google/Protobuf/Internal/FileOptions_OptimizeMode.php b/php/src/Google/Protobuf/Internal/FileOptions/OptimizeMode.php
similarity index 67%
rename from php/src/Google/Protobuf/Internal/FileOptions_OptimizeMode.php
rename to php/src/Google/Protobuf/Internal/FileOptions/OptimizeMode.php
index 4dd56ef..3dd60bf 100644
--- a/php/src/Google/Protobuf/Internal/FileOptions_OptimizeMode.php
+++ b/php/src/Google/Protobuf/Internal/FileOptions/OptimizeMode.php
@@ -2,14 +2,14 @@
 # Generated by the protocol buffer compiler.  DO NOT EDIT!
 # source: google/protobuf/descriptor.proto
 
-namespace Google\Protobuf\Internal;
+namespace Google\Protobuf\Internal\FileOptions;
 
 /**
  * Generated classes can be optimized for speed or code size.
  *
- * Protobuf enum <code>Google\Protobuf\Internal</code>
+ * Protobuf type <code>google.protobuf.FileOptions.OptimizeMode</code>
  */
-class FileOptions_OptimizeMode
+class OptimizeMode
 {
     /**
      * Generate complete code for parsing, serialization,
@@ -31,3 +31,6 @@
     const LITE_RUNTIME = 3;
 }
 
+// Adding a class alias for backwards compatibility with the previous class name.
+class_alias(OptimizeMode::class, \Google\Protobuf\Internal\FileOptions_OptimizeMode::class);
+
diff --git a/php/src/Google/Protobuf/Internal/GPBUtil.php b/php/src/Google/Protobuf/Internal/GPBUtil.php
index 05d5c39..023b07f 100644
--- a/php/src/Google/Protobuf/Internal/GPBUtil.php
+++ b/php/src/Google/Protobuf/Internal/GPBUtil.php
@@ -191,7 +191,7 @@
         $var = boolval($var);
     }
 
-    public static function checkMessage(&$var, $klass)
+    public static function checkMessage(&$var, $klass, $newClass = null)
     {
         if (!$var instanceof $klass && !is_null($var)) {
             throw new \Exception("Expect $klass.");
@@ -303,8 +303,11 @@
         $name,
         $file_proto)
     {
-        $classname = implode('_', explode('.', $name));
-        return static::getClassNamePrefix($classname, $file_proto) . $classname;
+        $parts = explode('.', $name);
+        foreach ($parts as $i => $part) {
+            $parts[$i] = static::getClassNamePrefix($parts[$i], $file_proto) . $parts[$i];
+        }
+        return implode('\\', $parts);
     }
 
     public static function getFullClassName(
@@ -347,9 +350,14 @@
         if ($package === "") {
             $classname = $class_name_without_package;
         } else {
+            $parts = array_map('ucwords', explode('.', $package));
+            foreach ($parts as $i => $part) {
+                $parts[$i] = self::getClassNamePrefix($part, $file_proto).$part;
+            }
             $classname =
-                implode('\\', array_map('ucwords', explode('.', $package))).
-                "\\".$class_name_without_package;
+                implode('\\', $parts) .
+                "\\".self::getClassNamePrefix($class_name_without_package,$file_proto).
+                $class_name_without_package;
         }
     }
 
diff --git a/php/src/Google/Protobuf/Internal/GeneratedCodeInfo.php b/php/src/Google/Protobuf/Internal/GeneratedCodeInfo.php
index c2b41a2..f5a65be 100644
--- a/php/src/Google/Protobuf/Internal/GeneratedCodeInfo.php
+++ b/php/src/Google/Protobuf/Internal/GeneratedCodeInfo.php
@@ -34,7 +34,7 @@
      * @param array $data {
      *     Optional. Data for populating the Message object.
      *
-     *     @type \Google\Protobuf\Internal\GeneratedCodeInfo_Annotation[]|\Google\Protobuf\Internal\RepeatedField $annotation
+     *     @type \Google\Protobuf\Internal\GeneratedCodeInfo\Annotation[]|\Google\Protobuf\Internal\RepeatedField $annotation
      *           An Annotation connects some span of text in generated code to an element
      *           of its generating .proto file.
      * }
@@ -61,12 +61,12 @@
      * of its generating .proto file.
      *
      * Generated from protobuf field <code>repeated .google.protobuf.GeneratedCodeInfo.Annotation annotation = 1;</code>
-     * @param \Google\Protobuf\Internal\GeneratedCodeInfo_Annotation[]|\Google\Protobuf\Internal\RepeatedField $var
+     * @param \Google\Protobuf\Internal\GeneratedCodeInfo\Annotation[]|\Google\Protobuf\Internal\RepeatedField $var
      * @return $this
      */
     public function setAnnotation($var)
     {
-        $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\GeneratedCodeInfo_Annotation::class);
+        $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\GeneratedCodeInfo\Annotation::class);
         $this->annotation = $arr;
         $this->has_annotation = true;
 
diff --git a/php/src/Google/Protobuf/Internal/GeneratedCodeInfo_Annotation.php b/php/src/Google/Protobuf/Internal/GeneratedCodeInfo/Annotation.php
similarity index 94%
rename from php/src/Google/Protobuf/Internal/GeneratedCodeInfo_Annotation.php
rename to php/src/Google/Protobuf/Internal/GeneratedCodeInfo/Annotation.php
index 7518200..09f958d 100644
--- a/php/src/Google/Protobuf/Internal/GeneratedCodeInfo_Annotation.php
+++ b/php/src/Google/Protobuf/Internal/GeneratedCodeInfo/Annotation.php
@@ -2,7 +2,7 @@
 # Generated by the protocol buffer compiler.  DO NOT EDIT!
 # source: google/protobuf/descriptor.proto
 
-namespace Google\Protobuf\Internal;
+namespace Google\Protobuf\Internal\GeneratedCodeInfo;
 
 use Google\Protobuf\Internal\GPBType;
 use Google\Protobuf\Internal\GPBWire;
@@ -13,7 +13,7 @@
 /**
  * Generated from protobuf message <code>google.protobuf.GeneratedCodeInfo.Annotation</code>
  */
-class GeneratedCodeInfo_Annotation extends \Google\Protobuf\Internal\Message
+class Annotation extends \Google\Protobuf\Internal\Message
 {
     /**
      * Identifies the element in the original source .proto file. This field
@@ -211,3 +211,6 @@
 
 }
 
+// Adding a class alias for backwards compatibility with the previous class name.
+class_alias(Annotation::class, \Google\Protobuf\Internal\GeneratedCodeInfo_Annotation::class);
+
diff --git a/php/src/Google/Protobuf/Internal/MethodOptions_IdempotencyLevel.php b/php/src/Google/Protobuf/Internal/MethodOptions/IdempotencyLevel.php
similarity index 69%
rename from php/src/Google/Protobuf/Internal/MethodOptions_IdempotencyLevel.php
rename to php/src/Google/Protobuf/Internal/MethodOptions/IdempotencyLevel.php
index 9e06d8e..dcc30e2 100644
--- a/php/src/Google/Protobuf/Internal/MethodOptions_IdempotencyLevel.php
+++ b/php/src/Google/Protobuf/Internal/MethodOptions/IdempotencyLevel.php
@@ -2,16 +2,16 @@
 # Generated by the protocol buffer compiler.  DO NOT EDIT!
 # source: google/protobuf/descriptor.proto
 
-namespace Google\Protobuf\Internal;
+namespace Google\Protobuf\Internal\MethodOptions;
 
 /**
  * Is this method side-effect-free (or safe in HTTP parlance), or idempotent,
  * or neither? HTTP based RPC implementation may choose GET verb for safe
  * methods, and PUT verb for idempotent methods instead of the default POST.
  *
- * Protobuf enum <code>Google\Protobuf\Internal</code>
+ * Protobuf type <code>google.protobuf.MethodOptions.IdempotencyLevel</code>
  */
-class MethodOptions_IdempotencyLevel
+class IdempotencyLevel
 {
     /**
      * Generated from protobuf enum <code>IDEMPOTENCY_UNKNOWN = 0;</code>
@@ -31,3 +31,6 @@
     const IDEMPOTENT = 2;
 }
 
+// Adding a class alias for backwards compatibility with the previous class name.
+class_alias(IdempotencyLevel::class, \Google\Protobuf\Internal\MethodOptions_IdempotencyLevel::class);
+
diff --git a/php/src/Google/Protobuf/Internal/SourceCodeInfo.php b/php/src/Google/Protobuf/Internal/SourceCodeInfo.php
index 2305a79..6e413f7 100644
--- a/php/src/Google/Protobuf/Internal/SourceCodeInfo.php
+++ b/php/src/Google/Protobuf/Internal/SourceCodeInfo.php
@@ -72,7 +72,7 @@
      * @param array $data {
      *     Optional. Data for populating the Message object.
      *
-     *     @type \Google\Protobuf\Internal\SourceCodeInfo_Location[]|\Google\Protobuf\Internal\RepeatedField $location
+     *     @type \Google\Protobuf\Internal\SourceCodeInfo\Location[]|\Google\Protobuf\Internal\RepeatedField $location
      *           A Location identifies a piece of source code in a .proto file which
      *           corresponds to a particular definition.  This information is intended
      *           to be useful to IDEs, code indexers, documentation generators, and similar
@@ -216,12 +216,12 @@
      *   be recorded in the future.
      *
      * Generated from protobuf field <code>repeated .google.protobuf.SourceCodeInfo.Location location = 1;</code>
-     * @param \Google\Protobuf\Internal\SourceCodeInfo_Location[]|\Google\Protobuf\Internal\RepeatedField $var
+     * @param \Google\Protobuf\Internal\SourceCodeInfo\Location[]|\Google\Protobuf\Internal\RepeatedField $var
      * @return $this
      */
     public function setLocation($var)
     {
-        $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\SourceCodeInfo_Location::class);
+        $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\SourceCodeInfo\Location::class);
         $this->location = $arr;
         $this->has_location = true;
 
diff --git a/php/src/Google/Protobuf/Internal/SourceCodeInfo_Location.php b/php/src/Google/Protobuf/Internal/SourceCodeInfo/Location.php
similarity index 97%
rename from php/src/Google/Protobuf/Internal/SourceCodeInfo_Location.php
rename to php/src/Google/Protobuf/Internal/SourceCodeInfo/Location.php
index f930aac..bad247a 100644
--- a/php/src/Google/Protobuf/Internal/SourceCodeInfo_Location.php
+++ b/php/src/Google/Protobuf/Internal/SourceCodeInfo/Location.php
@@ -2,7 +2,7 @@
 # Generated by the protocol buffer compiler.  DO NOT EDIT!
 # source: google/protobuf/descriptor.proto
 
-namespace Google\Protobuf\Internal;
+namespace Google\Protobuf\Internal\SourceCodeInfo;
 
 use Google\Protobuf\Internal\GPBType;
 use Google\Protobuf\Internal\GPBWire;
@@ -13,7 +13,7 @@
 /**
  * Generated from protobuf message <code>google.protobuf.SourceCodeInfo.Location</code>
  */
-class SourceCodeInfo_Location extends \Google\Protobuf\Internal\Message
+class Location extends \Google\Protobuf\Internal\Message
 {
     /**
      * Identifies which part of the FileDescriptorProto was defined at this
@@ -458,3 +458,6 @@
 
 }
 
+// Adding a class alias for backwards compatibility with the previous class name.
+class_alias(Location::class, \Google\Protobuf\Internal\SourceCodeInfo_Location::class);
+
diff --git a/php/src/Google/Protobuf/Internal/UninterpretedOption.php b/php/src/Google/Protobuf/Internal/UninterpretedOption.php
index 36a1868..3b517ec 100644
--- a/php/src/Google/Protobuf/Internal/UninterpretedOption.php
+++ b/php/src/Google/Protobuf/Internal/UninterpretedOption.php
@@ -67,7 +67,7 @@
      * @param array $data {
      *     Optional. Data for populating the Message object.
      *
-     *     @type \Google\Protobuf\Internal\UninterpretedOption_NamePart[]|\Google\Protobuf\Internal\RepeatedField $name
+     *     @type \Google\Protobuf\Internal\UninterpretedOption\NamePart[]|\Google\Protobuf\Internal\RepeatedField $name
      *     @type string $identifier_value
      *           The value of the uninterpreted option, in whatever type the tokenizer
      *           identified it as during parsing. Exactly one of these should be set.
@@ -94,12 +94,12 @@
 
     /**
      * Generated from protobuf field <code>repeated .google.protobuf.UninterpretedOption.NamePart name = 2;</code>
-     * @param \Google\Protobuf\Internal\UninterpretedOption_NamePart[]|\Google\Protobuf\Internal\RepeatedField $var
+     * @param \Google\Protobuf\Internal\UninterpretedOption\NamePart[]|\Google\Protobuf\Internal\RepeatedField $var
      * @return $this
      */
     public function setName($var)
     {
-        $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\UninterpretedOption_NamePart::class);
+        $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\UninterpretedOption\NamePart::class);
         $this->name = $arr;
         $this->has_name = true;
 
diff --git a/php/src/Google/Protobuf/Internal/UninterpretedOption_NamePart.php b/php/src/Google/Protobuf/Internal/UninterpretedOption/NamePart.php
similarity index 89%
rename from php/src/Google/Protobuf/Internal/UninterpretedOption_NamePart.php
rename to php/src/Google/Protobuf/Internal/UninterpretedOption/NamePart.php
index d4369fd..92ee4b4 100644
--- a/php/src/Google/Protobuf/Internal/UninterpretedOption_NamePart.php
+++ b/php/src/Google/Protobuf/Internal/UninterpretedOption/NamePart.php
@@ -2,7 +2,7 @@
 # Generated by the protocol buffer compiler.  DO NOT EDIT!
 # source: google/protobuf/descriptor.proto
 
-namespace Google\Protobuf\Internal;
+namespace Google\Protobuf\Internal\UninterpretedOption;
 
 use Google\Protobuf\Internal\GPBType;
 use Google\Protobuf\Internal\GPBWire;
@@ -19,7 +19,7 @@
  *
  * Generated from protobuf message <code>google.protobuf.UninterpretedOption.NamePart</code>
  */
-class UninterpretedOption_NamePart extends \Google\Protobuf\Internal\Message
+class NamePart extends \Google\Protobuf\Internal\Message
 {
     /**
      * Generated from protobuf field <code>required string name_part = 1;</code>
@@ -105,3 +105,6 @@
 
 }
 
+// Adding a class alias for backwards compatibility with the previous class name.
+class_alias(NamePart::class, \Google\Protobuf\Internal\UninterpretedOption_NamePart::class);
+
diff --git a/php/src/Google/Protobuf/ListValue.php b/php/src/Google/Protobuf/ListValue.php
index 12552ef..70f5423 100644
--- a/php/src/Google/Protobuf/ListValue.php
+++ b/php/src/Google/Protobuf/ListValue.php
@@ -23,9 +23,19 @@
      */
     private $values;
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type \Google\Protobuf\Value[]|\Google\Protobuf\Internal\RepeatedField $values
+     *           Repeated field of dynamically typed values.
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Google\Protobuf\Struct::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**
diff --git a/php/src/Google/Protobuf/Method.php b/php/src/Google/Protobuf/Method.php
index f55cb76..8e80350 100644
--- a/php/src/Google/Protobuf/Method.php
+++ b/php/src/Google/Protobuf/Method.php
@@ -58,9 +58,31 @@
      */
     private $syntax = 0;
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type string $name
+     *           The simple name of this method.
+     *     @type string $request_type_url
+     *           A URL of the input message type.
+     *     @type bool $request_streaming
+     *           If true, the request is streamed.
+     *     @type string $response_type_url
+     *           The URL of the output message type.
+     *     @type bool $response_streaming
+     *           If true, the response is streamed.
+     *     @type \Google\Protobuf\Option[]|\Google\Protobuf\Internal\RepeatedField $options
+     *           Any metadata attached to the method.
+     *     @type int $syntax
+     *           The source syntax of this method.
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Google\Protobuf\Api::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**
diff --git a/php/src/Google/Protobuf/Mixin.php b/php/src/Google/Protobuf/Mixin.php
index eb5117e..a2ea59c 100644
--- a/php/src/Google/Protobuf/Mixin.php
+++ b/php/src/Google/Protobuf/Mixin.php
@@ -90,9 +90,22 @@
      */
     private $root = '';
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type string $name
+     *           The fully qualified name of the interface which is included.
+     *     @type string $root
+     *           If non-empty specifies a path under which inherited HTTP paths
+     *           are rooted.
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Google\Protobuf\Api::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**
diff --git a/php/src/Google/Protobuf/NullValue.php b/php/src/Google/Protobuf/NullValue.php
index d4022cc..482b80d 100644
--- a/php/src/Google/Protobuf/NullValue.php
+++ b/php/src/Google/Protobuf/NullValue.php
@@ -9,7 +9,7 @@
  * `Value` type union.
  *  The JSON representation for `NullValue` is JSON `null`.
  *
- * Protobuf enum <code>Google\Protobuf\NullValue</code>
+ * Protobuf type <code>google.protobuf.NullValue</code>
  */
 class NullValue
 {
diff --git a/php/src/Google/Protobuf/Option.php b/php/src/Google/Protobuf/Option.php
index f803868..22ecfc5 100644
--- a/php/src/Google/Protobuf/Option.php
+++ b/php/src/Google/Protobuf/Option.php
@@ -35,9 +35,27 @@
      */
     private $value = null;
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type string $name
+     *           The option's name. For protobuf built-in options (options defined in
+     *           descriptor.proto), this is the short name. For example, `"map_entry"`.
+     *           For custom options, it should be the fully-qualified name. For example,
+     *           `"google.api.http"`.
+     *     @type \Google\Protobuf\Any $value
+     *           The option's value packed in an Any message. If the value is a primitive,
+     *           the corresponding wrapper type defined in google/protobuf/wrappers.proto
+     *           should be used. If the value is an enum, it should be stored as an int32
+     *           value using the google.protobuf.Int32Value type.
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Google\Protobuf\Type::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**
diff --git a/php/src/Google/Protobuf/SourceContext.php b/php/src/Google/Protobuf/SourceContext.php
index 07d90c6..cbc50c6 100644
--- a/php/src/Google/Protobuf/SourceContext.php
+++ b/php/src/Google/Protobuf/SourceContext.php
@@ -24,9 +24,20 @@
      */
     private $file_name = '';
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type string $file_name
+     *           The path-qualified name of the .proto file that contained the associated
+     *           protobuf element.  For example: `"google/protobuf/source_context.proto"`.
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Google\Protobuf\SourceContext::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**
diff --git a/php/src/Google/Protobuf/StringValue.php b/php/src/Google/Protobuf/StringValue.php
index f6bcc48..8fb354f 100644
--- a/php/src/Google/Protobuf/StringValue.php
+++ b/php/src/Google/Protobuf/StringValue.php
@@ -23,9 +23,19 @@
      */
     private $value = '';
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type string $value
+     *           The string value.
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Google\Protobuf\Wrappers::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**
diff --git a/php/src/Google/Protobuf/Struct.php b/php/src/Google/Protobuf/Struct.php
index 721e991..0456541 100644
--- a/php/src/Google/Protobuf/Struct.php
+++ b/php/src/Google/Protobuf/Struct.php
@@ -28,9 +28,19 @@
      */
     private $fields;
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type array|\Google\Protobuf\Internal\MapField $fields
+     *           Unordered map of dynamically typed values.
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Google\Protobuf\Struct::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**
diff --git a/php/src/Google/Protobuf/Syntax.php b/php/src/Google/Protobuf/Syntax.php
index bb7b789..3a52dc9 100644
--- a/php/src/Google/Protobuf/Syntax.php
+++ b/php/src/Google/Protobuf/Syntax.php
@@ -7,7 +7,7 @@
 /**
  * The syntax in which a protocol buffer element is defined.
  *
- * Protobuf enum <code>Google\Protobuf\Syntax</code>
+ * Protobuf type <code>google.protobuf.Syntax</code>
  */
 class Syntax
 {
diff --git a/php/src/Google/Protobuf/Timestamp.php b/php/src/Google/Protobuf/Timestamp.php
index 9d4d58e..a793c7e 100644
--- a/php/src/Google/Protobuf/Timestamp.php
+++ b/php/src/Google/Protobuf/Timestamp.php
@@ -91,9 +91,26 @@
      */
     private $nanos = 0;
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type int|string $seconds
+     *           Represents seconds of UTC time since Unix epoch
+     *           1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to
+     *           9999-12-31T23:59:59Z inclusive.
+     *     @type int $nanos
+     *           Non-negative fractions of a second at nanosecond resolution. Negative
+     *           second values with fractions must still have non-negative nanos values
+     *           that count forward in time. Must be from 0 to 999,999,999
+     *           inclusive.
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Google\Protobuf\Timestamp::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**
@@ -158,7 +175,7 @@
         return $this;
     }
 
-    /**
+    /*
      * Converts PHP DateTime to Timestamp.
      *
      * @param \DateTime $datetime
diff --git a/php/src/Google/Protobuf/Type.php b/php/src/Google/Protobuf/Type.php
index 7dbe2ca..1b47811 100644
--- a/php/src/Google/Protobuf/Type.php
+++ b/php/src/Google/Protobuf/Type.php
@@ -52,9 +52,29 @@
      */
     private $syntax = 0;
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type string $name
+     *           The fully qualified message name.
+     *     @type \Google\Protobuf\Field[]|\Google\Protobuf\Internal\RepeatedField $fields
+     *           The list of fields.
+     *     @type string[]|\Google\Protobuf\Internal\RepeatedField $oneofs
+     *           The list of types appearing in `oneof` definitions in this type.
+     *     @type \Google\Protobuf\Option[]|\Google\Protobuf\Internal\RepeatedField $options
+     *           The protocol buffer options.
+     *     @type \Google\Protobuf\SourceContext $source_context
+     *           The source context.
+     *     @type int $syntax
+     *           The source syntax.
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Google\Protobuf\Type::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**
diff --git a/php/src/Google/Protobuf/UInt32Value.php b/php/src/Google/Protobuf/UInt32Value.php
index 61a3ddf..f5a522d 100644
--- a/php/src/Google/Protobuf/UInt32Value.php
+++ b/php/src/Google/Protobuf/UInt32Value.php
@@ -23,9 +23,19 @@
      */
     private $value = 0;
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type int $value
+     *           The uint32 value.
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Google\Protobuf\Wrappers::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**
diff --git a/php/src/Google/Protobuf/UInt64Value.php b/php/src/Google/Protobuf/UInt64Value.php
index 69f7eb8..89e69cd 100644
--- a/php/src/Google/Protobuf/UInt64Value.php
+++ b/php/src/Google/Protobuf/UInt64Value.php
@@ -23,9 +23,19 @@
      */
     private $value = 0;
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type int|string $value
+     *           The uint64 value.
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Google\Protobuf\Wrappers::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**
diff --git a/php/src/Google/Protobuf/Value.php b/php/src/Google/Protobuf/Value.php
index 052a377..5c1e864 100644
--- a/php/src/Google/Protobuf/Value.php
+++ b/php/src/Google/Protobuf/Value.php
@@ -21,9 +21,29 @@
 {
     protected $kind;
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type int $null_value
+     *           Represents a null value.
+     *     @type float $number_value
+     *           Represents a double value.
+     *     @type string $string_value
+     *           Represents a string value.
+     *     @type bool $bool_value
+     *           Represents a boolean value.
+     *     @type \Google\Protobuf\Struct $struct_value
+     *           Represents a structured value.
+     *     @type \Google\Protobuf\ListValue $list_value
+     *           Represents a repeated `Value`.
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Google\Protobuf\Struct::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**
diff --git a/php/tests/array_test.php b/php/tests/array_test.php
index 1a26d72..36a649e 100644
--- a/php/tests/array_test.php
+++ b/php/tests/array_test.php
@@ -5,7 +5,7 @@
 use Google\Protobuf\Internal\RepeatedField;
 use Google\Protobuf\Internal\GPBType;
 use Foo\TestMessage;
-use Foo\TestMessage_Sub;
+use Foo\TestMessage\Sub;
 
 class RepeatedFieldTest extends PHPUnit_Framework_TestCase
 {
@@ -456,10 +456,10 @@
 
     public function testMessage()
     {
-        $arr = new RepeatedField(GPBType::MESSAGE, TestMessage_Sub::class);
+        $arr = new RepeatedField(GPBType::MESSAGE, Sub::class);
 
         // Test append.
-        $sub_m = new TestMessage_Sub();
+        $sub_m = new Sub();
         $sub_m->setA(1);
         $arr[] = $sub_m;
         $this->assertSame(1, $arr[0]->getA());
@@ -467,15 +467,15 @@
         $this->assertEquals(1, count($arr));
 
         // Test set.
-        $sub_m = new TestMessage_Sub();
+        $sub_m = new Sub();
         $sub_m->setA(2);
         $arr[0] = $sub_m;
         $this->assertSame(2, $arr[0]->getA());
 
         // Test foreach.
-        $arr = new RepeatedField(GPBType::MESSAGE, TestMessage_Sub::class);
+        $arr = new RepeatedField(GPBType::MESSAGE, Sub::class);
         for ($i = 0; $i < 3; $i++) {
-          $arr[] = new TestMessage_Sub();
+          $arr[] = new Sub();
           $arr[$i]->setA($i);
         }
         $i = 0;
diff --git a/php/tests/descriptors_test.php b/php/tests/descriptors_test.php
index 17e8a4f..93683b8 100644
--- a/php/tests/descriptors_test.php
+++ b/php/tests/descriptors_test.php
@@ -10,7 +10,7 @@
 use Google\Protobuf\Internal\MapField;
 use Descriptors\TestDescriptorsEnum;
 use Descriptors\TestDescriptorsMessage;
-use Descriptors\TestDescriptorsMessage_Sub;
+use Descriptors\TestDescriptorsMessage\Sub;
 
 class DescriptorsTest extends TestBase
 {
diff --git a/php/tests/encode_decode_test.php b/php/tests/encode_decode_test.php
index 74d5526..d36b883 100644
--- a/php/tests/encode_decode_test.php
+++ b/php/tests/encode_decode_test.php
@@ -7,7 +7,7 @@
 use Google\Protobuf\GPBType;
 use Foo\TestEnum;
 use Foo\TestMessage;
-use Foo\TestMessage_Sub;
+use Foo\TestMessage\Sub;
 use Foo\TestPackedMessage;
 use Foo\TestRandomFieldOrder;
 use Foo\TestUnpackedMessage;
@@ -82,7 +82,7 @@
         $n->mergeFromString($data);
         $this->assertSame('abc', $n->getOneofString());
 
-        $sub_m = new TestMessage_Sub();
+        $sub_m = new Sub();
         $sub_m->setA(1);
         $m->setOneofMessage($sub_m);
         $data = $m->serializeToString();
@@ -105,7 +105,7 @@
         $this->assertSame("oneof_string", $n->getMyOneof());
         $this->assertSame("", $n->getOneofString());
 
-        $sub_m = new TestMessage_Sub();
+        $sub_m = new Sub();
         $m->setOneofMessage($sub_m);
         $data = $m->serializeToString();
         $n = new TestMessage();
diff --git a/php/tests/gdb_test.sh b/php/tests/gdb_test.sh
index a5f6306..36fa31b 100755
--- a/php/tests/gdb_test.sh
+++ b/php/tests/gdb_test.sh
@@ -11,8 +11,8 @@
 # gdb --args php -dextension=../ext/google/protobuf/modules/protobuf.so `which
 # phpunit` --bootstrap autoload.php tmp_test.php
 #
-# gdb --args php -dextension=../ext/google/protobuf/modules/protobuf.so `which phpunit` --bootstrap autoload.php encode_decode_test.php
+gdb --args php -dextension=../ext/google/protobuf/modules/protobuf.so `which phpunit` --bootstrap autoload.php generated_class_test.php
 #
-gdb --args php -dextension=../ext/google/protobuf/modules/protobuf.so memory_leak_test.php
+# gdb --args php -dextension=../ext/google/protobuf/modules/protobuf.so memory_leak_test.php
 #
 # USE_ZEND_ALLOC=0 valgrind --leak-check=yes php -dextension=../ext/google/protobuf/modules/protobuf.so memory_leak_test.php
diff --git a/php/tests/generated_class_test.php b/php/tests/generated_class_test.php
index fbee29b..9f20bdd 100644
--- a/php/tests/generated_class_test.php
+++ b/php/tests/generated_class_test.php
@@ -8,14 +8,20 @@
 use Google\Protobuf\Internal\RepeatedField;
 use Google\Protobuf\Internal\MapField;
 use Google\Protobuf\Internal\GPBType;
+use Bar\TestLegacyMessage;
+use Bar\TestLegacyMessage_NestedEnum;
+use Bar\TestLegacyMessage_NestedMessage;
 use Foo\TestEnum;
 use Foo\TestIncludeNamespaceMessage;
 use Foo\TestIncludePrefixMessage;
 use Foo\TestMessage;
+use Foo\TestMessage\Sub;
 use Foo\TestMessage_Sub;
+use Foo\TestMessage\NestedEnum;
 use Foo\TestReverseFieldOrder;
 use Foo\testLowerCaseMessage;
 use Foo\testLowerCaseEnum;
+use PBEmpty\PBEcho\TestEmptyPackage;
 use Php\Test\TestNamespace;
 
 class GeneratedClassTest extends TestBase
@@ -231,9 +237,26 @@
     public function testNestedEnum()
     {
         $m = new TestMessage();
+        $m->setOptionalNestedEnum(NestedEnum::ZERO);
+    }
+
+    public function testLegacyNestedEnum()
+    {
+        $m = new TestMessage();
         $m->setOptionalNestedEnum(\Foo\TestMessage_NestedEnum::ZERO);
     }
 
+    public function testLegacyTypehintWithNestedEnums()
+    {
+        $this->legacyEnum(new TestLegacyMessage\NestedEnum);
+    }
+
+    private function legacyEnum(TestLegacyMessage_NestedEnum $enum)
+    {
+        // If we made it here without a PHP Fatal error, the typehint worked
+        $this->assertTrue(true);
+    }
+
     #########################################################
     # Test float field.
     #########################################################
@@ -370,6 +393,20 @@
     {
         $m = new TestMessage();
 
+        $sub_m = new Sub();
+        $sub_m->setA(1);
+        $m->setOptionalMessage($sub_m);
+        $this->assertSame(1, $m->getOptionalMessage()->getA());
+
+        $null = null;
+        $m->setOptionalMessage($null);
+        $this->assertNull($m->getOptionalMessage());
+    }
+
+    public function testLegacyMessageField()
+    {
+        $m = new TestMessage();
+
         $sub_m = new TestMessage_Sub();
         $sub_m->setA(1);
         $m->setOptionalMessage($sub_m);
@@ -380,6 +417,17 @@
         $this->assertNull($m->getOptionalMessage());
     }
 
+    public function testLegacyTypehintWithNestedMessages()
+    {
+        $this->legacyMessage(new TestLegacyMessage\NestedMessage);
+    }
+
+    private function legacyMessage(TestLegacyMessage_NestedMessage $sub)
+    {
+        // If we made it here without a PHP Fatal error, the typehint worked
+        $this->assertTrue(true);
+    }
+
     #########################################################
     # Test repeated field.
     #########################################################
@@ -474,7 +522,7 @@
         $this->assertSame(NULL, $m->getOneofMessage());
         $this->assertSame("oneof_string", $m->getMyOneof());
 
-        $sub_m = new TestMessage_Sub();
+        $sub_m = new Sub();
         $sub_m->setA(1);
         $m->setOneofMessage($sub_m);
         $this->assertSame(0, $m->getOneofInt32());
@@ -513,7 +561,7 @@
 
         // Singular
         $n->setOptionalInt32(100);
-        $sub1 = new TestMessage_Sub();
+        $sub1 = new Sub();
         $sub1->setA(101);
 
         $b = $sub1->getB();
@@ -531,7 +579,7 @@
         $repeatedString[] = 'abc';
         $n->setRepeatedString($repeatedString);
 
-        $sub2 = new TestMessage_Sub();
+        $sub2 = new Sub();
         $sub2->setA(201);
         $repeatedMessage = $n->getRepeatedMessage();
         $repeatedMessage[] = $sub2;
@@ -548,9 +596,9 @@
         $n->setMapStringString($mapStringString);
 
         $mapInt32Message = $n->getMapInt32Message();
-        $mapInt32Message[1] = new TestMessage_Sub();
+        $mapInt32Message[1] = new Sub();
         $mapInt32Message[1]->setA(302);
-        $mapInt32Message[2] = new TestMessage_Sub();
+        $mapInt32Message[2] = new Sub();
         $mapInt32Message[2]->setA(303);
         $n->setMapInt32Message($mapInt32Message);
 
@@ -607,7 +655,7 @@
         $m->mergeFrom($n);
         $this->assertSame(1, $m->getOneofInt32());
 
-        $sub = new TestMessage_Sub();
+        $sub = new Sub();
         $n->setOneofMessage($sub);
         $n->getOneofMessage()->setA(400);
         $m->mergeFrom($n);
@@ -630,14 +678,15 @@
     public function testMessageWithoutNamespace()
     {
         $m = new TestMessage();
-        $sub = new NoNameSpaceMessage();
-        $m->setOptionalNoNamespaceMessage($sub);
+        $n = new NoNameSpaceMessage();
+        $m->setOptionalNoNamespaceMessage($n);
         $repeatedNoNamespaceMessage = $m->getRepeatedNoNamespaceMessage();
         $repeatedNoNamespaceMessage[] = new NoNameSpaceMessage();
         $m->setRepeatedNoNamespaceMessage($repeatedNoNamespaceMessage);
 
-        $n = new NoNamespaceMessage();
-        $n->setB(NoNamespaceMessage_NestedEnum::ZERO);
+        // test nested messages
+        $sub = new NoNamespaceMessage\NestedMessage();
+        $n->setNestedMessage($sub);
     }
 
     public function testEnumWithoutNamespace()
@@ -650,35 +699,91 @@
     }
 
     #########################################################
-    # Test message with given prefix.
+    # Test message with given namespace.
     #########################################################
 
-    public function testPrefixMessage()
+    public function testNestedMessagesAndEnums()
     {
+        $m = new TestMessage();
+        $n = new TestMessage\Sub();
+        $m->setOptionalMessage($n);
+        $m->setOptionalNestedEnum(TestMessage\NestedEnum::ZERO);
+        $this->assertSame($n, $m->getOptionalMessage());
+        $this->assertSame(TestMessage\NestedEnum::ZERO, $m->getOptionalNestedEnum());
+    }
+
+    public function testMessagesAndEnumsWithPrefix()
+    {
+        // Test message prefix
         $m = new TestIncludePrefixMessage();
         $n = new PrefixTestPrefix();
         $n->setA(1);
         $m->setPrefixMessage($n);
         $this->assertSame(1, $m->getPrefixMessage()->getA());
+
+        // Test nested message prefix
+        $o = new PrefixTestPrefix();
+        $p = new PrefixTestPrefix\PrefixNestedMessage();
+        $o->setNestedMessage($p);
+        $o->setNestedEnum(PrefixTestPrefix\PrefixNestedEnum::ZERO);
+        $this->assertSame($p, $o->getNestedMessage());
+        $this->assertSame(PrefixTestPrefix\PrefixNestedEnum::ZERO, $o->getNestedEnum());
     }
 
-    #########################################################
-    # Test message with given namespace.
-    #########################################################
-
-    public function testNamespaceMessage()
+    public function testMessagesAndEnumsWithPhpNamespace()
     {
-        $m = new TestIncludeNamespaceMessage();
+        $m = new TestNamespace();
+        $n = new TestNamespace\NestedMessage();
+        $m->setNestedMessage($n);
+        $m->setNestedEnum(TestNamespace\NestedEnum::ZERO);
+        $this->assertSame($n, $m->getNestedMessage());
+        $this->assertSame(TestNamespace\NestedEnum::ZERO, $m->getNestedEnum());
+    }
 
-        $n = new TestNamespace();
-        $n->setA(1);
-        $m->setNamespaceMessage($n);
-        $this->assertSame(1, $m->getNamespaceMessage()->getA());
+    public function testMesssagesAndEnumsWithEmptyPhpNamespace()
+    {
+        $m = new TestEmptyNamespace();
+        $n = new TestEmptyNamespace\NestedMessage();
+        $m->setNestedMessage($n);
+        $m->setNestedEnum(TestEmptyNamespace\NestedEnum::ZERO);
+        $this->assertSame($n, $m->getNestedMessage());
+        $this->assertSame(TestEmptyNamespace\NestedEnum::ZERO, $m->getNestedEnum());
+    }
 
-        $n = new TestEmptyNamespace();
-        $n->setA(1);
-        $m->setEmptyNamespaceMessage($n);
-        $this->assertSame(1, $m->getEmptyNamespaceMessage()->getA());
+    public function testMessagesAndEnumsWithNoNamespace()
+    {
+        $m = new NoNamespaceMessage();
+        $n = new NoNamespaceMessage\NestedMessage();
+        $m->setNestedMessage($n);
+        $m->setNestedEnum(NoNamespaceMessage\NestedEnum::ZERO);
+        $this->assertSame($n, $m->getNestedMessage());
+        $this->assertSame(NoNamespaceMessage\NestedEnum::ZERO, $m->getNestedEnum());
+    }
+
+    public function testReservedWordsInPackageName()
+    {
+        $m = new TestEmptyPackage();
+        $n = new TestEmptyPackage\NestedMessage();
+        $m->setNestedMessage($n);
+        $m->setNestedEnum(TestEmptyPackage\NestedEnum::ZERO);
+        $this->assertSame($n, $m->getNestedMessage());
+        $this->assertSame(TestEmptyPackage\NestedEnum::ZERO, $m->getNestedEnum());
+    }
+
+    public function testReservedWordsInNamespace()
+    {
+        $m = new TestNamespace();
+        $n = new TestNamespace\PBEmpty();
+        $o = new TestNamespace\PBEmpty\NestedMessage();
+        $n->setNestedMessage($o);
+        $n->setNestedEnum(TestNamespace\PBEmpty\NestedEnum::ZERO);
+        $m->setReservedName($n);
+        $this->assertSame($n, $m->getReservedName());
+        $this->assertSame($o, $n->getNestedMessage());
+        $this->assertSame(
+            TestNamespace\PBEmpty\NestedEnum::ZERO,
+            $n->getNestedEnum()
+        );
     }
 
     #########################################################
@@ -687,7 +792,7 @@
 
     public function testPrefixForReservedWords()
     {
-        $m = new \Foo\TestMessage_Empty();
+        $m = new \Foo\TestMessage\PBEmpty();
         $m = new \Foo\PBEmpty();
         $m = new \PrefixEmpty();
         $m = new \Foo\PBARRAY();
@@ -1195,7 +1300,7 @@
             'optional_string' => 'a',
             'optional_bytes' => 'b',
             'optional_enum' => TestEnum::ONE,
-            'optional_message' => new TestMessage_Sub([
+            'optional_message' => new Sub([
                 'a' => 33
             ]),
             'repeated_int32' => [-42, -52],
@@ -1214,8 +1319,8 @@
             'repeated_string' => ['a', 'c'],
             'repeated_bytes' => ['b', 'd'],
             'repeated_enum' => [TestEnum::ZERO, TestEnum::ONE],
-            'repeated_message' => [new TestMessage_Sub(['a' => 34]),
-                                   new TestMessage_Sub(['a' => 35])],
+            'repeated_message' => [new Sub(['a' => 34]),
+                                   new Sub(['a' => 35])],
             'map_int32_int32' => [-62 => -62],
             'map_int64_int64' => [-63 => -63],
             'map_uint32_uint32' => [62 => 62],
@@ -1232,7 +1337,7 @@
             'map_string_string' => ['e' => 'e'],
             'map_int32_bytes' => [1 => 'f'],
             'map_int32_enum' => [1 => TestEnum::ONE],
-            'map_int32_message' => [1 => new TestMessage_Sub(['a' => 36])],
+            'map_int32_message' => [1 => new Sub(['a' => 36])],
         ]);
 
         TestUtil::assertTestMessage($m);
diff --git a/php/tests/generated_phpdoc_test.php b/php/tests/generated_phpdoc_test.php
index 505dafe..526927f 100644
--- a/php/tests/generated_phpdoc_test.php
+++ b/php/tests/generated_phpdoc_test.php
@@ -201,7 +201,7 @@
                 [
                     'setRepeatedMessage',
                 ],
-                '@param \Foo\TestMessage_Sub[]|\Google\Protobuf\Internal\RepeatedField $var'
+                '@param \Foo\TestMessage\Sub[]|\Google\Protobuf\Internal\RepeatedField $var'
             ],
             [
                 [
@@ -294,14 +294,14 @@
                     'getOptionalMessage',
                     'getOneofMessage'
                 ],
-                '@return \Foo\TestMessage_Sub'
+                '@return \Foo\TestMessage\Sub'
             ],
             [
                 [
                     'setOptionalMessage',
                     'setOneofMessage'
                 ],
-                '@param \Foo\TestMessage_Sub $var'
+                '@param \Foo\TestMessage\Sub $var'
             ],
             [
                 [
diff --git a/php/tests/map_field_test.php b/php/tests/map_field_test.php
index cffa252..447bdd9 100644
--- a/php/tests/map_field_test.php
+++ b/php/tests/map_field_test.php
@@ -5,7 +5,7 @@
 use Google\Protobuf\Internal\GPBType;
 use Google\Protobuf\Internal\MapField;
 use Foo\TestMessage;
-use Foo\TestMessage_Sub;
+use Foo\TestMessage\Sub;
 
 class MapFieldTest extends PHPUnit_Framework_TestCase {
 
@@ -408,10 +408,10 @@
 
     public function testMessage() {
         $arr = new MapField(GPBType::INT32,
-            GPBType::MESSAGE, TestMessage_Sub::class);
+            GPBType::MESSAGE, Sub::class);
 
         // Test append.
-        $sub_m = new TestMessage_Sub();
+        $sub_m = new Sub();
         $sub_m->setA(1);
         $arr[0] = $sub_m;
         $this->assertSame(1, $arr[0]->getA());
@@ -420,9 +420,9 @@
 
         // Test foreach.
         $arr = new MapField(GPBType::INT32,
-            GPBType::MESSAGE, TestMessage_Sub::class);
+            GPBType::MESSAGE, Sub::class);
         for ($i = 0; $i < 3; $i++) {
-          $arr[$i] = new TestMessage_Sub();;
+          $arr[$i] = new Sub();;
           $arr[$i]->setA($i);
         }
         $i = 0;
diff --git a/php/tests/memory_leak_test.php b/php/tests/memory_leak_test.php
index ad55d57..5456919 100644
--- a/php/tests/memory_leak_test.php
+++ b/php/tests/memory_leak_test.php
@@ -15,9 +15,9 @@
 require_once('generated/Foo/TestIncludeNamespaceMessage.php');
 require_once('generated/Foo/TestIncludePrefixMessage.php');
 require_once('generated/Foo/TestMessage.php');
-require_once('generated/Foo/TestMessage_Empty.php');
-require_once('generated/Foo/TestMessage_NestedEnum.php');
-require_once('generated/Foo/TestMessage_Sub.php');
+require_once('generated/Foo/TestMessage/PBEmpty.php');
+require_once('generated/Foo/TestMessage/NestedEnum.php');
+require_once('generated/Foo/TestMessage/Sub.php');
 require_once('generated/Foo/TestPackedMessage.php');
 require_once('generated/Foo/TestPhpDoc.php');
 require_once('generated/Foo/TestRandomFieldOrder.php');
@@ -37,7 +37,7 @@
 use Google\Protobuf\Internal\RepeatedField;
 use Google\Protobuf\Internal\GPBType;
 use Foo\TestMessage;
-use Foo\TestMessage_Sub;
+use Foo\TestMessage\Sub;
 
 $from = new TestMessage();
 TestUtil::setTestMessage($from);
@@ -97,7 +97,7 @@
 $n->mergeFromString($data);
 assert('abc' === $n->getOneofString());
 
-$sub_m = new TestMessage_Sub();
+$sub_m = new Sub();
 $sub_m->setA(1);
 $m->setOneofMessage($sub_m);
 assert(0 === $m->getOneofInt32());
diff --git a/php/tests/php_implementation_test.php b/php/tests/php_implementation_test.php
index 6481473..323a36f 100644
--- a/php/tests/php_implementation_test.php
+++ b/php/tests/php_implementation_test.php
@@ -5,7 +5,7 @@
 
 use Foo\TestEnum;
 use Foo\TestMessage;
-use Foo\TestMessage_Sub;
+use Foo\TestMessage\Sub;
 use Foo\TestPackedMessage;
 use Google\Protobuf\Internal\CodedInputStream;
 use Google\Protobuf\Internal\FileDescriptorSet;
@@ -527,7 +527,7 @@
 
     /**
      * @expectedException Exception
-     * @expectedExceptionMessage Expect message.
+     * @expectedExceptionMessage Expect Foo\TestMessage_Sub.
      */
     public function testArraysForMessagesThrowsException()
     {
diff --git a/php/tests/proto/empty/echo.proto b/php/tests/proto/empty/echo.proto
new file mode 100644
index 0000000..1817018
--- /dev/null
+++ b/php/tests/proto/empty/echo.proto
@@ -0,0 +1,17 @@
+syntax = "proto3";
+
+package empty.echo;
+
+message TestEmptyPackage {
+  int32 a = 1;
+
+  // Test nested messages, enums, and reserved names
+  NestedMessage nested_message = 2;
+  NestedEnum nested_enum = 3;
+  message NestedMessage {
+    int32 a = 1;
+  }
+  enum NestedEnum {
+      ZERO = 0;
+  };
+}
diff --git a/php/tests/proto/test_empty_php_namespace.proto b/php/tests/proto/test_empty_php_namespace.proto
index 1d02f76..c7ed165 100644
--- a/php/tests/proto/test_empty_php_namespace.proto
+++ b/php/tests/proto/test_empty_php_namespace.proto
@@ -6,4 +6,14 @@
 
 message TestEmptyNamespace {
   int32 a = 1;
+
+  // Test nested messages, enums, and reserved names
+  NestedMessage nested_message = 2;
+  NestedEnum nested_enum = 3;
+  message NestedMessage {
+    int32 a = 1;
+  }
+  enum NestedEnum {
+      ZERO = 0;
+  };
 }
diff --git a/php/tests/proto/test_include.proto b/php/tests/proto/test_include.proto
index 9844617..a9072fe 100644
--- a/php/tests/proto/test_include.proto
+++ b/php/tests/proto/test_include.proto
@@ -5,3 +5,14 @@
 message TestInclude {
   int32 a = 1;
 }
+
+message TestLegacyMessage {
+  NestedMessage message = 1;
+  NestedEnum enum = 2;
+  message NestedMessage {
+    int32 a = 1;
+  }
+  enum NestedEnum {
+    ZERO = 0;
+  }
+}
diff --git a/php/tests/proto/test_no_namespace.proto b/php/tests/proto/test_no_namespace.proto
index 03f8927..cce42ea 100644
--- a/php/tests/proto/test_no_namespace.proto
+++ b/php/tests/proto/test_no_namespace.proto
@@ -5,11 +5,15 @@
 message NoNamespaceMessage {
   int32 a = 1;
 
-  enum NestedEnum {
-    ZERO = 0;
+  // Test nested messages, enums, and reserved names
+  NestedMessage nested_message = 2;
+  NestedEnum nested_enum = 3;
+  message NestedMessage {
+    int32 a = 1;
   }
-  NestedEnum b = 2;
-  repeated NestedEnum c = 3;
+  enum NestedEnum {
+      ZERO = 0;
+  };
 }
 
 enum NoNamespaceEnum {
diff --git a/php/tests/proto/test_php_namespace.proto b/php/tests/proto/test_php_namespace.proto
index bb57d61..61085bf 100644
--- a/php/tests/proto/test_php_namespace.proto
+++ b/php/tests/proto/test_php_namespace.proto
@@ -6,4 +6,26 @@
 
 message TestNamespace {
   int32 a = 1;
+
+  // Test nested messages, enums, and reserved names
+  NestedMessage nested_message = 2;
+  NestedEnum nested_enum = 3;
+  Empty reserved_name = 4;
+  message NestedMessage {
+    int32 a = 1;
+  }
+  enum NestedEnum {
+      ZERO = 0;
+  };
+  // Test reserved name
+  message Empty {
+    NestedMessage nested_message = 1;
+    NestedEnum nested_enum = 2;
+    message NestedMessage {
+      int32 a = 1;
+    }
+    enum NestedEnum {
+      ZERO = 0;
+    };
+  }
 }
diff --git a/php/tests/proto/test_prefix.proto b/php/tests/proto/test_prefix.proto
index 9bfbad7..3fa1138 100644
--- a/php/tests/proto/test_prefix.proto
+++ b/php/tests/proto/test_prefix.proto
@@ -4,6 +4,14 @@
 
 message TestPrefix {
   int32 a = 1;
+  NestedMessage nested_message = 2;
+  NestedEnum nested_enum = 3;
+  message NestedMessage {
+    int32 a = 1;
+  }
+  enum NestedEnum {
+      ZERO = 0;
+  };
 }
 
 // Test prefix for reserved words.
diff --git a/php/tests/test_base.php b/php/tests/test_base.php
index dc5e73f..80f603c 100644
--- a/php/tests/test_base.php
+++ b/php/tests/test_base.php
@@ -2,7 +2,7 @@
 
 use Foo\TestMessage;
 use Foo\TestEnum;
-use Foo\TestMessage_Sub;
+use Foo\TestMessage\Sub;
 
 class TestBase extends PHPUnit_Framework_TestCase
 {
diff --git a/php/tests/test_util.php b/php/tests/test_util.php
index c8afdd3..a676d09 100644
--- a/php/tests/test_util.php
+++ b/php/tests/test_util.php
@@ -2,7 +2,7 @@
 
 use Foo\TestEnum;
 use Foo\TestMessage;
-use Foo\TestMessage_Sub;
+use Foo\TestMessage\Sub;
 use Foo\TestPackedMessage;
 use Foo\TestUnpackedMessage;
 
@@ -67,7 +67,7 @@
         $m->setOptionalString('a');
         $m->setOptionalBytes('b');
         $m->setOptionalEnum(TestEnum::ONE);
-        $sub = new TestMessage_Sub();
+        $sub = new Sub();
         $m->setOptionalMessage($sub);
         $m->getOptionalMessage()->SetA(33);
 
@@ -87,7 +87,7 @@
         self::appendHelper($m, 'RepeatedString',   'a');
         self::appendHelper($m, 'RepeatedBytes',    'b');
         self::appendHelper($m, 'RepeatedEnum',     TestEnum::ZERO);
-        self::appendHelper($m, 'RepeatedMessage',  new TestMessage_Sub());
+        self::appendHelper($m, 'RepeatedMessage',  new Sub());
         $m->getRepeatedMessage()[0]->setA(34);
 
         self::appendHelper($m, 'RepeatedInt32',    -52);
@@ -106,7 +106,7 @@
         self::appendHelper($m, 'RepeatedString',   'c');
         self::appendHelper($m, 'RepeatedBytes',    'd');
         self::appendHelper($m, 'RepeatedEnum',     TestEnum::ONE);
-        self::appendHelper($m, 'RepeatedMessage',  new TestMessage_Sub());
+        self::appendHelper($m, 'RepeatedMessage',  new Sub());
         $m->getRepeatedMessage()[1]->SetA(35);
 
         self::kvUpdateHelper($m, 'MapInt32Int32', -62, -62);
@@ -125,13 +125,13 @@
         self::kvUpdateHelper($m, 'MapStringString', 'e', 'e');
         self::kvUpdateHelper($m, 'MapInt32Bytes', 1, 'f');
         self::kvUpdateHelper($m, 'MapInt32Enum', 1, TestEnum::ONE);
-        self::kvUpdateHelper($m, 'MapInt32Message', 1, new TestMessage_Sub());
+        self::kvUpdateHelper($m, 'MapInt32Message', 1, new Sub());
         $m->getMapInt32Message()[1]->SetA(36);
     }
 
     public static function setTestMessage2(TestMessage $m)
     {
-        $sub = new TestMessage_Sub();
+        $sub = new Sub();
 
         $m->setOptionalInt32(-142);
         $m->setOptionalInt64(-143);
@@ -168,7 +168,7 @@
         self::appendHelper($m, 'RepeatedString',   'aa');
         self::appendHelper($m, 'RepeatedBytes',    'bb');
         self::appendHelper($m, 'RepeatedEnum',     TestEnum::TWO);
-        self::appendHelper($m, 'RepeatedMessage',  new TestMessage_Sub());
+        self::appendHelper($m, 'RepeatedMessage',  new Sub());
         $m->getRepeatedMessage()[0]->setA(134);
 
         self::kvUpdateHelper($m, 'MapInt32Int32', -62, -162);
@@ -187,7 +187,7 @@
         self::kvUpdateHelper($m, 'MapStringString', 'e', 'ee');
         self::kvUpdateHelper($m, 'MapInt32Bytes', 1, 'ff');
         self::kvUpdateHelper($m, 'MapInt32Enum', 1, TestEnum::TWO);
-        self::kvUpdateHelper($m, 'MapInt32Message', 1, new TestMessage_Sub());
+        self::kvUpdateHelper($m, 'MapInt32Message', 1, new Sub());
         $m->getMapInt32Message()[1]->SetA(136);
 
         self::kvUpdateHelper($m, 'MapInt32Int32', -162, -162);
@@ -206,7 +206,7 @@
         self::kvUpdateHelper($m, 'MapStringString', 'ee', 'ee');
         self::kvUpdateHelper($m, 'MapInt32Bytes', 2, 'ff');
         self::kvUpdateHelper($m, 'MapInt32Enum', 2, TestEnum::TWO);
-        self::kvUpdateHelper($m, 'MapInt32Message', 2, new TestMessage_Sub());
+        self::kvUpdateHelper($m, 'MapInt32Message', 2, new Sub());
         $m->getMapInt32Message()[2]->SetA(136);
     }
 
diff --git a/php/tests/undefined_test.php b/php/tests/undefined_test.php
index dc6b708..f844457 100644
--- a/php/tests/undefined_test.php
+++ b/php/tests/undefined_test.php
@@ -5,7 +5,7 @@
 use Google\Protobuf\Internal\RepeatedField;
 use Google\Protobuf\Internal\GPBType;
 use Foo\TestMessage;
-use Foo\TestMessage_Sub;
+use Foo\TestMessage\Sub;
 
 class UndefinedTest extends PHPUnit_Framework_TestCase
 {
@@ -35,7 +35,7 @@
     public function testInt32AppendMessageFail()
     {
         $arr = new RepeatedField(GPBType::INT32);
-        $arr[] = new TestMessage_Sub();
+        $arr[] = new Sub();
     }
 
     /**
@@ -45,7 +45,7 @@
     {
         $arr = new RepeatedField(GPBType::INT32);
         $arr[] = 0;
-        $arr[0] = new TestMessage_Sub();
+        $arr[0] = new Sub();
     }
 
     /**
@@ -73,7 +73,7 @@
     public function testUint32AppendMessageFail()
     {
         $arr = new RepeatedField(GPBType::UINT32);
-        $arr[] = new TestMessage_Sub();
+        $arr[] = new Sub();
     }
 
     /**
@@ -83,7 +83,7 @@
     {
         $arr = new RepeatedField(GPBType::UINT32);
         $arr[] = 0;
-        $arr[0] = new TestMessage_Sub();
+        $arr[0] = new Sub();
     }
 
     /**
@@ -111,7 +111,7 @@
     public function testInt64AppendMessageFail()
     {
         $arr = new RepeatedField(GPBType::INT64);
-        $arr[] = new TestMessage_Sub();
+        $arr[] = new Sub();
     }
 
     /**
@@ -121,7 +121,7 @@
     {
         $arr = new RepeatedField(GPBType::INT64);
         $arr[] = 0;
-        $arr[0] = new TestMessage_Sub();
+        $arr[0] = new Sub();
     }
 
     /**
@@ -149,7 +149,7 @@
     public function testUint64AppendMessageFail()
     {
         $arr = new RepeatedField(GPBType::UINT64);
-        $arr[] = new TestMessage_Sub();
+        $arr[] = new Sub();
     }
 
     /**
@@ -159,7 +159,7 @@
     {
         $arr = new RepeatedField(GPBType::UINT64);
         $arr[] = 0;
-        $arr[0] = new TestMessage_Sub();
+        $arr[0] = new Sub();
     }
 
     /**
@@ -187,7 +187,7 @@
     public function testFloatAppendMessageFail()
     {
         $arr = new RepeatedField(GPBType::FLOAT);
-        $arr[] = new TestMessage_Sub();
+        $arr[] = new Sub();
     }
 
     /**
@@ -197,7 +197,7 @@
     {
         $arr = new RepeatedField(GPBType::FLOAT);
         $arr[] = 0.0;
-        $arr[0] = new TestMessage_Sub();
+        $arr[0] = new Sub();
     }
 
     /**
@@ -225,7 +225,7 @@
     public function testDoubleAppendMessageFail()
     {
         $arr = new RepeatedField(GPBType::DOUBLE);
-        $arr[] = new TestMessage_Sub();
+        $arr[] = new Sub();
     }
 
     /**
@@ -235,7 +235,7 @@
     {
         $arr = new RepeatedField(GPBType::DOUBLE);
         $arr[] = 0.0;
-        $arr[0] = new TestMessage_Sub();
+        $arr[0] = new Sub();
     }
 
     /**
@@ -244,7 +244,7 @@
     public function testBoolAppendMessageFail()
     {
         $arr = new RepeatedField(GPBType::BOOL);
-        $arr[] = new TestMessage_Sub();
+        $arr[] = new Sub();
     }
 
     /**
@@ -254,7 +254,7 @@
     {
         $arr = new RepeatedField(GPBType::BOOL);
         $arr[] = true;
-        $arr[0] = new TestMessage_Sub();
+        $arr[0] = new Sub();
     }
 
     /**
@@ -263,7 +263,7 @@
     public function testStringAppendMessageFail()
     {
         $arr = new RepeatedField(GPBType::STRING);
-        $arr[] = new TestMessage_Sub();
+        $arr[] = new Sub();
     }
 
     /**
@@ -273,7 +273,7 @@
     {
         $arr = new RepeatedField(GPBType::STRING);
         $arr[] = 'abc';
-        $arr[0] = new TestMessage_Sub();
+        $arr[0] = new Sub();
     }
 
     /**
@@ -302,7 +302,7 @@
      */
     public function testMessageAppendIntFail()
     {
-        $arr = new RepeatedField(GPBType::MESSAGE, TestMessage_Sub::class);
+        $arr = new RepeatedField(GPBType::MESSAGE, Sub::class);
         $arr[] = 1;
     }
 
@@ -311,8 +311,8 @@
      */
     public function testMessageSetIntFail()
     {
-        $arr = new RepeatedField(GPBType::MESSAGE, TestMessage_Sub::class);
-        $arr[] = new TestMessage_Sub;
+        $arr = new RepeatedField(GPBType::MESSAGE, Sub::class);
+        $arr[] = new Sub;
         $arr[0] = 'abc';
     }
 
@@ -321,7 +321,7 @@
      */
     public function testMessageAppendStringFail()
     {
-        $arr = new RepeatedField(GPBType::MESSAGE, TestMessage_Sub::class);
+        $arr = new RepeatedField(GPBType::MESSAGE, Sub::class);
         $arr[] = 'abc';
     }
 
@@ -330,8 +330,8 @@
      */
     public function testMessageSetStringFail()
     {
-        $arr = new RepeatedField(GPBType::MESSAGE, TestMessage_Sub::class);
-        $arr[] = new TestMessage_Sub;
+        $arr = new RepeatedField(GPBType::MESSAGE, Sub::class);
+        $arr[] = new Sub;
         $arr[0] = 'abc';
     }
 
@@ -340,7 +340,7 @@
      */
     public function testMessageAppendOtherMessageFail()
     {
-        $arr = new RepeatedField(GPBType::MESSAGE, TestMessage_Sub::class);
+        $arr = new RepeatedField(GPBType::MESSAGE, Sub::class);
         $arr[] = new TestMessage;
     }
 
@@ -349,7 +349,7 @@
      */
     public function testMessageAppendNullFail()
     {
-        $arr = new RepeatedField(GPBType::MESSAGE, TestMessage_Sub::class);
+        $arr = new RepeatedField(GPBType::MESSAGE, Sub::class);
         $null = null;
         $arr[] = $null;
     }
@@ -359,8 +359,8 @@
      */
     public function testMessageSetNullFail()
     {
-        $arr = new RepeatedField(GPBType::MESSAGE, TestMessage_Sub::class);
-        $arr[] = new TestMessage_Sub();
+        $arr = new RepeatedField(GPBType::MESSAGE, Sub::class);
+        $arr[] = new Sub();
         $null = null;
         $arr[0] = $null;
     }
@@ -397,7 +397,7 @@
     {
         $arr = new RepeatedField(GPBType::INT32);
         $arr[] = 0;
-        $arr[new TestMessage_Sub()] = 0;
+        $arr[new Sub()] = 0;
     }
 
     /**
@@ -656,7 +656,7 @@
     public function testMessageMergeFromInvalidTypeFail()
     {
         $m = new TestMessage();
-        $n = new TestMessage_Sub();
+        $n = new Sub();
         $m->mergeFrom($n);
     }
 
@@ -684,7 +684,7 @@
     public function testInt32SetMessageKeyFail()
     {
         $arr = new MapField(GPBType::INT32, GPBType::INT32);
-        $arr[new TestMessage_Sub()] = 0;
+        $arr[new Sub()] = 0;
     }
 
     /**
@@ -693,7 +693,7 @@
     public function testInt32SetMessageValueFail()
     {
         $arr = new MapField(GPBType::INT32, GPBType::INT32);
-        $arr[0] = new TestMessage_Sub();
+        $arr[0] = new Sub();
     }
 
     /**
@@ -720,7 +720,7 @@
     public function testUint32SetMessageKeyFail()
     {
         $arr = new MapField(GPBType::UINT32, GPBType::UINT32);
-        $arr[new TestMessage_Sub()] = 0;
+        $arr[new Sub()] = 0;
     }
 
     /**
@@ -729,7 +729,7 @@
     public function testUint32SetMessageValueFail()
     {
         $arr = new MapField(GPBType::UINT32, GPBType::UINT32);
-        $arr[0] = new TestMessage_Sub();
+        $arr[0] = new Sub();
     }
 
     /**
@@ -756,7 +756,7 @@
     public function testInt64SetMessageKeyFail()
     {
         $arr = new MapField(GPBType::INT64, GPBType::INT64);
-        $arr[new TestMessage_Sub()] = 0;
+        $arr[new Sub()] = 0;
     }
 
     /**
@@ -765,7 +765,7 @@
     public function testInt64SetMessageValueFail()
     {
         $arr = new MapField(GPBType::INT64, GPBType::INT64);
-        $arr[0] = new TestMessage_Sub();
+        $arr[0] = new Sub();
     }
 
     /**
@@ -792,7 +792,7 @@
     public function testUint64SetMessageKeyFail()
     {
         $arr = new MapField(GPBType::UINT64, GPBType::UINT64);
-        $arr[new TestMessage_Sub()] = 0;
+        $arr[new Sub()] = 0;
     }
 
     /**
@@ -801,7 +801,7 @@
     public function testUint64SetMessageValueFail()
     {
         $arr = new MapField(GPBType::UINT64, GPBType::UINT64);
-        $arr[0] = new TestMessage_Sub();
+        $arr[0] = new Sub();
     }
 
     /**
@@ -819,7 +819,7 @@
     public function testDoubleSetMessageValueFail()
     {
         $arr = new MapField(GPBType::INT64, GPBType::DOUBLE);
-        $arr[0] = new TestMessage_Sub();
+        $arr[0] = new Sub();
     }
 
     /**
@@ -828,7 +828,7 @@
     public function testBoolSetMessageKeyFail()
     {
         $arr = new MapField(GPBType::BOOL, GPBType::BOOL);
-        $arr[new TestMessage_Sub()] = true;
+        $arr[new Sub()] = true;
     }
 
     /**
@@ -837,7 +837,7 @@
     public function testBoolSetMessageValueFail()
     {
         $arr = new MapField(GPBType::BOOL, GPBType::BOOL);
-        $arr[true] = new TestMessage_Sub();
+        $arr[true] = new Sub();
     }
 
     /**
@@ -864,7 +864,7 @@
     public function testStringSetMessageKeyFail()
     {
         $arr = new MapField(GPBType::STRING, GPBType::STRING);
-        $arr[new TestMessage_Sub()] = 'abc';
+        $arr[new Sub()] = 'abc';
     }
 
     /**
@@ -873,7 +873,7 @@
     public function testStringSetMessageValueFail()
     {
         $arr = new MapField(GPBType::STRING, GPBType::STRING);
-        $arr['abc'] = new TestMessage_Sub();
+        $arr['abc'] = new Sub();
     }
 
     /**
@@ -903,7 +903,7 @@
     {
        $arr =
            new MapField(GPBType::INT32, GPBType::MESSAGE, TestMessage::class);
-       $arr[0] = new TestMessage_Sub();
+       $arr[0] = new Sub();
     }
 
     /**
diff --git a/php/tests/well_known_test.php b/php/tests/well_known_test.php
index a776068..1e8c4f4 100644
--- a/php/tests/well_known_test.php
+++ b/php/tests/well_known_test.php
@@ -14,8 +14,8 @@
 use Google\Protobuf\EnumValue;
 use Google\Protobuf\Field;
 use Google\Protobuf\FieldMask;
-use Google\Protobuf\Field_Cardinality;
-use Google\Protobuf\Field_Kind;
+use Google\Protobuf\Field\Cardinality;
+use Google\Protobuf\Field\Kind;
 use Google\Protobuf\FloatValue;
 use Google\Protobuf\GPBEmpty;
 use Google\Protobuf\Int32Value;
@@ -206,11 +206,11 @@
     {
         $m = new Field();
 
-        $m->setKind(Field_Kind::TYPE_DOUBLE);
-        $this->assertSame(Field_Kind::TYPE_DOUBLE, $m->getKind());
+        $m->setKind(Kind::TYPE_DOUBLE);
+        $this->assertSame(Kind::TYPE_DOUBLE, $m->getKind());
 
-        $m->setCardinality(Field_Cardinality::CARDINALITY_OPTIONAL);
-        $this->assertSame(Field_Cardinality::CARDINALITY_OPTIONAL, $m->getCardinality());
+        $m->setCardinality(Cardinality::CARDINALITY_OPTIONAL);
+        $this->assertSame(Cardinality::CARDINALITY_OPTIONAL, $m->getCardinality());
 
         $m->setNumber(1);
         $this->assertSame(1, $m->getNumber());