Skip to content

Remove unintended Beobles\ namespace prefix from View engine#6

Draft
Copilot wants to merge 3 commits into
copilot/refatoracao-arquitetural-view-enginefrom
copilot/remove-eval-implement-file-based-compilation
Draft

Remove unintended Beobles\ namespace prefix from View engine#6
Copilot wants to merge 3 commits into
copilot/refatoracao-arquitetural-view-enginefrom
copilot/remove-eval-implement-file-based-compilation

Conversation

Copy link
Copy Markdown

Copilot AI commented Jun 3, 2026

The namespace migration introduced an unintended Beobles\ prefix in the template engine classes. This PR aligns all affected references back to the repository’s namespace convention (Core\View\...) to restore consistent class resolution.

  • Namespace normalization across source

    • Replaced Beobles\Core\View\... with Core\View\... in src/Core/View/** namespaces and imports.
    • Updated generated compiled-template header namespace/imports in Compiler::generateHeader() to emit Core\View\Compiled.
  • Autoload alignment

    • Updated the PSR-4 prefix in autoload.php from Beobles\Core\View\ to Core\View\.
  • Usage/docs consistency

    • Updated consumer-facing references (example and README) to import Core\View\Engine.
// Before
use Beobles\Core\View\Engine;

// After
use Core\View\Engine;
Original prompt

🚀 Professional Template Rendering - Remove eval(), Implement File-Based Compilation

Problema Atual

Seu Renderer usa eval() - inseguro, lento, não debugável, unprofessional.

// ❌ ERRADO (eval):
eval('?>' . $compiledCode);

Solução: Twig/Laravel Pattern

Como funciona em Twig/Laravel:

  1. Compilar templatePHP válido
  2. Escrever em arquivo no cache directory
  3. Include com namespace isolado (não eval)
  4. Versionamento & invalidação inteligentes
  5. Stack traces corretos para debugging

Estrutura de Cache

cache/
├── 5a8f3d2e1c4b9f7a.php          # Compiled template
├── 5a8f3d2e1c4b9f7a.meta         # Metadata (path, hash, deps)
└── manifest.json                  # Version tracking

Arquivo Compilado Exemplo

<?php
// cache/5a8f3d2e1c4b9f7a.php

namespace Core\View\Compiled;

use Core\View\Engine;

/**
 * Compiled from: templates/Home/Home.html
 * Compiled at: 2026-06-02 21:19:23
 * Hash: sha256:abc123...
 */
class TemplateAbc123 
{
    public function render(array $data = [], Engine $engine = null): string
    {
        $output = '';
        
        // Inject scope
        foreach ($data as $__name => $__value) {
            $$__name = $__value;
        }
        
        $output .= '<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>';
        $output .= $engine->escape($title ?? "", 'html');
        $output .= '</title>
</head>
<body>
    
</body>
</html>';
        
        return $output;
    }
}

Invocação

// Renderer apenas faz include + method call
$class = require $cacheFile; // Returns class path
$template = new $class();
return $template->render($data, $engine);

Implementação Completa

1. CompiledTemplate Base Class

<?php
// src/Core/View/CompiledTemplate.php

namespace Core\View;

abstract class CompiledTemplate
{
    abstract public function render(array $data = [], Engine $engine = null): string;
    
    protected function escape(mixed $value, string $context = 'html'): string
    {
        if ($engine === null) {
            return (string)$value;
        }
        return $engine->escape($value, $context);
    }
}

2. Compiler - Generate Class-Based Code

<?php
// src/Core/View/Compiler.php

namespace Core\View;

class Compiler
{
    private string $className;
    private string $sourceFile;
    
    public function compile(array $nodes, string $sourceFile = ''): string
    {
        $this->sourceFile = $sourceFile;
        $this->className = 'Template' . hash('crc32', $sourceFile);
        
        $code = $this->generateHeader();
        $code .= $this->generateClassStart();
        $code .= $this->generateRenderMethod($nodes);
        $code .= $this->generateClassEnd();
        
        return $code;
    }
    
    private function generateHeader(): string
    {
        return <<<'PHP'
<?php

namespace Core\View\Compiled;

use Core\View\Engine;
use Core\View\CompiledTemplate;

/**
 * Auto-generated compiled template
 * Source: {source}
 * Generated: {date}
 */
PHP . sprintf(
            "\n * Source: %s\n * Generated: %s\n */\n\n",
            $this->sourceFile,
            date('Y-m-d H:i:s')
        );
    }
    
    private function generateClassStart(): string
    {
        return <<<PHP
class {$this->className} extends CompiledTemplate
{
    private Engine \$__engine;
    
    public function render(array \$data = [], Engine \$engine = null): string
    {
        \$this->__engine = \$engine;
        \$output = '';
        
        // Inject data into scope
        extract(\$data, EXTR_SKIP);
        
PHP;
    }
    
    private function generateRenderMethod(array $nodes): string
    {
        $code = '';
        
        foreach ($nodes as $node) {
            $code .= $this->compileNode($node);
        }
        
        return $code;
    }
    
    private function generateClassEnd(): string
    {
        return <<<'PHP'

        return $output;
    }
}

PHP;
    }
    
    private function compileNode(object $node): string
    {
        $class = (new \ReflectionClass($node))->getShortName();
        
        return match ($class) {
            'TextNode' => $this->compileText($node),
            'ExpressionNode' => $this->compileExpression($node),
            'RawNode' => $this->compileRaw($node),
            'ComponentNode' => $this->compileComponent($node),
            'IfNode' => $this->compileIf($node),
            'ForeachNode' => $this->compileForeach($node),
            'BlockNode' => $this->compileBlock($node),
            default => ''
        };
    }
    
    private function compileText(object $node): string
    {
        $escaped = addslashes($node->value);
        return "\$output .= '{$escaped}';\n";
    }
    
    private function compileExpression(object $node): string
    {
        $expr = $this->transformExpression($node->value);
   ...

</details>



<!-- START COPILOT CODING AGENT SUFFIX -->

*This pull request was created from Copilot chat.*
>

Copilot AI changed the title [WIP] Remove eval and implement file-based compilation for templates Replace eval-based rendering with class-backed compiled template cache Jun 3, 2026
Copilot AI requested a review from beobles June 3, 2026 00:28
Copilot AI changed the title Replace eval-based rendering with class-backed compiled template cache Remove unintended Beobles\ namespace prefix from View engine Jun 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants