Skip to content

Commit 1f68ef9

Browse files
flynnduismmichelleN
authored andcommitted
theme adjustments for blog listing and posts
Signed-off-by: Ronan Flynn-Curran <[email protected]>
1 parent 88708f0 commit 1f68ef9

20 files changed

+686
-417
lines changed

config/site.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
title = "Spin Docs"
22
base_url = ""
33
about = "Spin is an open-source multi-language framework and CLI for building and deploying WebAssembly apps."
4-
index_site_pages = ["sitemap", "home", "changelog", "hub_list_api", "main"]
4+
index_site_pages = ["sitemap", "home", "changelog", "hub_list_api", "main", "blog_index"]
55
prepend_route_info = true
66

77
[extra]

content/blog/hello.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
title = "Hello World"
22
date = "2025-10-30T12:00:00Z"
3-
template = "blog"
3+
template = "blog_post"
4+
description = "This is a hello world blog post with example contents and formatting references."
45

56
[extra]
67
author = "Michelle Dhanani"

content/blog/index.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
title = "Spin | Community Blog"
2-
template = "main"
2+
template = "blog_index"
33
date = "2022-04-01T00:00:00Z"
4+
description = "Read the latest Spin project updates. Spin is the open source tool for building and running Wasm apps."
45

56
[extra]
67
author = "Spin Community"
78
type = "index"
8-
category = "index"
99

1010
---

