@@ -1294,6 +1294,131 @@ the closure::
12941294 // services depending on which environment you're on
12951295 };
12961296
1297+ Generating Adapters for Functional Interfaces
1298+ ---------------------------------------------
1299+
1300+ Functional interfaces are interfaces with a single method.
1301+ They are conceptually very similar to a closure except that their only method
1302+ has a name. Moreover, they can be used as type-hints across your code.
1303+
1304+ The :class: `Symfony\\ Component\\ DependencyInjection\\ Attribute\\ AutowireCallable `
1305+ attribute can be used to generate an adapter for a functional interface.
1306+ Let's say you have the following functional interface::
1307+
1308+ // src/Service/MessageFormatterInterface.php
1309+ namespace App\Service;
1310+
1311+ interface MessageFormatterInterface
1312+ {
1313+ public function format(string $message, array $parameters): string;
1314+ }
1315+
1316+ You also have a service that defines many methods and one of them is the same
1317+ ``format() `` method of the previous interface::
1318+
1319+ // src/Service/MessageFormatterInterface.php
1320+ namespace App\Service;
1321+
1322+ class MessageUtils
1323+ {
1324+ // other methods...
1325+
1326+ public function format($string $message, array $parameters): string
1327+ {
1328+ // ...
1329+ }
1330+ }
1331+
1332+ Thanks to the ``#[AutowireCallable] `` attribute, you can now inject this
1333+ ``MessageUtils `` service as a functional interface implementation::
1334+
1335+ namespace App\Service\Mail;
1336+
1337+ use App\Service\MessageFormatterInterface;
1338+ use App\Service\MessageUtils;
1339+ use Symfony\Component\DependencyInjection\Attribute\AutowireCallable;
1340+
1341+ class Mailer
1342+ {
1343+ public function __construct(
1344+ #[AutowireCallable(service: MessageUtils::class, method: 'formatMessage')]
1345+ private MessageFormatterInterface $formatter
1346+ ) {
1347+ }
1348+
1349+ public function sendMail($string $message, array $parameters): string
1350+ {
1351+ $formattedMessage = $this->formatter->format($message, $parameters);
1352+
1353+ // ...
1354+ }
1355+ }
1356+
1357+ .. versionadded :: 6.3
1358+
1359+ The :class: `Symfony\\ Component\\ DependencyInjection\\ Attribute\\ AutowireCallable `
1360+ attribute was introduced in Symfony 6.3.
1361+
1362+ Instead of using the ``#[AutowireCallable] `` attribute, you can also generate
1363+ an adapter for a functional interface through configuration:
1364+
1365+ .. configuration-block ::
1366+
1367+ .. code-block :: yaml
1368+
1369+ # config/services.yaml
1370+ services :
1371+
1372+ # ...
1373+
1374+ app.message_formatter :
1375+ class : App\Service\MessageFormatterInterface
1376+ from_callable : [!service {class: 'App\Service\MessageUtils'}, 'formatMessage']
1377+
1378+ .. code-block :: xml
1379+
1380+ <!-- config/services.xml -->
1381+ <?xml version =" 1.0" encoding =" UTF-8" ?>
1382+ <container xmlns =" http://symfony.com/schema/dic/services"
1383+ xmlns : xsi =" http://www.w3.org/2001/XMLSchema-instance"
1384+ xsi : schemaLocation =" http://symfony.com/schema/dic/services
1385+ https://symfony.com/schema/dic/services/services-1.0.xsd" >
1386+
1387+ <services >
1388+ <!-- ... -->
1389+
1390+ <service id =" app.message_formatter" class =" App\Service\MessageFormatterInterface" >
1391+ <from-callable method =" formatMessage" >
1392+ <service class =" App\Service\MessageUtils" />
1393+ </from-callable >
1394+ </service >
1395+
1396+ </services >
1397+ </container >
1398+
1399+ .. code-block :: php
1400+
1401+ // config/services.php
1402+ namespace Symfony\Component\DependencyInjection\Loader\Configurator;
1403+
1404+ use App\Service\MessageFormatterInterface;
1405+ use App\Service\MessageUtils;
1406+
1407+ return function(ContainerConfigurator $container) {
1408+ // ...
1409+
1410+ $container
1411+ ->set('app.message_formatter', MessageFormatterInterface::class)
1412+ ->fromCallable([inline_service(MessageUtils::class), 'formatMessage'])
1413+ ->alias(MessageFormatterInterface::class, 'app.message_formatter')
1414+ ;
1415+ };
1416+
1417+ By doing so, Symfony will generate a class (also called an *adapter *)
1418+ implementing ``MessageFormatterInterface `` that will forward calls of
1419+ ``MessageFormatterInterface::format() `` to your underlying service's method
1420+ ``MessageUtils::format() ``, with all its arguments.
1421+
12971422Learn more
12981423----------
12991424
0 commit comments