Hint: Each tip is independent of the others. Read them in any order!
Topincs is targeted to achieve more with less domain specific code. That said, in a large project you will still spend quite some time looking and working with code: PHP, JavaScript and SCSS. On this page you will find numerous useful tips which will make your life easier!
Some systems are more complex than others. When you need to make delicate and difficult changes to the source code, you can protect yourself from breaking existing functionality by using the PHP function assert. In the simplest case create a POST service assert with the format txt and group your related assertions in functions. Split up the work into tiny steps and deactivate services if necessary. After each step execute assert. Silence is golden. If there is no output all assertions pass and you are good.
It is easy to call a service from JavaScript. In our first example we empower our users to directly change something in the store without visiting a form before, e.g. by clicking a check box displayed in HTML output of our survey
service. In the JavaScript we install event handlers on all checkboxes. The key fragment to make the change is this modifying POST request to the service named pickteam
:
Hint: This is just standard JavaScript promises with then and catch.
var call = new ServiceCall("pickteam", {team: teamId});
call
.post({blockui: true})
.then(function (response) { ... })
.catch(function (message) { ... });
If you omit the catch, the default handler for rejection is to display the the body of the response in a modal dialog.
The second example illustrates how to get information through a service. We want to reduce the list of articles selectable in the form to the ones actually listed in a store. The service is called articles
and produces JSON output. It has one argument outlet
.
var call = new ServiceCall("articles.json", {outlet: outletId});
// By default async and json
call.get().then(function(articles) { ... });
// Sync
var articles = call.get({sync: true});
// String response instead of json
somecall.get({json: false}).then(function (message) { ... });
API reference
You can embed a service call in another service with the ServiceCall
class. The need for this feature might not be evident immediately, since you can simply use a domain class or a plain PHP function in a helper file and use it in any number of services. The next paragraph will explain why ServiceCall
actually is important, but first its basic usage:
$output = call("pickteam", ["team" =>Tobject::get($team_id)]);
Hint: Learn more about jobs.
Since a POST service runs in a single transaction. It succeeds when it terminates without exception and everything is committed. If it fails, everything is rolled back. Some actions cannot not be reverted like the sending of an email. In addition you do not want users to wait for feedback more than a few seconds. To avoid long running execution time during a POST, e.g. when sending numerous emails or importing data, service calls can be scheduled for later. And this has the added benefit of isolation: an error in one service call does not have any effect on the others.
$delay = 3;
foreach ($invoices as $invoice) {
schedule("sendinvoice", ["invoice" => $invoice], $delay);
$delay += 3;
}
API reference
Hint: The interface of debug
works just like printf.
When coding a larger task in Topincs, it is possible that the source code does not immediately produce the desired result. Tracking down problems is easier with the help of the simple global function debug
. Here is how:
The debug information is supposed to be a temporary support and is meant to be produced and consumed during development only. So please remove debug statements from the source code after they have done their job. Debug information is deleted automatically after 48 hours.
If you need to persist information always use the database. Ideally store it structered in the topic map. If this is not feasible, e.g. you have a complex algorithm where you need to trace decisions, create a Topincs file type and add the textual information as a file (see Persisting files).
// This service writes some debug information.
$person = $p->get("person");
debug("person: %s", $person->label());
During service programming you will encounter the need to assemble related code in units to make it available for another service or simply to improve readability. You can achieve this by declaring files and after reloading the empty new file will be contained in service source code editor.
require_once("etc.php");
@import("common.scss");
include("common.js");
API reference
Some information is best held in a file, a sequence of bytes. It is easy to create files (Topincs files to be exact) by programming in Topincs.
$report = [];
// Perform miracle with the help of for, while and if.
// Explain in report what just happend.
// Collect the report in a temporary file.
$logfile = tmp_file();
file_put_contents($logfile, implode("\n", $report));
// Add the temporary file to the store.
// 923 is the id of the file topic type.
Tobject::make("id:923", $logfile, "miracle-report.log")
->add_timestamp(new DateTime());
// This will only create a new topic when the byte
// sequence is not already in the store. The timestamp allows
// us to recognize when the same miracle is performed twice.
When feeding information in the store to other computational processes, JSON is the format to go to. It is very simple to produce in PHP using a Topincs service:
// This service outputs information on one person into JSON.
$person = $p->get("person");
$data = (object) [
"name" => sprintf(
"%s %s",
$person->get_first_name(),
$person->get_last_name()
),
"height" => $person->get_height(),
"weight" => $person->get_weight()
];
echo json_encode($data);
Warning: While this works and will remain supported, it is easier to accomplish the same result with a template or a service call.
It is possible to reuse the presentational or computational component of one service in another by simply including the source code file. This makes it easier to reuse the complete service code, but is only recommended for services without parameters.
$data = ...;
$title = ...;
include("services/service2/GET.php");
include("services/service2/GET.html");
if (isset($data) === false) {
$data = ...;
$title = ...;
}
// Do amazing things with data!
<h1><?php echo $title ?></h1>
<!-- render data --!>
API reference
It is recommended to use the table
PHP function to create HTML tables containing data. But if you do not for whatever reason and you code a HTML table manually, you can easily make it sortable. You need to add the attributes sortable
and datatype
to the respective th
opening tag. If the datatype is not string or the display value differs from the data value, you need to add a data-value
attribute to all the td
elements. If you have a sum row, put it in a separate tbody
.
When programming in Topincs most of the work is performed in a very narrow context. Services are largely independent of each other sharing usually only a few helper functions. Yet, sometimes it is necessary to ensure certain properties on tobjects representing topics of a certain topic type. This can be achieved by declaring an init
method in a domain class. There is no need to explicitly call this method. It is done automatically by Topincs.
class WorkSession extends Tobject {
function init() {
$this->start = $this->get_start();
$this->end = $this->get_end();
$this->duration_in_sec =
$this->end->format("U") - $this->start->format("U");
}
}
Tobject::register(
"WorkSession",
"si:https://www.topincs.com/trial/invoicing/392"
);
This page cannot be displayed in your browser. Use Firefox, Opera, Safari, or Chrome instead.
Saving …