Main  /  Edit version 7  /  Edit version 8  /   /  Users Area

Difference "Templates: General Concepts (v 1.x)" ver. 7 versus ver. 8

Content:

<!--toc-->
## Basic Structure of CppCMS template file
When we build templates, we put their content in their own `skin`. Thus when we build any template we specify its skin name as first level command. Each skin is represented
by separate namespace at C++ level. So skin name is
actually C++ namespace name.
by a separate namespace at C++ level. So the skin name is
actually the C++ namespace name.
The second level is view (C++'s class). Each view withing its skin represents certain page that should be rendered.
The second level is view (C++'s class). Each view within its skin represents certain pages that should be rendered.
Each skin should implement `render()` virtual member function, unless it is already implemented in its parent.
Each view represented by separate class that is derived
from `cppcms::base_view` at topmost parent.
Each view is represented by a separate class that is derived from `cppcms::base_view` by the topmost parent.
Example:
<% skin purple %>
<% view master uses data::master %>
<% template render() %>
...
<% end template %>
<% end view %>
<% end skin %>
All views may be organized to inheritance hierarchy. For example, we can have following hierarchy for typical blog:
All views may be organized to inheritance hierarchy. For example, we can have the following hierarchy for a typical blog application:
[master]
/ \
[page] [summary]
/ \ / \
[post] [info.] [archive] [recent_posts]
Where `master` defines general appearance of the page --- theme. `page` uses for displaying general page
in blog that can be `post` or `info` -- information page. On the other hand `summary` represents list of recent posts
or archive by category.
Where `master` defines the general appearance of the page --- theme. `page` uses for displaying general page
in blog that can be `post` or `info` -- information page. On the other hand `summary` represents a list of recent posts or the archive by category.
Each inherited view may redefine its parent templates that are actually virtual functions.
## Syntax
### HTML and Controls separation
Template system of CppCMS is bases on HTML pages with injected flow control commands between `<% %>` tags.
Each template command starts with `<%` and should be closed with `%>` in same line.
The template system of CppCMS is based on HTML pages with injected flow control commands between `<% %>` tags.
Each template command starts with `<%` and should be closed with `%>` in the same line.
Each template command should be closed with these "brackets".
For example --- correct code:
<% if not empty Name %>
Hello <% Name %>
<% else %>
Hello Visitor
<% end %>
It is incorrect to "merge different commands. For example (incorrect):
Hello <% if not empty name ; name ; else %>Visitor<% end %>
You should not split command on different rows as well. The following is incorrect:
<% if not empty
name %> Not empty <% end %>
Symbols inside commands can not include `%` or `>`. You may include them inside double quotes using C++/C escaping
rules. For example:
<% number | intf("<%04x>") %>
### Syntax Description Rules
Describing syntax of template commands is done in following way:
The description of the syntax of template commands is done in the following way:
- All keywords will be shown in small caps in single quotes. For example 'skin'
- **NAME** is sequence of Latin letters, digits and underscore starting with letter. They represent identifiers
and can be defined by regular expression as: `[a-zA-Z][a-zA-Z0-9_]*`. For example `skin_1`.
- **NAME** is a sequence of Latin letters, digits and underscore starting with a letter. They represent identifiers and can be defined by regular expression such as: `[a-zA-Z][a-zA-Z0-9_]*`. For example `skin_1`.
- **VARIABLE** is non-empty sequence of NAMES separated by dot "`.`" or "`->`" that may optionally end with `()` or begin with `*` for identification of function call result. No blanks are allowed. For example: `data->point.x`, `something.else()` `*foo.bar`.
- **STRING** is standard C++/C string with standard escape characters like `"Hello \"World\""`. _Note:_ No string concatenation is allowed like `"Hello " "World"` that is equivalent of `"Hello World"`.
- **NUMBER** is a number -- sequence of digits that may start with `-` and include `.`. It can be defined by regular expression: `\-?\d+(\.\d*)?`
- **IDENTIFIER** is a sequence of NAME separated with `::` symbol. No blanks are allowed. For example: `data::page`
- **STRING** is standard C++/C string with standard escape characters like `"Hello \"World\""`. _Note:_ No string concatenation is allowed like `"Hello " "World" when `"Hello World" is meant`.
- **NUMBER** is a number -- sequence of digits that may start with `-` and include `.`. It can be defined by the regular expression: `\-?\d+(\.\d*)?`
- **IDENTIFIER** is a sequence of NAME separated by the symbol `::`. No blanks are allowed. For example: `data::page`
- All punctuation symbols are enclosed with single quotes. Like `','`.
- Non-mandatory elements are displayed withing rectangular brackets `[]` and mandatory using round brackets `()`. Options are separated using `|` symbol.
- Non-mandatory elements are displayed within square brackets `[]` and mandatory ones within round brackets `()`. Options are separated by the symbol `|`.
- There is no limit on blanks between the words.
For example:
'view' NAME 'uses' IDENTIFIER ['extends' NAME]
Means that following definitions are legal:
Means that the following definitions are legal:
<% view page uses data::page extends master %>
<% view test uses data::test %>
<% view test uses data_test %>
And these are not:
<% view 1page uses data::page extends master %>
<% view page %>
<% view page uses data::page extends other::master %>
<h1>include <iostream></h1> <h1>include <string></h1> <h1>include <cstring></h1>

include <sys/socket.h>

include <netinet/in.h>

include <unistd.h>

int main() { int server_fd, client_fd; struct sockaddr_in address; int addrlen = sizeof(address);

// HTML content to be served
std::string html = 
    "HTTP/1.1 200 OK\r\n"
    "Content-Type: text/html\r\n\r\n"
    "<!DOCTYPE html>"
    "<html>"
    "<head><title>My C++ Web</title></head>"
    "<body><h1>Welcome to a Simple Web Page!</h1><p>This is served from C++.</p></body>"
    "</html>";

// Create socket
server_fd = socket(AF_INET, SOCK_STREAM, 0);
if (server_fd == 0) {
    perror("socket failed");
    exit(EXIT_FAILURE);
}

// Bind
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(8080);

if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {
    perror("bind failed");
    exit(EXIT_FAILURE);
}

// Listen
if (listen(server_fd, 3) < 0) {
    perror("listen");
    exit(EXIT_FAILURE);
}

std::cout << "Server is running on http://localhost:8080" << std::endl;

while (true) {
    // Accept client
    client_fd = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen);
    if (client_fd < 0) {
        perror("accept");
        exit(EXIT_FAILURE);
    }

    char buffer[3000] = {0};
    read(client_fd, buffer, 3000);  // Read client request

    std::cout << "Request:\n" << buffer << std::endl;

    // Send response
    send(client_fd, html.c_str(), html.size(), 0);
    close(client_fd); // Close connection
}

return 0;

}

<h1>include <iostream></h1> <h1>include <string></h1> <h1>include <cstring></h1>

include <sys/socket.h>

include <netinet/in.h>

include <unistd.h>

int main() { int server_fd, client_fd; struct sockaddr_in address; int addrlen = sizeof(address);

// HTML content to be served
std::string html = 
    "HTTP/1.1 200 OK\r\n"
    "Content-Type: text/html\r\n\r\n"
    "<!DOCTYPE html>"
    "<html>"
    "<head><title>My C++ Web</title></head>"
    "<body><h1>Welcome to a Simple Web Page!</h1><p>This is served from C++.</p></body>"
    "</html>";

// Create socket
server_fd = socket(AF_INET, SOCK_STREAM, 0);
if (server_fd == 0) {
    perror("socket failed");
    exit(EXIT_FAILURE);
}

// Bind
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(8080);

if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {
    perror("bind failed");
    exit(EXIT_FAILURE);
}

// Listen
if (listen(server_fd, 3) < 0) {
    perror("listen");
    exit(EXIT_FAILURE);
}

std::cout << "Server is running on http://localhost:8080" << std::endl;

while (true) {
    // Accept client
    client_fd = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen);
    if (client_fd < 0) {
        perror("accept");
        exit(EXIT_FAILURE);
    }

    char buffer[3000] = {0};
    read(client_fd, buffer, 3000);  // Read client request

    std::cout << "Request:\n" << buffer << std::endl;

    // Send response
    send(client_fd, html.c_str(), html.size(), 0);
    close(client_fd); // Close connection
}

return 0;

}


Navigation

Main Page


Valid CSS | Valid XHTML 1.0