11<?php declare (strict_types=1 );
22
3-
43namespace Swoft \Proxy ;
54
6-
7- use function file_put_contents ;
8- use const PHP_EOL ;
9- use function sprintf ;
105use Swoft \Proxy \Ast \Parser ;
116use Swoft \Proxy \Ast \Visitor \Visitor ;
12- use Swoft \Proxy \Contract \VisitorInterface ;
137use Swoft \Proxy \Exception \ProxyException ;
148use Swoft \Stdlib \Helper \Sys ;
9+ use function file_put_contents ;
10+ use function sprintf ;
11+ use const PHP_EOL ;
1512
13+ /**
14+ * Class Proxy
15+ *
16+ * @package Swoft\Proxy
17+ */
1618class Proxy
1719{
20+ /**
21+ * Optimize logic
22+ * - Save classes that have been parsed and generated to avoid repeated parsing and loading
23+ *
24+ * @var array
25+ */
26+ private static $ caches = [];
27+
1828 /**
1929 * New class name by proxy
2030 *
@@ -26,19 +36,17 @@ class Proxy
2636 */
2737 public static function newClassName (string $ className , Visitor $ visitor ): string
2838 {
29- $ parser = new Parser ();
30-
31- $ visitorClassName = get_class ($ visitor );
32- if (!$ visitor instanceof VisitorInterface) {
33- throw new ProxyException (
34- sprintf ('%s is not instance of %s ' , $ visitorClassName , VisitorInterface::class)
35- );
39+ if (isset (self ::$ caches [$ className ])) {
40+ return self ::$ caches [$ className ];
3641 }
3742
38- $ parser ->addNodeVisitor ($ visitorClassName , $ visitor );
43+ $ parser = new Parser ();
44+ $ parser ->addNodeVisitor (get_class ($ visitor ), $ visitor );
3945
4046 $ proxyCode = $ parser ->parse ($ className );
4147 $ proxyName = $ visitor ->getProxyName ();
48+ // New proxy class name
49+ $ newClassName = $ visitor ->getProxyClassName ();
4250
4351 // Proxy file and proxy code
4452 $ proxyFile = sprintf ('%s/%s.php ' , Sys::getTempDir (), $ proxyName );
@@ -50,18 +58,28 @@ public static function newClassName(string $className, Visitor $visitor): string
5058 throw new ProxyException (sprintf ('Proxy file(%s) generate fail ' , $ proxyFile ));
5159 }
5260
53- // Load proxy php file
61+ // Load new proxy class file.
62+ self ::loadProxyClass ($ proxyFile );
63+
64+ // Ensure proxy class is loaded
65+ if (!class_exists ($ newClassName )) {
66+ throw new ProxyException (sprintf ('Proxy class(%s) is not exist! ' , $ newClassName ));
67+ }
68+
69+ // Add cache, mark has been required.
70+ self ::$ caches [$ className ] = $ newClassName ;
71+ return $ newClassName ;
72+ }
73+
74+ /**
75+ * @param string $proxyFile
76+ */
77+ private static function loadProxyClass (string $ proxyFile ): void
78+ {
79+ /** @noinspection PhpIncludeInspection */
5480 require $ proxyFile ;
5581
5682 // Remove proxy file
5783 unlink ($ proxyFile );
58-
59- // Proxy class
60- $ proxyClassName = $ visitor ->getProxyClassName ();
61- if (!class_exists ($ proxyClassName )) {
62- throw new ProxyException (sprintf ('Proxy class(%s) is not exist! ' , $ proxyClassName ));
63- }
64-
65- return $ proxyClassName ;
6684 }
67- }
85+ }
0 commit comments