The extractTo() method does not offer any parameter to allow extracting files and folders recursively from another (parent) folder inside the ZIP archive. With the following method it is possible:
<?php
class my_ZipArchive extends ZipArchive
{
    public function extractSubdirTo($destination, $subdir)
    {
$errors = array();
$destination = str_replace(array("/", "\\"), DIRECTORY_SEPARATOR, $destination);
$subdir = str_replace(array("/", "\\"), "/", $subdir);
      if (substr($destination, mb_strlen(DIRECTORY_SEPARATOR, "UTF-8") * -1) != DIRECTORY_SEPARATOR)
$destination .= DIRECTORY_SEPARATOR;
      if (substr($subdir, -1) != "/")
$subdir .= "/";
for ($i = 0; $i < $this->numFiles; $i++)
      {
$filename = $this->getNameIndex($i);
        if (substr($filename, 0, mb_strlen($subdir, "UTF-8")) == $subdir)
        {
$relativePath = substr($filename, mb_strlen($subdir, "UTF-8"));
$relativePath = str_replace(array("/", "\\"), DIRECTORY_SEPARATOR, $relativePath);
          if (mb_strlen($relativePath, "UTF-8") > 0)
          {
            if (substr($filename, -1) == "/")  {
if (!is_dir($destination . $relativePath))
                if (!@mkdir($destination . $relativePath, 0755, true))
$errors[$i] = $filename;
            }
            else
            {
              if (dirname($relativePath) != ".")
              {
                if (!is_dir($destination . dirname($relativePath)))
                {
@mkdir($destination . dirname($relativePath), 0755, true);
                }
              }
if (@file_put_contents($destination . $relativePath, $this->getFromIndex($i)) === false)
$errors[$i] = $filename;
            }
          }
        }
      }
      return $errors;
    }
  }
?>
Example:
<?php
echo "<pre>";
$zip = new my_ZipArchive();
  if ($zip->open("test.zip") === TRUE)
  {
$errors = $zip->extractSubdirTo("C:/output", "folder/subfolder/");
$zip->close();
    echo 'ok, errors: ' . count($errors);
  }
  else
  {
    echo 'failed';
  }
?>