├── Php2Zep.php ├── README.md ├── examples ├── php │ └── myapp │ │ ├── Application.php │ │ ├── controllers │ │ └── UserController.php │ │ └── models │ │ └── UserModel.php └── zep │ └── myapp │ ├── Application.zep │ ├── controllers │ └── UserController.zep │ └── models │ └── UserModel.zep └── test ├── test.php ├── testList.php ├── testStaticSet.php └── testTryCatch.php /Php2Zep.php: -------------------------------------------------------------------------------- 1 | All Rights Reserved | 15 | * +-----------------------------------------------------------------+ 16 | */ 17 | class Php2Zep 18 | { 19 | private $currentFile = ''; 20 | private $currentLine = 0; 21 | private $currentMethod = ''; 22 | private $currentClass = ''; 23 | private $currentStaticVars = []; 24 | private $staticLetLines = []; 25 | private $foundFunction = false; 26 | 27 | private $lineFlag = ''; 28 | private $keywords = ['object', 'string', 'array', 'function', 'for', 'foreach', 'while', 'do', 'if', 'else', 'elseif', 'type', 'unset', 'empty', 'isset', 'boolean', 'integer', 'int', 'float', 'double', 'class', 'public', 'private', 'static', 'protected', 'extends', 'else', 'elseif', 'throw', 'exception', 'final', 'abstract', 'parent', 'self', 'range', 'in', 'instanceof', 'default', 'switch', 'inline', 'var', 'let', 'const']; 29 | private $ignoreVars = ['this','_GET', '_POST', '_SERVER', '_FILES', '_COOKIE', '_SESSION']; 30 | private $varPrefix = 'x_'; 31 | 32 | private $currentFuncLines; 33 | private $funcVars = []; 34 | private $tmpArrVars = []; 35 | 36 | /** 37 | * 针对函数体 38 | * @param [type] $str [description] 39 | * @return [type] [description] 40 | */ 41 | public function getVars($str) 42 | { 43 | // 类变量 44 | $hasclassStaticProperties = preg_match_all('/[a-zA-Z_][a-zA-Z0-9_]*::(\$[a-zA-Z_][a-zA-Z0-9_]*)/', $str, $staticMatches); 45 | if ($hasclassStaticProperties) { 46 | $this->currentStaticVars = array_unique($staticMatches[1]); 47 | } else { 48 | $this->currentStaticVars = []; 49 | } 50 | // 其它变量 51 | $hasVars = preg_match_all('/[^:]{2}(\$[a-zA-Z_][a-zA-Z0-9_]*)/', $str, $matches); 52 | if ($hasVars) { 53 | return array_unique($matches[1]); 54 | } 55 | 56 | return []; 57 | } 58 | 59 | /** 60 | * 针对函数参数 61 | * @param [type] $str [description] 62 | * @return [type] [description] 63 | */ 64 | public function getArgs($str) 65 | { 66 | $hasFunc = preg_match_all('/\bfunction\s+\w+\([^\)]*\)/', $str, $func); 67 | if ($hasFunc) { 68 | $hasArgs = preg_match_all('/\$\w+/', $func[0][0], $funcArgs); 69 | if ($hasArgs) { 70 | return $funcArgs[0]; 71 | } 72 | } 73 | 74 | return []; 75 | } 76 | 77 | /** 78 | * 针对单行或多行 79 | * @param [type] $str [description] 80 | * @return [type] [description] 81 | */ 82 | public function convertVars($str) 83 | { 84 | // 先替换类变量 85 | if (!empty($this->currentStaticVars)) { 86 | $str = preg_replace('/([a-zA-Z_][a-zA-Z0-9_]*):: 87 | \$([a-zA-Z_][a-zA-Z0-9_]*)/', "$1::$2", $str); 88 | } 89 | // 与类变量同名的其它变量需要加前缀 90 | $extendedKeywords = array_merge($this->keywords, $this->currentStaticVars); 91 | 92 | return preg_replace_callback('/\$(\w+)/', function($matches) use ($extendedKeywords){ 93 | if (in_array($matches[1], $this->ignoreVars)) { 94 | return $matches[1]; // $this 95 | } elseif (in_array($matches[1], $extendedKeywords)) { 96 | return $this->varPrefix . $matches[1]; 97 | } else { 98 | return $matches[1]; 99 | } 100 | }, $str); 101 | } 102 | 103 | /** 104 | * 针对单行 105 | * @param [type] $str [description] 106 | * @return [type] [description] 107 | */ 108 | public function convertForeach($str) 109 | { 110 | $hasForeach = preg_match('/\bforeach\s*\(\s*([^\s]+)\s+as\s+([^\s\)]+)\s*(=>\s*\$\w+)?\)/', $str, $matches, PREG_OFFSET_CAPTURE); //([^\s]+)\s*\) (=>\s*\$\w+)? 111 | 112 | if ($hasForeach) { 113 | $this->lineFlag = 'foreach'; 114 | //print_r($matches); 115 | if (count($matches) == 4) { 116 | $matches[3][0] = trim(str_replace("=>", "", $matches[3][0])); 117 | $newExpr = 'for ' . $matches[2][0] . ',' . $matches[3][0] . ' in ' . $matches[1][0] ; 118 | //$str = substr($str, 0, $matches[0][1]) . $newExpr . substr($str, $matches[0][1] + strlen($matches[0][0])); 119 | } else { 120 | $newExpr = 'for ' . $matches[2][0] . ' in ' . $matches[1][0]; 121 | } 122 | $str = substr($str, 0, $matches[0][1]) . $newExpr . substr($str, $matches[0][1] + strlen($matches[0][0])); 123 | } 124 | 125 | return $str; 126 | } 127 | 128 | /** 129 | * 针对单行 130 | * @param [type] $str [description] 131 | * @return [type] [description] 132 | */ 133 | public function convertAssigns($str) 134 | { 135 | $hasAssign = preg_match_all('/([^\s\(]+?\s*[^>= $mstr) { 142 | //echo $str, PHP_EOL; 143 | $lenMstr = strlen($mstr[0]); 144 | //echo $mstr[0]; 145 | $c = $str[$lenMstr + $mstr[1] + $offset]; 146 | $c01 = $str[$lenMstr + $mstr[1] + $offset - 2]; 147 | //echo "#", $c,' ', $c01, PHP_EOL; 148 | if (!($c == '=' || $c == '>' || $c01 == '=' || $c01 == '>' || $c01 == '<' || $c01 == '!')) { 149 | // check special 150 | $j = $mstr[1]-1; 151 | while($j>=0 && $str[$j] == ' ') { 152 | $j--; 153 | } 154 | 155 | if ($j>=0 && $str[$j] == '.') { 156 | if (preg_match('/^\s*/', $str, $spaces)) { 157 | $str = $spaces[0] . 'let ' . ltrim($str); 158 | } else { 159 | $str = 'let ' . ltrim($str); 160 | } 161 | } else { 162 | $newExpr = "let " . $matches[1][$k][0] . ' '; 163 | $remainStr = substr($str, $offset+$mstr[1]+$lenMstr); 164 | //echo 'rem= ', $remainStr, PHP_EOL; 165 | if (preg_match('/(\s*)if\s*\(/', $str, $spaces)) { 166 | $varName = rtrim($matches[1][$k][0], " ="); 167 | $remainLen = strlen($remainStr); 168 | $hasParences = false; 169 | $leftParences = 0; 170 | $rightParences = 0; 171 | for($x = 0; $x < $remainLen; $x++) { 172 | if ($remainStr[$x] == '(') { 173 | $hasParences = true; 174 | $leftParences++; 175 | } elseif ($remainStr[$x] == ')') { 176 | $rightParences++; 177 | if (!$hasParences) { 178 | break; 179 | } elseif ($rightParences>$leftParences) { 180 | break; 181 | } 182 | } 183 | } 184 | 185 | //echo ": ", substr($remainStr, 0, $x), PHP_EOL; 186 | $newExpr = $spaces[1] . $newExpr . substr($remainStr, 0, $x) . ";\n"; 187 | //echo "newExpr= ", $newExpr, PHP_EOL; 188 | $remainStr = substr($remainStr, $x); 189 | $str = $newExpr . substr($str, 0, $mstr[1]+$offset) . $varName . $remainStr; 190 | $offset += (strlen($newExpr) + strlen($varName) - $lenMstr - $x); 191 | } elseif(preg_match('/(\s*)while\s*\(/', $str, $spaces)) { 192 | $varName = rtrim($matches[1][$k][0], " ="); 193 | $remainLen = strlen($remainStr); 194 | $hasParences = false; 195 | $leftParences = 0; 196 | $rightParences = 0; 197 | for($x = 0; $x < $remainLen; $x++) { 198 | if ($remainStr[$x] == '(') { 199 | $hasParences = true; 200 | $leftParences++; 201 | } elseif ($remainStr[$x] == ')') { 202 | $rightParences++; 203 | if (!$hasParences) { 204 | break; 205 | } elseif ($rightParences>$leftParences) { 206 | break; 207 | } 208 | } 209 | } 210 | 211 | //echo ": ", substr($remainStr, 0, $x), PHP_EOL; 212 | $newExpr = $spaces[1] . $newExpr . substr($remainStr, 0, $x) . ";\n"; 213 | //echo "newExpr= ", $newExpr, PHP_EOL; 214 | $remainStr = substr($remainStr, $x); 215 | $str = $newExpr . substr($str, 0, $mstr[1]+$offset) . $varName . $remainStr; 216 | $offset += (strlen($newExpr) + strlen($varName) - $lenMstr - $x); 217 | 218 | $whileEnd = $spaces[1] . '}'; 219 | for($xx = 0; $xx < count($this->currentFuncLines); $xx++) { 220 | if (strpos($this->currentFuncLines[$xx], $whileEnd) === 0) { 221 | break; 222 | } 223 | } 224 | $this->currentFuncLines[$xx-1] .= ("\n" . " " . $newExpr); 225 | } else { 226 | $str = substr($str, 0, $mstr[1]+$offset) . $newExpr . $remainStr; 227 | $offset += strlen($newExpr) - $lenMstr; 228 | } 229 | } 230 | 231 | if (preg_match('/(\s*)return /', $str, $returnMatch, PREG_OFFSET_CAPTURE)) { 232 | //print_r($returnMatch); 233 | $letExpr = substr($str, strlen($returnMatch[0][0]) + 4); 234 | //echo $letExpr,PHP_EOL; 235 | $lenExpr = strlen($letExpr); 236 | for($i=0; $i<$lenExpr; $i++) { 237 | if ($letExpr[$i] == '=') { 238 | break; 239 | } 240 | } 241 | $xvar = substr($letExpr, 0, $i); 242 | $letLine = $returnMatch[1][0] . 'let ' . $letExpr; 243 | $letLine .= ($returnMatch[1][0] . 'return ' . $xvar . ";\n"); 244 | $str = $letLine; 245 | } 246 | $hasLet = true; 247 | } 248 | //echo "typeof " . $matches[1][$k] . ' == "' . $type . '"', "\n"; 249 | } 250 | } 251 | 252 | return $str; 253 | } 254 | 255 | /** 256 | * 针对单行 257 | * @param [type] $str [description] 258 | * @return [type] [description] 259 | */ 260 | public function convertIsType($str) 261 | { 262 | $isTypeArr = [ 263 | '/\bis_array\s*\(([^ \)]+)\)/' => 'array', 264 | '/\bis_object\s*\(([^ \)]+)\)/' => 'object', 265 | '/\bis_callable\s*\(([^ \)]+)\)/' => 'callable', 266 | '/\bis_string\s*\(([^ \)]+)\)/' => 'string', 267 | '/\bis_integer\s*\(([^ \)]+)\)/' => 'integer', 268 | '/\bis_double\s*\(([^ \)]+)\)/' => 'double', 269 | '/\bis_float\s*\(([^ \)]+)\)/' => 'double', 270 | '/\bis_boolean\s*\(([^ \)]+)\)/' => 'boolean', 271 | '/\bis_int\s*\(([^ \)]+)\)/' => 'integer', 272 | '/\bis_resource\s*\(([^ \)]+)\)/' => 'resource', 273 | ]; 274 | 275 | foreach ($isTypeArr as $pattern => $type) { 276 | if (preg_match_all($pattern, $str, $matches, PREG_OFFSET_CAPTURE)) { 277 | //print_r($matches); 278 | $offset = 0; 279 | foreach($matches[0] as $k => $mstr) { 280 | //echo "typeof " . $matches[1][$k] . ' == "' . $type . '"', "\n"; 281 | $newExpr = "(typeof " . $matches[1][$k][0] . ' == "' . $type . '")'; 282 | $lenMstr = strlen($mstr[0]); 283 | $str = substr($str, 0, $mstr[1]+$offset) . $newExpr . substr($str, $offset+$mstr[1]+$lenMstr); 284 | $offset += strlen($newExpr) - $lenMstr; 285 | } 286 | } 287 | } 288 | 289 | if (preg_match_all('/\bis_number\s*\(([^ \)]+)\)/', $str, $matches, PREG_OFFSET_CAPTURE)) { 290 | $offset = 0; 291 | foreach ($matches[0] as $k => $mstr) { 292 | $newExpr = "(typeof " . $matches[1][$k][0] . ' == "integer" || typeof ' . $matches[1][$k][0] . ' == "double")'; 293 | $lenMstr = strlen($mstr[0]); 294 | $str = substr($str, 0, $mstr[1]+$offset) . $newExpr . substr($str, $offset+$mstr[1]+$lenMstr); 295 | $offset += strlen($newExpr) - $lenMstr; 296 | } 297 | } 298 | 299 | return $str; 300 | } 301 | 302 | /** 303 | * 针对单行 304 | * @param [type] $str [description] 305 | * @return [type] [description] 306 | */ 307 | public function convertEmpty($str) 308 | { 309 | $hasEmpty = preg_match_all('/\bempty\s*\(([^ \)]+)\)/', $str, $matches, PREG_OFFSET_CAPTURE); 310 | if ($hasEmpty) { 311 | $offset = 0; 312 | foreach ($matches[0] as $k => $mstr) { 313 | $newExpr = "(empty " . $matches[1][$k][0] . ')'; 314 | $lenMstr = strlen($mstr[0]); 315 | $str = substr($str, 0, $mstr[1]+$offset) . $newExpr . substr($str, $offset+$mstr[1]+$lenMstr); 316 | $offset += strlen($newExpr) - $lenMstr; 317 | } 318 | } 319 | 320 | return $str; 321 | } 322 | 323 | /** 324 | * 针对单行 325 | * @param [type] $str [description] 326 | * @return [type] [description] 327 | */ 328 | public function convertIsset($str) 329 | { 330 | $hasIsset = preg_match_all('/\bisset\s*\(([^ \)]+)\)/', $str, $matches, PREG_OFFSET_CAPTURE); 331 | if ($hasIsset) { 332 | $offset = 0; 333 | foreach ($matches[0] as $k => $mstr) { 334 | $newExpr = "(isset " . $matches[1][$k][0] . ')'; 335 | $lenMstr = strlen($mstr[0]); 336 | $str = substr($str, 0, $mstr[1]+$offset) . $newExpr . substr($str, $offset+$mstr[1]+$lenMstr); 337 | $offset += strlen($newExpr) - $lenMstr; 338 | } 339 | } 340 | 341 | return $str; 342 | } 343 | 344 | /** 345 | * 针对单行 346 | * @param [type] $str [description] 347 | * @return [type] [description] 348 | */ 349 | public function convertUnset($str) 350 | { 351 | $hasIsset = preg_match_all('/\bunset\s*\(([^\)]+)\)/', $str, $matches, PREG_OFFSET_CAPTURE); 352 | if ($hasIsset) { 353 | $offset = 0; 354 | foreach ($matches[0] as $k => $mstr) { 355 | if (strpos($matches[1][$k][0], ',')) { 356 | $newExpr = ''; 357 | $toUnsetArr = explode(',', $matches[1][$k][0]); 358 | foreach ($toUnsetArr as $v) { 359 | $newExpr .= ("unset " . $v . ";\n"); 360 | } 361 | } else { 362 | $newExpr = "unset " . $matches[1][$k][0] . ''; 363 | } 364 | 365 | $lenMstr = strlen($mstr[0]); 366 | $str = substr($str, 0, $mstr[1]+$offset) . $newExpr . substr($str, $offset+$mstr[1]+$lenMstr); 367 | $offset += strlen($newExpr) - $lenMstr; 368 | } 369 | } 370 | 371 | return $str; 372 | } 373 | 374 | /** 375 | * 针对单行 376 | * @param [type] $str [description] 377 | * @return [type] [description] 378 | */ 379 | public function convertQuote($str) 380 | { 381 | //$str = str_replace("'", '"', $str); 382 | $len = strlen($str); 383 | $i = 0; 384 | $inQuote = false; 385 | $inTimes = 0; 386 | $inDoubleQuote = false; 387 | $dqTimes = 0; 388 | while($i < $len) { 389 | if ($str[$i] == "'" && !$inDoubleQuote) { 390 | if (!$inQuote) { 391 | $str[$i] = '"'; 392 | $inQuote = true; 393 | $inTimes++; 394 | } else { 395 | //if ($i>0 && $str[$i-1] != '\\') { 396 | $str[$i] = '"'; 397 | $inQuote = false; 398 | $inTimes++; 399 | //} 400 | } 401 | } elseif ($str[$i] == '"') { 402 | if ($inQuote) { 403 | $str[$i] = "'"; 404 | //$str = substr($str, 0, $i) . '\"' . substr($str, $i+1); 405 | //$i++; 406 | //$len++; 407 | } else { 408 | if ($inDoubleQuote) { 409 | $inDoubleQuote = false; 410 | $dqTimes = 0; 411 | } else { 412 | $inDoubleQuote = true; 413 | $dqTimes++; 414 | } 415 | } 416 | } 417 | $i++; 418 | } 419 | 420 | return $str; 421 | } 422 | 423 | public function convertFuncArg($str) 424 | { 425 | return $this->convertQuote(preg_replace_callback('/(\w+)\s+\$(\w+)/', function($matches){ 426 | if (in_array($matches[2], $this->ignoreVars)) { 427 | return $matches[1] . ' $' . $matches[2]; // $this 428 | } elseif (in_array($matches[2], $this->keywords)) { 429 | return $matches[1] . ' ' . $this->varPrefix . $matches[2]; 430 | } else { 431 | return $matches[1] . ' ' . $matches[2]; 432 | } 433 | }, preg_replace_callback('/(\(|,\s*)\$(\w+)/', function($matches){ 434 | if (in_array($matches[2], $this->ignoreVars)) { 435 | return $matches[1] . 'var $' . $matches[2]; // $this 436 | } elseif (in_array($matches[2], $this->keywords)) { 437 | return $matches[1] . ' var ' . $this->varPrefix . $matches[2]; 438 | } else { 439 | return $matches[1] . ' var ' . $matches[2]; 440 | } 441 | }, $str))); 442 | } 443 | 444 | /** 445 | * 针对多行 446 | * @param [type] $str [description] 447 | * @return [type] [description] 448 | */ 449 | public function convertArray($str) 450 | { 451 | if (preg_match_all('/\barray\(/', $str, $matches, PREG_OFFSET_CAPTURE)) { 452 | $offset = 0; 453 | //print_r($matches);//exit(); 454 | $strLen = strlen($str); 455 | foreach ($matches[0] as $k => $mstr) { 456 | $i = $mstr[1] + strlen($mstr[0]) + $offset;$l = 0;$r = 0; 457 | while($i < $strLen) { 458 | if ($str[$i] == '(') { 459 | $l++; 460 | } elseif ($str[$i] == ')') { 461 | $r++; 462 | } 463 | 464 | if ($r-$l === 1) { 465 | $str[$i] = ']'; 466 | break; 467 | } 468 | $i++; 469 | } 470 | if ($i >= $strLen) { 471 | echo $this->currentFile, "\n"; 472 | exit(); 473 | } 474 | 475 | $newExpr = '['; 476 | $lenMstr = strlen($mstr[0]); 477 | $str = substr($str, 0, $mstr[1]+$offset) . $newExpr . substr($str, $offset+$mstr[1]+$lenMstr); 478 | $offset += strlen($newExpr) - $lenMstr; 479 | 480 | $strLen = strlen($str); 481 | } 482 | } 483 | 484 | return str_replace("=>", ":", $str); 485 | } 486 | 487 | /** 488 | * 转换for 489 | * @param [type] $lines [description] 490 | * @return [type] [description] 491 | */ 492 | public function convertFor($lines) 493 | { 494 | $totalLines = count($lines); 495 | for($i = 0; $i < $totalLines; $i++) { 496 | $hasFor = preg_match('/(\s*)\bfor\s*\(([^;]+);([^;]+);(.+)/', $lines[$i], $matches, PREG_OFFSET_CAPTURE); 497 | if ($hasFor) { 498 | //print_r($matches); 499 | $initLine = $matches[1][0] . trim($matches[2][0]) . "\n"; 500 | $lines[$i] = $matches[1][0] . 'while (' . trim($matches[3][0]) . ')'; 501 | if (preg_match('/\{\s*$/', $matches[4][0])) { 502 | $lines[$i] .= (' {' . "\n"); 503 | $matches[4][0] = rtrim($matches[4][0], "\r\n {"); 504 | } 505 | $matches[4][0] = rtrim($matches[4][0]); 506 | $incExpr = $matches[1][0] . ' ' . substr(ltrim($matches[4][0]), 0, -1) . ";\n"; 507 | 508 | array_splice($lines, $i, 0, $initLine); 509 | $i++; 510 | $totalLines++; 511 | 512 | for($j = $i; $j < $totalLines; $j++) { 513 | if(strpos($lines[$j], $matches[1][0] . '}') === 0) { 514 | array_splice($lines, $j, 0, $incExpr); 515 | $totalLines++; 516 | break; 517 | } 518 | } 519 | //print_r($matches); 520 | } 521 | } 522 | 523 | return $lines; 524 | } 525 | 526 | public function convertMagic($str) 527 | { 528 | $rules = [ 529 | '/\b__LINE__\b/' => $this->currentLine, 530 | '/\b__FILE__\b/' => $this->currentFile, 531 | '/\b__METHOD__\b/' => $this->currentMethod, 532 | '/\b__CLASS__\b/' => $this->currentClass . '::' . $this->currentMethod 533 | ]; 534 | 535 | foreach ($rules as $pattern => $replacement) { 536 | $str = preg_replace($pattern, '"' . $replacement . '"', $str); 537 | } 538 | 539 | return $str; 540 | } 541 | 542 | public function convertNamespace($str) 543 | { 544 | if (preg_match('#\byii(\\\\[0-9a-zA-Z_]+)+\b#', $str, $matches, PREG_OFFSET_CAPTURE)) { 545 | return substr($str, 0, $matches[0][1]) . implode("\\", array_map(function($v){return ucfirst($v);}, explode("\\", $matches[0][0]))) . substr($str, $matches[0][1]+strlen($matches[0][0])); 546 | } 547 | return $str; 548 | } 549 | 550 | /** 551 | * convert static::method or new static() 552 | * @param [type] $str [description] 553 | * @return [type] [description] 554 | */ 555 | public function convertStatic($str) 556 | { 557 | return preg_replace('/\bnew\s+static\(/', 'new ' . $this->currentClass . '(', preg_replace('/\bstatic::(\w+)/', "self::$1", $str)); 558 | } 559 | 560 | /** 561 | * convert Yii::app->a = b to let app = Yii::app; let app->a = b; 562 | * @param [type] $str [description] 563 | * @return [type] [description] 564 | */ 565 | public function convertStaticPointerSet($str) 566 | { 567 | if(preg_match('/([a-zA-Z_][a-zA-Z0-9_]*+)::([a-zA-Z_][a-zA-Z0-9_]*+)\->([^=]+)=([^=])/', $str, $matches)) { 568 | $this->staticLetLines[] = ' let ' . $matches[2] . ' = ' . $matches[1] . '::' . $matches[2] . ";\n"; 569 | print_r($this->staticLetLines); 570 | return preg_replace('/([a-zA-Z_][a-zA-Z0-9_]*+)::([a-zA-Z_][a-zA-Z0-9_]*+)\->([^=]+)=([^=])/', "$2->$3 = $4", $str); 571 | } 572 | 573 | return $str; 574 | } 575 | 576 | /** 577 | * catch (Exception $e) => catch Exception, $e 578 | * @param [type] $str [description] 579 | * @return [type] [description] 580 | */ 581 | public function convertTryCatch($str) 582 | { 583 | if (preg_match('/\bcatch\s*\((\\\?([a-zA-Z_][a-zA-Z0-9_]*+\\\)*[a-zA-Z_][a-zA-Z0-9_]*+)\s+(\$[a-zA-Z_][a-zA-Z0-9_]*+)\s*\)/', $str, $matches, PREG_OFFSET_CAPTURE)) { 584 | $this->lineFlag = 'catch'; 585 | $newCatch = 'catch ' . $matches[1][0] . ', ' . $matches[3][0]; 586 | return substr($str, 0, $matches[0][1]) . $newCatch . substr($str, $matches[0][1]+strlen($matches[0][0])); 587 | } 588 | 589 | return $str; 590 | } 591 | 592 | /** 593 | * convert list($a, $b, $c) = $this->getArr(); 594 | * @param [type] $str [description] 595 | * @return [type] [description] 596 | */ 597 | public function convertList($str) 598 | { 599 | if (preg_match('/(\s*)list\s*\(([^=]+)\)\s*=\s*([^;]+)/', $str, $matches)) { // 600 | $varArr = explode(',', $matches[2]); 601 | $tmpVar = ''; 602 | do { 603 | $tmpVar = '$tmpArr' . substr(str_shuffle('abcdefghijklmnopqrstuvwxyz0123456'), 0, 4); 604 | } while (in_array($tmpVar, $this->funcVars) || in_array($tmpVar, $this->tmpArrVars)); 605 | 606 | $this->tmpArrVars[] = $tmpVar; 607 | 608 | $newExpr[] = $matches[1] . 'var ' . $tmpVar . ' = ' . $matches[3] . ';'; 609 | foreach ($varArr as $v) { 610 | $v = trim($v); 611 | if (!empty($v)) { 612 | $newExpr[] = $matches[1] . 'let ' . $v . ' = array_shift(' . $tmpVar . ');'; 613 | } else { 614 | $newExpr[] = $matches[1] . 'array_shift(' . $tmpVar . ');'; 615 | } 616 | } 617 | 618 | $this->lineFlag = 'list'; 619 | 620 | return implode("\n", $newExpr) . "\n"; 621 | } 622 | 623 | return $str; 624 | } 625 | 626 | /** 627 | * 转换一行 628 | * @param [type] $line [description] 629 | * @return [type] [description] 630 | */ 631 | public function handleLine($line) 632 | { 633 | $convertors = [ 634 | 'convertAssigns', 635 | 'convertIsType', 636 | 'convertEmpty', 637 | 'convertIsset', 638 | 'convertUnset', 639 | 'convertQuote', 640 | 'convertVars', 641 | 'convertMagic', 642 | 'convertNamespace', 643 | 'convertStatic', 644 | ]; 645 | 646 | $line = $this->convertForeach($line); 647 | if ($this->lineFlag == 'foreach') { 648 | $this->lineFlag = ''; 649 | return $this->convertStatic($this->convertVars($this->convertQuote($line))); 650 | } 651 | 652 | $line = $this->convertTryCatch($line); 653 | if ($this->lineFlag == 'catch') { 654 | $this->lineFlag = ''; 655 | return $this->convertVars($line); 656 | } 657 | 658 | $line = $this->convertList($line); 659 | if ($this->lineFlag == 'list') { 660 | $this->lineFlag = ''; 661 | $convertors = [ 662 | //'convertAssigns', 663 | 'convertQuote', 664 | 'convertVars', 665 | 'convertMagic', 666 | 'convertNamespace', 667 | 'convertStatic', 668 | ]; 669 | foreach ($convertors as $convertor) { 670 | $line = $this->{$convertor}($line); 671 | } 672 | 673 | return $line; 674 | } 675 | 676 | foreach ($convertors as $convertor) { 677 | $line = $this->{$convertor}($line); 678 | } 679 | $this->lineFlag = ''; 680 | $line = $this->convertStaticPointerSet($line); 681 | 682 | return $line; 683 | } 684 | public function handleOther($str) 685 | { 686 | return $this->convertMagic($this->convertVars($this->convertQuote($str))); 687 | } 688 | /** 689 | * 转换一个函数 690 | * @param [type] $lines [description] 691 | * @return [type] [description] 692 | */ 693 | public function handleFunc($lines, $spaceStr) 694 | { 695 | $args = $this->getArgs($lines[0]); 696 | $funcStr = implode('', $lines); 697 | $vars = $this->getVars($funcStr); 698 | 699 | $this->funcVars = $vars; 700 | $this->tmpArrVars = []; 701 | 702 | $keywords = ['$this', '$_GET', '$_POST', '$_SERVER', '$_FILES', '$_COOKIE', '$_SESSION']; 703 | 704 | $toAnounceVars = array_merge(array_diff($vars, array_merge($args, $keywords))); 705 | $funcBegin = 0; 706 | if (count($toAnounceVars) > 0) { 707 | $announceLine = $spaceStr . ' var ' . implode(', ', $toAnounceVars) . ';' . "\n"; 708 | //$funcBegin = 0; 709 | while (true) { 710 | if (preg_match('/\)\s*\{/', $lines[$funcBegin]) || preg_match('/\s*\{/', $lines[$funcBegin])) { 711 | break; 712 | } 713 | $funcBegin++; 714 | } 715 | array_splice($lines, $funcBegin+1, 0, $announceLine); 716 | } 717 | 718 | $lines = $this->convertFor($lines); 719 | 720 | $totalLines = count($lines); 721 | $lines[0] = $this->convertMagic($this->convertFuncArg($lines[0])); 722 | 723 | $this->currentFuncLines = $lines; 724 | for ($i = 1; $i < $totalLines; $i++) { 725 | $this->currentLine = $this->currentLine + 1; 726 | $lines[$i] = $this->handleLine($this->currentFuncLines[$i]); 727 | } 728 | 729 | // for static let expression 730 | if (!empty($this->staticLetLines)) { 731 | $this->staticLetLines = array_unique($this->staticLetLines); 732 | 733 | $i = 2; 734 | foreach ($this->staticLetLines as $letLine) { 735 | array_splice($lines, $funcBegin + $i, 0, $spaceStr . $letLine); 736 | $i++; 737 | } 738 | } 739 | 740 | $funcStr = implode('', $lines); 741 | 742 | if (!empty($this->staticLetLines)) { 743 | $funcStr = preg_replace('/\b([a-zA-Z_][a-zA-Z0-9_]*+)::([a-zA-Z_][a-zA-Z0-9_]*+)\->/', "$2->", $funcStr); 744 | } 745 | 746 | $this->staticLetLines = []; 747 | $this->currentStaticVars = []; 748 | 749 | return $funcStr; 750 | } 751 | 752 | public function handleFile($filein) 753 | { 754 | $firstFuncStart = 0; 755 | $classLineStart = 0; 756 | $foundFunction = false; 757 | $otherPropertyDef = []; 758 | 759 | $this->currentFile = basename($filein); 760 | $this->currentClass = pathinfo($this->currentFile, PATHINFO_FILENAME); 761 | 762 | echo "handling File ", $filein, "\n"; 763 | $lines = file($filein); 764 | 765 | $resultLines = []; 766 | $totalLines = count($lines); 767 | for($i = 1; $i < $totalLines;) { 768 | if (preg_match('/^\s*\/\*/', $lines[$i])) { 769 | //$resultLines[] = $lines[$i]; 770 | $i++; 771 | while ($i<$totalLines) { 772 | //$resultLines[] = $lines[$i]; 773 | if (preg_match('/\*\/\s*$/', $lines[$i++])) { 774 | break; 775 | } 776 | } 777 | } else { 778 | if (preg_match('/(\s*)(public|private|protected)?\s+(static\s+)?function\s+(?P\w+)\(/', $lines[$i], $matches)) { 779 | $func = []; 780 | if (!preg_match('/;$/', rtrim($lines[$i]))) { 781 | $func[] = $lines[$i]; 782 | $j = $i + 1; 783 | while ($j < $totalLines) { 784 | $func[] = $lines[$j]; 785 | if (strpos($lines[$j++], $matches[1] . '}') === 0) { 786 | break; 787 | } else { 788 | } 789 | } 790 | if ($j >= $totalLines) { 791 | echo $filein, ' Line: ', $j, ' TotalLines: ', $totalLines, "\n"; 792 | //exit("End"); 793 | } 794 | $i = $j; 795 | 796 | $this->currentMethod = $matches['methodname']; 797 | $this->currentLine = $i; 798 | $resultLines[] = $this->handleFunc($func, $matches[1]); 799 | } else { 800 | $resultLines[] = $this->convertFuncArg($lines[$i]); 801 | $i++; 802 | } 803 | 804 | if (!$foundFunction) { 805 | $firstFuncStart = count($resultLines); 806 | $foundFunction = true; 807 | } 808 | } else { 809 | if (strpos($lines[$i], "namespace ") === 0) { 810 | $namespaceLine = substr(rtrim($lines[$i], ";\r\n "), 10); 811 | $namespaceLine = implode("\\", array_map(function($v){return ucfirst($v);}, explode("\\", $namespaceLine))); 812 | 813 | $resultLines[] = "namespace " . $namespaceLine . ";\n"; 814 | } elseif (strpos($lines[$i], "use ") === 0) { 815 | $useLine = substr(rtrim($lines[$i], ";\r\n "), 4); 816 | $useLine = implode("\\", array_map(function($v){return ucfirst($v);}, explode("\\", $useLine))); 817 | 818 | $resultLines[] = "use " . $useLine . ";\n"; 819 | } elseif (preg_match('/^(abstract )?class (?P\w+)/', $lines[$i], $matches)) { 820 | $resultLines[] = $lines[$i]; 821 | //$this->currentClass = $matches['classname']; 822 | $classLineStart = count($resultLines); 823 | } elseif ($foundFunction && preg_match('/(\s*)(public|private|protected)?\s+(static\s+)?\$\w+/', $lines[$i])) { 824 | $otherPropertyDef[] = str_replace('$', '', $lines[$i]); 825 | } else { 826 | $resultLines[] = $this->handleOther($lines[$i]); 827 | } 828 | 829 | $i++; 830 | } 831 | } 832 | } 833 | 834 | if (!empty($otherPropertyDef)) { 835 | foreach ($otherPropertyDef as $propertyDef) { 836 | array_splice($resultLines, $firstFuncStart-1, 0, $propertyDef); 837 | } 838 | } 839 | return $this->convertArray(implode('', $resultLines)); 840 | } 841 | 842 | public function handleDir($dir, $outDir) { 843 | $dh = opendir($dir); 844 | 845 | while ($file = readdir($dh)) { 846 | if (pathinfo($file, PATHINFO_EXTENSION) == "php") { 847 | if (!file_exists($outDir)) { 848 | mkdir($outDir); 849 | } 850 | $outFile = $outDir . DIRECTORY_SEPARATOR . pathinfo($file, PATHINFO_FILENAME) . ".zep"; 851 | file_put_contents($outFile, $this->handleFile($dir . DIRECTORY_SEPARATOR . $file)); 852 | echo $dir . DIRECTORY_SEPARATOR . $file , " finished!", "\n"; 853 | } else if (is_dir($dir . DIRECTORY_SEPARATOR . $file) && $file != "." && $file != "..") { 854 | //closedir($dh); 855 | //echo "in dir ", $file, "\n"; 856 | $this->handleDir($dir . DIRECTORY_SEPARATOR . $file, $outDir . DIRECTORY_SEPARATOR . $file); 857 | } 858 | 859 | } 860 | 861 | closedir($dh); 862 | } 863 | } 864 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # php2zep 2 | php2zep is a tool that translate php language into zephir language 3 | 4 | # Install & Usage 5 | 6 | > ``` 7 | > git clone https://github.com/springlchy/php2zep 8 | > ``` 9 | 10 | ​ Then, require the Php2Zep.php. 11 | 12 | > ``` 13 | > 15 | > define('APP_DIR', dirname(__DIR__)); 16 | > 17 | > require APP_DIR . "/Php2Zep.php"; 18 | > 19 | > $inputDir = APP_DIR . "/examples/php/myapp"; // assume that this is the directory of your application which is written by php 20 | > $outputDir = APP_DIR . "/examples/zep/myapp"; // destination directory, .zep 21 | > 22 | > $obj = new Php2Zep(); 23 | > 24 | > $obj->handleDir($inputDir, $outputDir); 25 | > ``` 26 | 27 | # Example 28 | 29 | In this example, we'll write a simple MVC applicataion using PHP, and then, translate them into zephir scripts, then build an extension. And at last, run the application with several lines of code. (Linux Only) 30 | 31 | ## Step 1: Install Zephir 32 | 33 | Of course we must have Zephir installed. See [Zephir](https://zephir-lang.com) 34 | 35 | ## Step 2: Initialize a Zephir extension 36 | 37 | > ``` zephir myapp 38 | > cd /home/theta/zephir 39 | > zephir myapp 40 | > ``` 41 | 42 | Then we have the directory structure as below: 43 | 44 | >\+ myapp 45 | > 46 | > | - config.json 47 | > 48 | > | + ext 49 | > 50 | > | + myapp (*we'll put translated zephir scripts here, assume this directory is /home/theta/zephir/myapp/myapp*) 51 | 52 | ## Step 3: create php application 53 | 54 | We have the structure as below: 55 | 56 | >\+ myapp (*assume this directory is /home/theta/php/myapp*) 57 | > 58 | >​ | + controllers 59 | > 60 | >​ | - UserController.php 61 | > 62 | >​ | + models 63 | > 64 | >​ | - UserModel.php 65 | > 66 | >​ | - Application.php 67 | 68 | * UserModel.php 69 | 70 | > ``` php 71 | > 73 | > namespace myapp\models; 74 | > 75 | > class UserModel 76 | > { 77 | > ... 78 | > } 79 | > ``` 80 | 81 | See the **"examples"** directory for more detail. 82 | 83 | * UserController.php 84 | 85 | > ``` php 86 | > 88 | > namespace myapp\controllers; 89 | > 90 | > use myapp\models\UserModel; 91 | > 92 | > class UserController 93 | > { 94 | > private $_model; 95 | > 96 | > public function __construct() 97 | > { 98 | > $this->_model = new UserModel(); 99 | > } 100 | > ... 101 | > } 102 | > ``` 103 | 104 | See the **"examples"** directory for more detail. 105 | 106 | * Application.php 107 | 108 | > ``` php 109 | > 111 | > namespace myapp; 112 | > 113 | > class Application 114 | > { 115 | > private $_defaultControllerNameSpace = "\Myapp\Controllers"; 116 | > private $_defaultController = "user"; 117 | > private $_DefaultAction = "index"; 118 | > 119 | > private $_controllerSuffix = "Controller"; 120 | > private $_actionSuffix = "Action"; 121 | > 122 | > public function __construct() 123 | > { 124 | > } 125 | > public function parseRoute() 126 | > { 127 | > ... 128 | > } 129 | > 130 | > public function run() 131 | > { 132 | > ... 133 | > } 134 | > } 135 | > ``` 136 | > 137 | 138 | See the **"examples"** directory for more detail. 139 | 140 | 141 | ## Step 4: Translate php into zephir using php2zep 142 | 143 | ​ convert.php 144 | 145 | > ``` php 146 | > $inputDir = "/home/theta/php/myapp"; 147 | > $outputDir = "/home/theta/zephir/myapp/myapp"; 148 | > 149 | > $obj = new Php2Zep(); 150 | > 151 | > $obj->handleDir($inputDir, $outputDir); 152 | > ``` 153 | 154 | ​ run. 155 | 156 | > ``` shell 157 | > php convert.php 158 | > ``` 159 | 160 | ​ move to /home/theta/zephir/myapp/myapp, we can see: 161 | 162 | >\+ myapp 163 | > 164 | >​ | + controllers 165 | > 166 | >​ | - UserController.zep 167 | > 168 | >​ | + models 169 | > 170 | >​ | - UserModel.zep 171 | > 172 | >​ | - Application.zep 173 | 174 | ## Step 5: Install Extension 175 | 176 | > ``` 177 | > cd /home/theta/zephir/myapp 178 | > sudo zephir install 179 | > ``` 180 | 181 | ​ Add **myapp.so** to your php.ini 182 | 183 | > ``` 184 | > extension=myapp.so 185 | > ``` 186 | 187 | ​ Check 188 | 189 | > ``` 190 | > php -m | grep "myapp" // output: myapp 191 | > ``` 192 | 193 | ## Step 6: Test 194 | ​ Write a bootstrap script ( saving as index.php): 195 | 196 | > ``` php 197 | > $app = new \Myapp\Application(); 199 | > echo json_encode($app->run()); 200 | > ``` 201 | 202 | ​ Restart phpfpm 203 | 204 | > ```shell 205 | > killall phpfpm 206 | > phpfpm 207 | > ``` 208 | 209 | ​ Visit `http://localhost/myapp/index.php`, output: 210 | 211 | > ``` 212 | > [{"id":1,"name":"Jack","job":"Engineer"},{"id":2,"name":"Lee","job":"Actor"},{"id":3,"name":"Bill","job":"Programmer"}] 213 | > ``` 214 | 215 | **Congratulations! It Works!** 216 | 217 | -------------------------------------------------------------------------------- /examples/php/myapp/Application.php: -------------------------------------------------------------------------------- 1 | _defaultController; 21 | $action = $this->_DefaultAction; 22 | 23 | $r = isset($_GET['r']) ? $_GET['r'] : ''; 24 | if (!empty($r)) { 25 | $segments = explode("/", $r); 26 | if (count($segments) == 1) { 27 | $controller = $segments[0]; 28 | } else { 29 | list($controller, $action) = $segments; 30 | } 31 | } 32 | 33 | return [$controller, $action]; 34 | } 35 | 36 | public function run() 37 | { 38 | list($controller, $action) = $this->parseRoute(); 39 | 40 | $className = $this->_defaultControllerNameSpace . "\\" . ucfirst($controller) . $this->_controllerSuffix; 41 | 42 | try { 43 | if (!class_exists($className)) { 44 | throw new \Exception($className . " does not exist!"); 45 | } 46 | 47 | $methodName = $action . $this->_actionSuffix; 48 | 49 | $controllerRef = new \ReflectionClass($className); 50 | if (!($controllerRef->hasMethod($methodName))) { 51 | throw new \Exception($className . " does not have method " . $methodName); 52 | } 53 | 54 | $controllerObj = $controllerRef->newInstance(); 55 | $methodRef = $controllerRef->getMethod($methodName); 56 | if (!($methodRef->isPublic())) { 57 | throw new \Exception($methodName . " is not public!"); 58 | } 59 | } catch (\Exception $e) { 60 | // do nothing 61 | } 62 | 63 | 64 | return $methodRef->invoke($controllerObj); 65 | } 66 | } -------------------------------------------------------------------------------- /examples/php/myapp/controllers/UserController.php: -------------------------------------------------------------------------------- 1 | _model = new UserModel(); 14 | } 15 | 16 | public function indexAction() 17 | { 18 | if (isset($_GET['id'])) { 19 | return $this->_model->findById(intval($_GET['id'])); 20 | } 21 | 22 | return $this->_model->getAll(); 23 | } 24 | 25 | public function addAction() 26 | { 27 | if (!isset($_POST["name"]) || !isset($_POST["job"])) { 28 | return [1, "name or job is empty"]; 29 | } 30 | 31 | $this->_model->addOne($_POST); 32 | return $this->_model->getAll(); 33 | } 34 | 35 | public function editAction() 36 | { 37 | if (!isset($_POST["name"]) || !isset($_POST["job"])) { 38 | return [1, "name or job is empty"]; 39 | } 40 | 41 | $this->_model->replaceOne($_POST); 42 | return $this->_model->getAll(); 43 | } 44 | 45 | public function dropAction() 46 | { 47 | $this->_model->dropOne(intval($_GET["id"])); 48 | return $this->_model->getAll(); 49 | } 50 | } -------------------------------------------------------------------------------- /examples/php/myapp/models/UserModel.php: -------------------------------------------------------------------------------- 1 | 1, 10 | "name" => "Jack", 11 | "job" => "Engineer" 12 | ], 13 | [ 14 | "id" => 2, 15 | "name" => "Lee", 16 | "job" => "Actor" 17 | ], 18 | [ 19 | "id" => 3, 20 | "name" => "Bill", 21 | "job" => "Programmer" 22 | ] 23 | ]; 24 | 25 | public function getAll() 26 | { 27 | return $this->_users; 28 | } 29 | 30 | public function getById($id) 31 | { 32 | $user = null; 33 | foreach ($this->_users as $v) { 34 | if ($v["id"] == $id) { 35 | $user = $v; 36 | break; 37 | } 38 | } 39 | 40 | return $user; 41 | } 42 | 43 | public function addOne($user) 44 | { 45 | $u = [ 46 | "id" => count($this->_users), 47 | "name" => $user["name"], 48 | "job" => $user["job"] 49 | ]; 50 | 51 | $this->_users[] = $u; 52 | return true; 53 | } 54 | 55 | public function replaceOne($user) 56 | { 57 | $result = false; 58 | foreach ($this->_users as $k => $v) { 59 | if ($v["id"] == $user["id"]) { 60 | $this->_users[$k] = $user; 61 | $result = true; 62 | break; 63 | } 64 | } 65 | 66 | return $result; 67 | } 68 | 69 | public function dropOne($id) 70 | { 71 | $result = false; 72 | foreach ($this->_users as $k => $v) { 73 | if ($v["id"] == $id) { 74 | array_splice($this->_users, $k, 0); 75 | $result = true; 76 | break; 77 | } 78 | } 79 | 80 | return $result; 81 | } 82 | } -------------------------------------------------------------------------------- /examples/zep/myapp/Application.zep: -------------------------------------------------------------------------------- 1 | 2 | namespace Myapp; 3 | 4 | class Application 5 | { 6 | private _defaultControllerNameSpace = "\Myapp\Controllers"; 7 | private _defaultController = "user"; 8 | private _DefaultAction = "index"; 9 | 10 | private _controllerSuffix = "Controller"; 11 | private _actionSuffix = "Action"; 12 | 13 | public function __construct() 14 | { 15 | } 16 | 17 | public function parseRoute() 18 | { 19 | var controller, action, r, segments; 20 | let controller = this->_defaultController; 21 | let action = this->_DefaultAction; 22 | 23 | let r = (isset _GET["r"]) ? _GET["r"] : ""; 24 | if (!(empty r)) { 25 | let segments = explode("/", r); 26 | if (count(segments) == 1) { 27 | let controller = segments[0]; 28 | } else { 29 | var tmpArrbyt5 = segments; 30 | let controller = array_shift(tmpArrbyt5); 31 | let action = array_shift(tmpArrbyt5); 32 | } 33 | } 34 | 35 | return [controller, action]; 36 | } 37 | 38 | public function run() 39 | { 40 | var controller, action, className, methodName, controllerRef, controllerObj, methodRef, e; 41 | var tmpArrmna1 = this->parseRoute(); 42 | let controller = array_shift(tmpArrmna1); 43 | let action = array_shift(tmpArrmna1); 44 | 45 | let className = this->_defaultControllerNameSpace . "\\" . ucfirst(controller) . this->_controllerSuffix; 46 | 47 | try { 48 | if (!class_exists(className)) { 49 | throw new \Exception(className . " does not exist!"); 50 | } 51 | 52 | let methodName = action . this->_actionSuffix; 53 | 54 | let controllerRef = new \ReflectionClass(className); 55 | if (!(controllerRef->hasMethod(methodName))) { 56 | throw new \Exception(className . " does not have method " . methodName); 57 | } 58 | 59 | let controllerObj = controllerRef->newInstance(); 60 | let methodRef = controllerRef->getMethod(methodName); 61 | if (!(methodRef->isPublic())) { 62 | throw new \Exception(methodName . " is not public!"); 63 | } 64 | } catch \Exception, e { 65 | // do nothing 66 | } 67 | 68 | 69 | return methodRef->invoke(controllerObj); 70 | } 71 | } -------------------------------------------------------------------------------- /examples/zep/myapp/controllers/UserController.zep: -------------------------------------------------------------------------------- 1 | 2 | namespace Myapp\Controllers; 3 | 4 | use Myapp\Models\UserModel; 5 | 6 | class UserController 7 | { 8 | private _model; 9 | 10 | public function __construct() 11 | { 12 | let this->_model = new UserModel(); 13 | } 14 | 15 | public function indexAction() 16 | { 17 | if ((isset _GET["id"])) { 18 | return this->_model->findById(intval(_GET["id"])); 19 | } 20 | 21 | return this->_model->getAll(); 22 | } 23 | 24 | public function addAction() 25 | { 26 | if (!(isset _POST["name"]) || !(isset _POST["job"])) { 27 | return [1, "name or job is empty"]; 28 | } 29 | 30 | this->_model->addOne(_POST); 31 | return this->_model->getAll(); 32 | } 33 | 34 | public function editAction() 35 | { 36 | if (!(isset _POST["name"]) || !(isset _POST["job"])) { 37 | return [1, "name or job is empty"]; 38 | } 39 | 40 | this->_model->replaceOne(_POST); 41 | return this->_model->getAll(); 42 | } 43 | 44 | public function dropAction() 45 | { 46 | this->_model->dropOne(intval(_GET["id"])); 47 | return this->_model->getAll(); 48 | } 49 | } -------------------------------------------------------------------------------- /examples/zep/myapp/models/UserModel.zep: -------------------------------------------------------------------------------- 1 | 2 | namespace Myapp\Models; 3 | 4 | class UserModel 5 | { 6 | private _users = [ 7 | [ 8 | "id" : 1, 9 | "name" : "Jack", 10 | "job" : "Engineer" 11 | ], 12 | [ 13 | "id" : 2, 14 | "name" : "Lee", 15 | "job" : "Actor" 16 | ], 17 | [ 18 | "id" : 3, 19 | "name" : "Bill", 20 | "job" : "Programmer" 21 | ] 22 | ]; 23 | 24 | public function getAll() 25 | { 26 | return this->_users; 27 | } 28 | 29 | public function getById( var id) 30 | { 31 | var user, v; 32 | let user = null; 33 | for v in this->_users { 34 | if (v["id"] == id) { 35 | let user = v; 36 | break; 37 | } 38 | } 39 | 40 | return user; 41 | } 42 | 43 | public function addOne( var user) 44 | { 45 | var u; 46 | let u = [ 47 | "id" : count(this->_users), 48 | "name" : user["name"], 49 | "job" : user["job"] 50 | ]; 51 | 52 | let this->_users[] = u; 53 | return true; 54 | } 55 | 56 | public function replaceOne( var user) 57 | { 58 | var result, k, v; 59 | let result = false; 60 | for k,v in this->_users { 61 | if (v["id"] == user["id"]) { 62 | let this->_users[k] = user; 63 | let result = true; 64 | break; 65 | } 66 | } 67 | 68 | return result; 69 | } 70 | 71 | public function dropOne( var id) 72 | { 73 | var result, k, v; 74 | let result = false; 75 | for k,v in this->_users { 76 | if (v["id"] == id) { 77 | array_splice(this->_users, k, 0); 78 | let result = true; 79 | break; 80 | } 81 | } 82 | 83 | return result; 84 | } 85 | } -------------------------------------------------------------------------------- /test/test.php: -------------------------------------------------------------------------------- 1 | handleDir($inputDir, $outputDir); -------------------------------------------------------------------------------- /test/testList.php: -------------------------------------------------------------------------------- 1 | convertList($str); 12 | -------------------------------------------------------------------------------- /test/testStaticSet.php: -------------------------------------------------------------------------------- 1 | a[3] = 4'; 10 | 11 | echo $obj->handleLine($str); -------------------------------------------------------------------------------- /test/testTryCatch.php: -------------------------------------------------------------------------------- 1 | convertTryCatch($str), PHP_EOL; 18 | } 19 | --------------------------------------------------------------------------------