content/blog/testing-spin.md

Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
1+
title = "PHP Spin"
2+
description = "In this post, we’ll create a new PHP application with Spin and then run it in Fermyon Cloud."
3+
date = "2022-12-22T18:13:50.393377Z"
4+
template = "blog_post"
5+
6+
[extra]
7+
type = "post"
8+
9+
---
10+
11+
In this post, we’ll create a new PHP application with Spin and then run it in [Fermyon Cloud](https://fermyon.com/cloud). VMware’s Wasm Labs maintains a version of PHP that is compiled to WebAssembly, and we will use that. We will create a new Spin application that loads the PHP-Wasm runtime, and then we will write a couple of scripts and look at a few configuration options. We will test it locally until we are happy with our result. Then we’ll deploy to a publicly accessible Fermyon Cloud app.
12+
13+
<!-- break -->
14+
15+
## WebAssembly and Scripting Languages Like PHP
16+
Before we dive into the practical side, it is helpful to understand how PHP and WebAssembly work. PHP is a scripting language, which typically means we need to [compile the language interpreter itself](https://www.fermyon.com/blog/scripts-vs-compiled-wasm) to WebAssembly. Then we write our code the usual PHP way. When we run our application, the Wasm version of PHP runs our code just like we would expect in PHP’s other runtime versions. For that reason, the bulk of our setup here is just configuring Spin to use the Wasm version of PHP.
17+
18+
## Getting Started
19+
Make sure you have the [latest Spin](https://developer.fermyon.com/spin/install) installed. Since there is not yet a Spin PHP starter template, we’ll create an empty HTTP project and add PHP.
20+
21+
```console
22+
$ spin new http-empty hello-php
23+
Project description: PHP for Fermyon Cloud
24+
HTTP base: /
25+
```
26+
27+
Next, we need to edit the generated `spin.toml` to tell it how to fetch PHP from [VMware Labs](https://github.com/vmware-labs/webassembly-language-runtimes/releases). Find the release you want to install and copy the download link. We recommended downloading the version optimized for speed, but any of them will work.
28+
29+
You will also need to get the SHA-256 digest of the file you are going to download. You can check the [release page](https://github.com/vmware-labs/webassembly-language-runtimes/releases), or you can generate your own by downloading the file and running `shasum -a 256 php-cgi-7.4.32.speed-optimized.wasm`.
30+
31+
```toml
32+
# This part was generated for us by "spin new http-empty"
33+
spin_version = "1"
34+
authors = ["Matt Butcher <[email protected]>"]
35+
description = "PHP for Fermyon Cloud"
36+
name = "hello-php"
37+
trigger = { type = "http", base = "/" }
38+
version = "0.1.0"
39+
40+
# This is the stuff we are adding.
41+
[[component]]
42+
# Latest PHP-Wasm
43+
id = "PHP"
44+
files = [ { source = "./src", destination = "/" } ]
45+
[component.source]
46+
# URL to download the .wasm file
47+
url = "https://github.com/vmware-labs/webassembly-language-runtimes/releases/download/php%2F7.4.32%2B20221124-2159d1c/php-cgi-7.4.32.speed-optimized.wasm"
48+
# digest of the .wasm file we expect to get from the URL
49+
digest = "sha256:511720698dee56134ed8a08a87131d33c3ea8a64b6726cd6710d624bca4ceb6c"
50+
[component.trigger]
51+
# Make sure the executor is wagi
52+
executor = { type = "wagi"}
53+
# This means PHP will be used for all requests.
54+
route = "/..."
55+
56+
```
57+
58+
Importantly, the `component.source` has two required parts:
59+
* `url` is the URL where Spin can fetch the PHP runtime.
60+
* `digest` is the SHA-256 digest of the download file. This is a security feature that makes sure nothing was corrupted for compromised during download.
61+
62+
We mapped a source directory called `src/` in our local project to the remote path `/`. That means that any PHP files we put locally in `./src/` will be loaded into the root of the PHP-Wasm server. So let’s create that directory and write our first PHP script:
63+
64+
```console
65+
$ mkdir src
66+
$ cd src
67+
```
68+
69+
Inside of `src/`, we can create `index.php`. Let’s start with a “Hello World”:
70+
71+
```php
72+
<?php
73+
echo “Hello World”;
74+
?>
75+
```
76+
77+
Now we have everything we need to test things out. In a console window, run `spin up`. Since we’re currently in the `src/` directory, we need to change directories up a level so that we are in the same directory as the `spin.toml`:
78+
79+
```console
80+
$ cd ..
81+
$ ls
82+
modules spin.toml src
83+
$ spin up
84+
Serving http://127.0.0.1:3000
85+
Available Routes:
86+
PHP: http://127.0.0.1:3000 (wildcard)
87+
```
88+
89+
If we point a web browser at `http://127.0.0.1:3000/index.php`, we should see “Hello World”. Here’s what it looks like with `curl`:
90+
91+
```console
92+
$ curl localhost:3000/index.php
93+
Hello World
94+
```
95+
96+
We now have a Spin PHP app. We’ll get on to more features, but first let’s look at a couple frequent configuration issues.
97+
98+
## The Most Common Configuration Issues
99+
Getting an error message instead of the “Hello World” message? Here are the first things to check:
100+
101+
1. The `source` attribute in your `spin.toml` _must_ have both a URL and a digest if you want to fetch the latest version from GitHub. However, you can also download the php-wasm binary to your local working directory and just use `source = “/path/to/php-wasm.wasm”`
102+
2. The `component.trigger` in `spin.toml` _must_ use the Wagi trigger: `executor = { type = "wagi"}`
103+
3. The `files` list needs to map a local path where your PHP files are to the `/` path on the runtime: `files = [ { source = "./src", destination = "/" } ]`. That copies, for example, your local `src/index.php` to `/index.php` in the PHP engine.
104+
105+
## Mapping `/` to `/index.php`
106+
In our example above, in order to access our new app, we need to add `/index.php` to the URL. What if you want to configure `http://localhost:3000/` to run `index.php`? By default, Spin will not assume that `index.php` is the path it should run. There are a few ways to work around this, but the easiest is to just redirect from `/` to `/index.php`. And we can do that with the `spin add redirect` command:
107+
108+
```console
109+
$ spin add redirect
110+
Enter a name for your new project: redirect-root
111+
Redirect from: /
112+
Redirect to: /index.php
113+
```
114+
115+
Now when we run `spin up localhost:3000`, it will execute our PHP code.
116+
117+
How does this work? When we did `spin add redirect`, Spin added a redirector to our `spin.toml` file. Taking a look at `spin.toml`, we’ll see the new redirect component:
118+
119+
```toml
120+
[[component]]
121+
source = { url = "https://github.com/fermyon/spin-redirect/releases/download/v0.0.1/redirect.wasm", digest = "sha256:d57c3d91e9b62a6b628516c6d11daf6681e1ca2355251a3672074cddefd7f391" }
122+
id = "redirect-root"
123+
environment = { DESTINATION = "/index.php" }
124+
[component.trigger]
125+
route = "/"
126+
executor = { type = "wagi" }
127+
```
128+
129+
>> Twice we have seen `url` used in `source`. This is a new feature in Spin 0.7 that allows Spin to fetch a Wasm component directly from its source. Doing so makes it easy to include standard components without having to keep them all locally downloaded.
130+
131+
## Using PHP Features
132+
We have now got a simple PHP “hello world”. Just for fun, let’s build something slightly more sophisticated. This example will show a few features of PHP:
133+
134+
* Setting HTTP headers
135+
* Accessing query parameters (the part after `?` in a URL)
136+
* Using built-in PHP libraries. In this case, it’ll the JSON encoder
137+
138+
```php
139+
<?php
140+
header("Content-Type: application/json");
141+
142+
$name = $_GET["name"];
143+
144+
if (empty($name)) {
145+
$name = "Unknown";
146+
}
147+
148+
$data = array(
149+
"name" => $name,
150+
"platform" => "PHP",
151+
);
152+
153+
154+
echo json_encode($data);
155+
```
156+
157+
This example writes a JSON object instead of plain text. Additionally, `name` is set to whatever gets passed in on the query string’s `name` parameter. Here’s what the output looks like with curl:
158+
159+
```console
160+
$ curl localhost:3000/index.php\?name=Matt
161+
{"name":"Matt","platform":"PHP"}
162+
```
163+
164+
The code above is nothing extraordinary. In fact the reason for giving this example is to show that once you have PHP running in Wasm, you can for the most part use it normally.
165+
166+
Be aware, though, that not all of the libraries that can be run in PHP are compiled into this version of PHP-Wasm. The easiest way to see which libraries are supported is to create another script in `src/` named `info.php` and add this:
167+
168+
```php
169+
<?php phpinfo(); ?>
170+
```
171+
172+
Accessing `http://localhost:3000/info.php` in your browser will display the configuration of PHP-Wasm.
173+
174+
## Deploying to Fermyon Cloud
175+
We’ve done the hard part. Now all we need to do is deploy it to Fermyon Cloud, and we’ll have our first PHP app online and ready for use!
176+
177+
```console
178+
$ spin deploy
179+
180+
Copy your one-time code:
181+
182+
XXXXXXXX
183+
184+
...and open the authorization page in your browser:
185+
186+
https://cloud.fermyon.com/device-authorization
187+
188+
Waiting for device authorization...
189+
Device authorized!
190+
Uploading hello-php version 0.1.0+r4a15e354...
191+
Deploying...
192+
Waiting for application to become ready............. ready
193+
Available Routes:
194+
PHP: https://hello-php-gpye1en3.fermyon.app/(wildcard)
195+
redirect-root: https://hello-php-gpye1en3.fermyon.app/
196+
```
197+
198+
And that’s it! We’ve got PHP on Fermyon Cloud.
199+
200+
## Conclusion
201+
PHP has been one of the most popular programming languages for decades. And it is no wonder. Web developers can be highly productive with PHP’s rich libraries and easy programming model. Furthermore, PHP lends itself to the serverless functions model.
202+
203+
This post introduced how to configure Spin for PHP-Wasm, and then walked through creating a simple app. If you’re interested in chatting about this, or if you have questions, don’t hesitate to [hit us up in Discord](https://discord.gg/AAFNfS7NGf).

scripts/pagination.rhai

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
let arr = params[0];
2+
let index = params[1];
3+
let offset = parse_int(params[2]);
4+
5+
let total_pages = arr.len/offset;
6+
7+
// If there are any remaining posts, add an extra page
8+
if ( arr.len%offset > 0) {
9+
total_pages = total_pages + 1;
10+
}
11+
12+
let val = #{
13+
prev: "",
14+
next: "",
15+
subarr: [],
16+
navigation: [],
17+
current_page: index,
18+
pages: []
19+
};
20+
21+
let pageIndex = 0;
22+
do {
23+
val.pages.push(pageIndex);
24+
pageIndex = pageIndex + 1;
25+
} while pageIndex < total_pages;
26+
27+
val.subarr = arr.extract(index * offset, offset);
28+
29+
if (arr.len > (index*offset) + offset ) {
30+
val.next = index + 1;
31+
}
32+
33+
if index > 0 {
34+
if (arr.len < index*offset) {
35+
val.prev = arr.len/offset;
36+
}
37+
else {
38+
val.prev = index - 1;
39+
}
40+
}
41+
42+
val.navigation.push(1);
43+
44+
if total_pages < 6 {
45+
for i in 2..total_pages {
46+
val.navigation.push(i);
47+
}
48+
} else {
49+
if index > 2 && index < total_pages - 3 {
50+
val.navigation.push(0);
51+
val.navigation.push(index);
52+
val.navigation.push(index+1);
53+
val.navigation.push(index+2);
54+
val.navigation.push(0);
55+
} else {
56+
if index > total_pages - 4 {
57+
val.navigation.push(0);
58+
for i in index..total_pages {
59+
val.navigation.push(i);
60+
}
61+
}
62+
if index < 4 {
63+
for i in 2..index+3 {
64+
val.navigation.push(i);
65+
}
66+
val.navigation.push(0);
67+
}
68+
}
69+
70+
if total_pages > 1 {
71+
val.navigation.push(total_pages)
72+
}
73+
}
74+
75+
val

scripts/url_query_params_int.rhai

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
let full_url = params[0];
2+
let query_params = #{page: 0};
3+
let query_string;
4+
let query_param;
5+
6+
if full_url.contains("?") {
7+
// Get the query string
8+
query_string = full_url.sub_string(full_url.index_of("?") + 1);
9+
do {
10+
// Seperate by parameters
11+
if query_string.contains("&") {
12+
query_param = query_string.sub_string(0, query_string.index_of("&"));
13+
query_string = query_string.sub_string(query_string.index_of("&") + 1);
14+
} else {
15+
query_param = query_string;
16+
query_string.clear();
17+
}
18+
// set the page parameter to the value from the url
19+
if query_param.sub_string(0, query_param.index_of("=")) == "page" {
20+
try {
21+
query_params.page = parse_int(query_param.sub_string(query_param.index_of("=") + 1));
22+
} catch {
23+
query_params.page = 0;
24+
}
25+
}
26+
} while ( query_string.len() > 0)
27+
}
28+
29+
// Return the query_params
30+
query_params.page

0 commit comments

Comments
 (0)