Skip to content

Commit 006f37f

Browse files
docs: update extension generator doc for a more natural order (#2279)
I've been advised during Dutch PHP Conference (thanks @dseguy!) to move the "Generate your extension" section before going deep into type juggling. I agree: the reader will have way more satisfaction and will be eager to dig the topic if the basic case already works. There may be more to improve but this is a first quick-win.
1 parent ebbc4e2 commit 006f37f

File tree

1 file changed

+59
-59
lines changed

1 file changed

+59
-59
lines changed

docs/extensions.md

Lines changed: 59 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,65 @@ There are two important things to note here:
8080
- A directive comment `//export_php:function` defines the function signature in PHP. This is how the generator knows how to generate the PHP function with the right parameters and return type;
8181
- The function must return an `unsafe.Pointer`. FrankenPHP provides an API to help you with type juggling between C and Go.
8282

83-
While the first point speaks for itself, the second may be harder to apprehend. Let's take a deeper dive to type juggling in the next section.
83+
While the first point speaks for itself, the second may be harder to apprehend. Let's take a deeper dive to type juggling later in this guide.
84+
85+
### Generating the Extension
86+
87+
This is where the magic happens, and your extension can now be generated. You can run the generator with the following command:
88+
89+
```console
90+
GEN_STUB_SCRIPT=php-src/build/gen_stub.php frankenphp extension-init my_extension.go
91+
```
92+
93+
> [!NOTE]
94+
> Don't forget to set the `GEN_STUB_SCRIPT` environment variable to the path of the `gen_stub.php` file in the PHP sources you downloaded earlier. This is the same `gen_stub.php` script mentioned in the manual implementation section.
95+
96+
If everything went well, your project directory should contain the following files for your extension:
97+
98+
- **`my_extension.go`** - Your original source file (remains unchanged)
99+
- **`my_extension_generated.go`** - Generated file with CGO wrappers that call your functions
100+
- **`my_extension.stub.php`** - PHP stub file for IDE autocompletion
101+
- **`my_extension_arginfo.h`** - PHP argument information
102+
- **`my_extension.h`** - C header file
103+
- **`my_extension.c`** - C implementation file
104+
- **`README.md`** - Documentation
105+
106+
> [!IMPORTANT]
107+
> **Your source file (`my_extension.go`) is never modified.** The generator creates a separate `_generated.go` file containing CGO wrappers that call your original functions. This means you can safely version control your source file without worrying about generated code polluting it.
108+
109+
### Integrating the Generated Extension into FrankenPHP
110+
111+
Our extension is now ready to be compiled and integrated into FrankenPHP. To do this, refer to the FrankenPHP [compilation documentation](compile.md) to learn how to compile FrankenPHP. Add the module using the `--with` flag, pointing to the path of your module:
112+
113+
```console
114+
CGO_ENABLED=1 \
115+
XCADDY_GO_BUILD_FLAGS="-ldflags='-w -s' -tags=nobadger,nomysql,nopgx" \
116+
CGO_CFLAGS=$(php-config --includes) \
117+
CGO_LDFLAGS="$(php-config --ldflags) $(php-config --libs)" \
118+
xcaddy build \
119+
--output frankenphp \
120+
--with github.com/my-account/my-module/build
121+
```
122+
123+
Note that you point to the `/build` subdirectory that was created during the generation step. However, this is not mandatory: you can also copy the generated files to your module directory and point to it directly.
124+
125+
### Testing Your Generated Extension
126+
127+
You can create a PHP file to test the functions and classes you've created. For example, create an `index.php` file with the following content:
128+
129+
```php
130+
<?php
131+
132+
// Using global constants
133+
var_dump(repeat_this('Hello World', 5, STR_REVERSE));
134+
135+
// Using class constants
136+
$processor = new StringProcessor();
137+
echo $processor->process('Hello World', StringProcessor::MODE_LOWERCASE); // "hello world"
138+
echo $processor->process('Hello World', StringProcessor::MODE_UPPERCASE); // "HELLO WORLD"
139+
```
140+
141+
Once you've integrated your extension into FrankenPHP as demonstrated in the previous section, you can run this test file using `./frankenphp php-server`, and you should see your extension working.
84142

85143
### Type Juggling
86144

@@ -580,64 +638,6 @@ echo My\Extension\STATUS_ACTIVE; // 1
580638
- Namespace names follow PHP namespace conventions using backslashes (`\`) as separators.
581639
- If no namespace is declared, symbols are exported to the global namespace as usual.
582640

583-
### Generating the Extension
584-
585-
This is where the magic happens, and your extension can now be generated. You can run the generator with the following command:
586-
587-
```console
588-
GEN_STUB_SCRIPT=php-src/build/gen_stub.php frankenphp extension-init my_extension.go
589-
```
590-
591-
> [!NOTE]
592-
> Don't forget to set the `GEN_STUB_SCRIPT` environment variable to the path of the `gen_stub.php` file in the PHP sources you downloaded earlier. This is the same `gen_stub.php` script mentioned in the manual implementation section.
593-
594-
If everything went well, your project directory should contain the following files for your extension:
595-
596-
- **`my_extension.go`** - Your original source file (remains unchanged)
597-
- **`my_extension_generated.go`** - Generated file with CGO wrappers that call your functions
598-
- **`my_extension.stub.php`** - PHP stub file for IDE autocompletion
599-
- **`my_extension_arginfo.h`** - PHP argument information
600-
- **`my_extension.h`** - C header file
601-
- **`my_extension.c`** - C implementation file
602-
- **`README.md`** - Documentation
603-
604-
> [!IMPORTANT]
605-
> **Your source file (`my_extension.go`) is never modified.** The generator creates a separate `_generated.go` file containing CGO wrappers that call your original functions. This means you can safely version control your source file without worrying about generated code polluting it.
606-
607-
### Integrating the Generated Extension into FrankenPHP
608-
609-
Our extension is now ready to be compiled and integrated into FrankenPHP. To do this, refer to the FrankenPHP [compilation documentation](compile.md) to learn how to compile FrankenPHP. Add the module using the `--with` flag, pointing to the path of your module:
610-
611-
```console
612-
CGO_ENABLED=1 \
613-
XCADDY_GO_BUILD_FLAGS="-ldflags='-w -s' -tags=nobadger,nomysql,nopgx" \
614-
CGO_CFLAGS=$(php-config --includes) \
615-
CGO_LDFLAGS="$(php-config --ldflags) $(php-config --libs)" \
616-
xcaddy build \
617-
--output frankenphp \
618-
--with github.com/my-account/my-module/build
619-
```
620-
621-
Note that you point to the `/build` subdirectory that was created during the generation step. However, this is not mandatory: you can also copy the generated files to your module directory and point to it directly.
622-
623-
### Testing Your Generated Extension
624-
625-
You can create a PHP file to test the functions and classes you've created. For example, create an `index.php` file with the following content:
626-
627-
```php
628-
<?php
629-
630-
// Using global constants
631-
var_dump(repeat_this('Hello World', 5, STR_REVERSE));
632-
633-
// Using class constants
634-
$processor = new StringProcessor();
635-
echo $processor->process('Hello World', StringProcessor::MODE_LOWERCASE); // "hello world"
636-
echo $processor->process('Hello World', StringProcessor::MODE_UPPERCASE); // "HELLO WORLD"
637-
```
638-
639-
Once you've integrated your extension into FrankenPHP as demonstrated in the previous section, you can run this test file using `./frankenphp php-server`, and you should see your extension working.
640-
641641
## Manual Implementation
642642

643643
If you want to understand how extensions work or need full control over your extension, you can write them manually. This approach gives you complete control but requires more boilerplate code.

0 commit comments

Comments
 (0)