diff --git a/CHANGELOG b/CHANGELOG index 49843b72c..e1615c91d 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,7 +1,8 @@ -# 3.29.1 (2026-XX-XX) +# 3.30.0 (2026-XX-XX) * Fix the deprecation about omitting parentheses when calling a macro being reported twice for the same call * Add the macro name to the deprecation about omitting parentheses when calling a macro + * Deprecate cloning a `Twig\Environment` instance # 3.29.0 (2026-09-18) diff --git a/doc/deprecated.rst b/doc/deprecated.rst index 668343c27..3f7e8b4ba 100644 --- a/doc/deprecated.rst +++ b/doc/deprecated.rst @@ -475,6 +475,11 @@ Testing Utilities Environment ----------- +* Cloning a ``Twig\Environment`` instance is deprecated as of Twig 3.30 and will + throw in Twig 4.0. A clone keeps the templates and runtimes created by the + original environment, and those resolve their globals, extensions, and charset + against the environment that created them. Build a new environment instead. + * The ``Twig\Environment::mergeGlobals()`` method is deprecated as of Twig 3.14 and will be removed in Twig 4.0: diff --git a/src/Environment.php b/src/Environment.php index e3b2e7aaa..260458c71 100644 --- a/src/Environment.php +++ b/src/Environment.php @@ -144,6 +144,11 @@ class Environment $this->addExtension(new OptimizerExtension($options['optimizations'])); } + public function __clone() + { + trigger_deprecation('twig/twig', '3.30', 'Cloning a "%s" instance is deprecated and will throw in Twig 4.0; build a new environment instead.', self::class); + } + /** * @internal */ diff --git a/tests/EnvironmentTest.php b/tests/EnvironmentTest.php index d311c2677..cc5d3f296 100644 --- a/tests/EnvironmentTest.php +++ b/tests/EnvironmentTest.php @@ -96,6 +96,19 @@ class EnvironmentTest extends TestCase $twig->load($foreign->load('index')); } + /** + * @group legacy + */ + #[Group('legacy')] + public function testCloningIsDeprecated(): void + { + $this->expectDeprecation('Since twig/twig 3.30: Cloning a "Twig\Environment" instance is deprecated and will throw in Twig 4.0; build a new environment instead.'); + + $twig = new Environment(new ArrayLoader()); + + $this->assertInstanceOf(Environment::class, clone $twig); + } + public function escapingStrategyCallback($name) { return $name;