Blog tutorial
In this example we'll create a basic blog using Saturn.
Installation
Start off by creating a new Saturn app. Make sure the make-saturn-app command is installed and execute it in the parent directory.
make-saturn-app blog-example
Once the command completes, duplicate the settings-example.php file as settings.php and make sure all settings are correct. It's also recommended to set your name and email address in settings.global.php.
<?php
return [
'applications' => [
[
'name' => 'My Blog',
'email' => 'example@example.org',
'domain' => 'blog.dev.local',
'prefer_www' => false,
'production' => false,
'secure' => false,
]
],
'database' => [
'host' => 'localhost',
'username' => 'saturn',
'password' => 'saturn',
'database' => 'blog-example',
],
'smtp' => [
'host' => 'localhost',
'port' => 1026,
'username' => '',
'password' => '',
'security' => false,
],
];
Setup using MAMP
If you're using MAMP to run PHP applications locally, create a new custom host with a name matching your blog domain (blog.dev.local) and set its document root to the /root directory of your project. Additionally, create a database named blog-example.
Test
If you see a basic welcome message when opening http://blog.dev.local in your browser, your setup should be working correctly.
Creating database tables
Next, we'll create a database table for storing blog posts. Make the directory application/blog and add a file with name schema.xml. This file will contain our database schema definitions, which Saturn will automatically apply to our database (in development mode, for production check building). Add an entity xml tag and give it an appropriate name attribute.
<entity name="post">
</entity>
After (re)loading the homepage in your browser, you should notice a table named post appear in your database.
Add some fields to the table by adding a string tag for the title, and a text tag for the post content. We won't allow any posts without either title or content, so we'll add the required attribute.
<entity name="post">
<string name="title" required="required"/>
<text name="content" required="required"/>
</entity>
This will cause Saturn to add new columns to the table. Notice that the title will be stored in your database as title:nl. This is due to default support for internationalisation. If you have added multiple languages in settings.global.php, multiple columns would have been created.
Providing a CMS
Open your browser and point it to http://blog.dev.local/admin (http://blog.dev.local/nl/admin if you're using multiple languages). You'll end up in Saturn's CMS.
We'd like to manage our blog posts here. We can do so by creating an admin.xml file alongside our schema.xml file. In this new file, we'll add a new section to the CMS sidebar by adding a section tag, which we'll give a name and a title.
<section name="blog">
<title>Blog</title>
</section>
To add a page for our blog posts to this section, add a page tag with the section attribute set to the name of our section, and give it a title.
<section name="blog">
<title>Blog</title>
</section>
<page section="blog">
<title>Posts</title>
</page>
Our CMS now shows the page in the navigation bar, but it's still blank when we open it. Let's add some dummy text to see some more results. Content for a page must be added within a content tag. Within this tag we can just add a p tag to display some text.
<section name="blog">
<title>Blog</title>
</section>
<page section="blog">
<title>Posts</title>
<content>
<p>These are my blog posts</p>
</content>
</page>
The text now shows up on our page, but we'd rather like to actually manage some database content here instead, so let's add a list of our blog posts.
Lists
First, we need to add a list tag within the page content. This tag requires a for tag, with its value set to the name of an entity from our database schema.
<section name="blog">
<title>Blog</title>
</section>
<page section="blog">
<title>Posts</title>
<content>
<list for="post">
</list>
</content>
</page>
Next, we need to define what should be shown in the list. Add a column tag to the list, with a for attribute set to the name of a field from the entity (our title for example).
<section name="blog">
<title>Blog</title>
</section>
<page section="blog">
<title>Posts</title>
<content>
<list for="post">
<column for="title"/>
</list>
</content>
</page>
Great, but our list is still blank because our table is empty. Let's fix that by adding the ability to create blog posts.
Entity pages
Create a second page, which we'll use to create/edit our blog posts. This one should not appear in the navigation, so we'll omit the section tag. Instead, we'll tell Saturn this page is intended for our blog posts by setting its for attribute to the name of our database entity. This will allow the CMS to populate the page with data, and understand its format and context. Give this page a title as well. Preferably, use singular and plural tags within the title to improve the phrasing the CMS will use to refer to our posts.
<section name="blog">
<title>Blog</title>
</section>
<page section="blog">
<title>Posts</title>
<content>
<list for="post">
<column for="title"/>
</list>
</content>
</page>
<page for="post">
<title>
<singular>Post</singular>
<plural>Posts</plural>
</title>
<content>
</content>
</page>
To provide inputs for our dynamic content, simply add an input tag for every field you'd like to be editable. The CMS will automatically determine the most appropriate input type, based on the data format defined in your database schema. Set a for attribute equal to the schema field name, and add a title.
<page for="post">
<title>
<singular>Post</singular>
<plural>Posts</plural>
</title>
<content>
<input for="title">
<title>Titel</title>
</input>
<input for="content">
<title>Inhoud</title>
</input>
</content>
</page>
You'll notice that the CMS now has sufficient information to provide full create/update/delete functionality for our blog posts. We'll consider this to be sufficiently functional for now.
Displaying blog posts
We'll display a list of blog posts on our homepage. Open the homepage controller at application/home/home.php. Here, the index() method is responsible for displaying the homepage, where we'll fetch a list of posts by calling the getAll() function. This function takes the name of an entity as argument and returns a complete list of database records.
public function index()
{
$posts = getAll('post');
echo layout()->content('index');
}
Pass these posts to the view by adding a second argument to the content() call. This argument should be an associative array containing any data we'd like to be available within our view.
public function index()
{
$posts = getAll('post');
echo layout()->content('index', [
'posts' => $posts,
]);
}
We can now traverse this list within our view and display its data. Open the homepage view at application/home/views/index.php and traverse the list using a foreach loop. Within this loop we can access the individual records as objects.
<ul>
<?php foreach ($posts as $post): ?>
<li><?= $post->title ?></li>
<?php endforeach; ?>
</ul>