Building Applications

Now that you understand the core concepts of Fuwafuwa Framework, it's time to start building applications. This guide will walk you through creating both static pages and dynamic, data-driven applications.

Building web applications with Fuwafuwa Framework is designed to be straightforward and enjoyable. Whether you're creating a simple landing page or a complex data management system, the framework provides the tools and conventions you need to work efficiently.

The framework follows a clear separation of concerns, making it easy to organize your code and collaborate with other developers. As you build your application, you'll work with models, views, and controllers—the three pillars of the MVC pattern that Fuwafuwa is built upon.

Static Pages

Static pages are the simplest type of pages you can create in Fuwafuwa Framework. They display content that doesn't change based on user input or database queries, making them perfect for informational content like about pages, privacy policies, terms and conditions, and help documentation.

Despite their name, static pages in Fuwafuwa aren't completely static. You can still use template variables to inject dynamic content like your application name, site URL, or other configuration values. This gives you the best of both worlds: the simplicity of a static page with the flexibility of dynamic content.

Creating a static page in Fuwafuwa is refreshingly simple. You don't need to create a controller or define routes manually. Just create a template file in the views directory, and the framework will automatically handle the rest. This convention-over-configuration approach means you can focus on creating content rather than configuring the framework.

A common example of a static page is the "Terms and Conditions" section. Here's a look at a typical static page template (app/views/themes/fuwafuwa/terms.html):

<f3:inject id="content">
<div class="mx-auto my-6 format lg:format-lg dark:format-invert">
<h2><strong>Terms and Conditions</strong></h2>

<p>Welcome to {{@APP.title}}!</p>

<p>These terms and conditions outline the rules and regulations for the use of {{@APP.title}}'s Website, located at
    <code>{{@HOST}}</code>.
</p>
...

As you can see, this template includes dynamic elements like {{@APP.title}} and {{@HOST}}, which are automatically populated from your application configuration. This approach allows you to maintain consistent branding and site information across all your static pages without having to hardcode values in multiple files.

Fuwafuwa Framework's templating system automatically wraps static pages within a default layout (typically found in /themes/fuwafuwa/templates/template.html). This provides a consistent look and feel across your application, ensuring that your static pages share the same header, footer, and navigation as the rest of your site.

If you need to customize the layout for specific pages, you have several options. You can create a custom template and reference it in your view, or you can override the default template by placing a modified copy in the app/views/user/templates directory. This flexibility allows you to create unique page designs when needed while maintaining consistency across your application.

Dynamic Pages

While static pages are great for informational content, most web applications need dynamic pages that display and interact with data. Dynamic pages show content that changes based on user input, database queries, or other runtime conditions. This is where the true power of the MVC pattern becomes apparent.

Creating a dynamic page in Fuwafuwa involves coordinating three components: models, views, and controllers. Each component has a specific responsibility: the model handles data access, the controller processes requests and coordinates between components, and the view presents the data to the user. This separation makes your code more maintainable and easier to test.

When a user requests a dynamic page, the framework routes the request to the appropriate controller, which then retrieves the necessary data from the model and passes it to the view for rendering. This flow happens seamlessly and automatically, allowing you to focus on your application's business logic rather than the mechanics of request handling.

Let's say you want to display user information based on a provided login parameter (e.g., /user/view?login=admin). Here's a complete breakdown of the required files and code, with explanations for each part.

Model (app/controllers/user/model/user.php)

The model is responsible for all database operations related to user data. By extending \Fuwafuwa\BaseModel, we inherit a powerful set of methods for creating, reading, updating, and deleting user records. The model encapsulates all database logic, keeping our controllers clean and focused on request handling.

<?php
namespace Model;

class User extends \Fuwafuwa\BaseModel {
    function __construct(\Fuwafuwa\Db $db) {
        parent::__construct($db, 'user', ['keys' => 'login',]);
    }
}

In this example, we're specifying that the login field is the primary key for our user table. This allows the model to efficiently retrieve users by their login name, which we'll use in our controller.

Controller (app/controllers/user/user.php)

The controller acts as the intermediary between the user's request and your application's data. When a user visits /user/view?login=admin, the framework routes this request to our controller's execute method, which then calls the appropriate action method—in this case, view.

In the view method, we use the m() helper function to get an instance of our User model, retrieve the requested user from the database using the login parameter, and then pass the user data to the view for rendering. The m() function is a convenient way to instantiate models through Fuwafuwa's dependency injection container.

<?php
// app/controllers/user/user.php
class User {
    function execute($f3, $action) {
        if (method_exists($this, $action)) {
            $this->$action($f3);
        } else {
            $f3->error(404);
        }
    }

    function view($f3) {
        $user = m('\Fuwafuwa\Model\User');
        $user->retrieve($f3['GET.login']);
        $f3['user'] = $user->cast();
        $f3['content'] = 'view-user';
    }
}

The cast() method converts the model's data into a simple array, making it easy to pass to the view. We also set $f3['content'] to specify which template file should be used for rendering.

View (app/views/user/view-user.html)

The view is responsible for presenting the data to the user in a readable, formatted way. Using the Fat-Free Framework's template syntax, we can easily access the data that our controller passed to the F3 hive. The <f3:inject id="content"> tag ensures our content is placed in the correct location within the layout template.

<!-- app/views/user/view-user.html -->
<f3:inject id="content">
    <table>
        <tr>
            <td>Login</td>
            <td>{{ @user.login }}</td>
        </tr>
        <tr>
            <td>Fullname</td>
            <td>{{ @user.fullname }}</td>
        </tr>
        <tr>
            <td>Token</td>
            <td>{{ @user.token }}</td>
        </tr>
    </table>
</f3:inject>

The {{ @user.field }} syntax accesses the user data that we stored in the F3 hive from our controller. This clean separation means our view only needs to worry about presentation, not about how the data was retrieved or processed.

By following this structure, you can create dynamic pages that display data based on user input or other criteria. The framework's conventions mean you don't have to worry about routing, autoloading, or other configuration details—just follow the naming conventions and everything works automatically.

Next Steps

Now that you understand how to create both static and dynamic pages in Fuwafuwa Framework, you're ready to start building your application. Here are some key points to remember as you develop:

  • Static pages are perfect for informational content that doesn't change frequently. Just create a template file and the framework handles the rest.
  • Dynamic pages require coordination between models, views, and controllers to handle data and user interactions effectively.
  • Follow conventions - Fuwafuwa's routing and autoloading systems work automatically when you follow the established naming conventions for files and classes.
  • Use the m() helper - This function is the easiest way to instantiate models through the dependency injection container.
  • Leverage the F3 hive - Storing data in the F3 hive makes it easy to pass data between controllers and views without tight coupling.
✨ Pro Tip

As you build your application, consider using Fuwafuwa's built-in features like FFTable for data grids, widgets for common UI components, and the validation system for form processing. These tools can significantly speed up your development process.