Widgets
Widgets are a bit different, as they can't be services. They inherit WP_Widget
class and are instantiated by WordPress.
Configuration
To let Sword understand where to load widgets, we need to configure them. Open /config/packages/sword.yaml
file and add:
sword:
# ...
widgets_namespace: 'App\Wordpress\Widget\'
widgets_path: '%kernel.project_dir%/src/Wordpress/Widget/'
2
3
4
TIP
By default, the namespace is App\\Widget\\
and path %kernel.project_dir%/src/Widget/
. You don't have to configure it if you like it this way.
Create a widget
Now create your first widget in src/Wordpress/Widget/MyWidget.php
and fill it with this content:
<?php
declare(strict_types=1);
namespace App\Wordpress\Widget;
use WP_Widget;
final class MyWidget extends WP_Widget
{
public function __construct()
{
parent::__construct(
'my_widget',
'My Widget',
['description' => __('This is my new widget', 'mychildtheme')],
);
}
public function widget($args, $instance): void
{
// ...
}
public function form($instance): void
{
// ...
}
public function update($newInstance, $oldInstance): array
{
$instance = [];
// ...
return $instance;
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
TIP
You don't need to register the widget using register_widget()
nor call widgets_init
action. This is automatically done for you, as long as your widgets live in the namespace you configured. You can also create sub-namespaced widgets and they'll be loaded as well.
Dependency injection
Widgets are instantiated while WordPress is loading, therefore you can't autowire services in the constructor.
This is where the helper functions get_symfony_service()
and get_symfony_parameter()
come into play.
// ...
use Twig\Environment;
use WP_Widget;
use function Sword\SwordBundle\Helper\get_symfony_parameter;
use function Sword\SwordBundle\Helper\get_symfony_service;
final class MyWidget extends WP_Widget
{
private readonly Environment $twig;
private readonly string $translationDomain;
public function __construct()
{
$this->twig = get_symfony_service(Environment::class);
$this->translationDomain = get_symfony_parameter('sword.child_theme_translation_domain');
parent::__construct(
'my_widget',
'My Widget',
['description' => __('This is my new widget', $this->translationDomain)],
);
}
public function widget($args, $instance): void
{
echo $this->twig->render(
'wordpress/widget/my_widget.html.twig',
compact('args', 'instance'),
);
}
// ...
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
Then create a template in /templates/wordpress/widget/my_widget.html.twig
and put this content:
{{ args.before_title|raw }}
Hello from Twig
{{ args.after_title|raw}}
2
3
If you run this code, you'll get the following error:
The "Twig\Environment" service or alias has been removed or inlined when the container was compiled.
The next step is to make this service public. To do so, simply add it to the list of the public services in /config/packages/sword.yaml
:
sword:
# ...
public_services:
- Twig\Environment
2
3
4
Now you can add your widget to the sidebar and see the result.