Tina4 is a light-weight routing and twig based templating system which allows you to write websites and API applications very quickly. Currently, the full deployment is under 8mb in size, and we are aiming at being the PHP framework with the smallest carbon footprint. Due to the nature of the code being very compact and all functionality engineered from the ground up we trust you will find it a pleasant experience.
Join us on Discord to be part of the journey.
The premise of the project is to make you the developer and PHP, the heroes!
We are currently testing on latest PHP 8.2, please report any issues you may find.
- Install PHP7.4 > make sure the following extensions are enabled: fileinfo, mbstring, curl, gd, xml.
- Install Composer * Windows users must install openssl so that the JWT keys will be generated correctly
- Create a project folder where you want to work
- In your project folder terminal / console
composer require tina4stack/tina4php
composer exec tina4 initialize:run
composer start
Hit up http://localhost:7145 in your browser, you should see the documentation page
If you want to run the webservice on a specific port
composer start 8080
The ORM and database modules are all extracted into their own packagist modules. The ORM and database metadata work now using a more uniform mechanism. The service module now is created under bin and tina4 service and tina4 bin executables are replaced when their checksums change.
Database support table
Database | Composer Command |
---|---|
Sqlite3 | composer require tina4stack/tina4php-sqlite3 |
ODBC | composer require tina4stack/tina4php-odbc |
MySQL | composer require tina4stack/tina4php-mysql |
Firebird | composer require tina4stack/tina4php-firebird |
MongoDB | composer require tina4stack/tina4php-mongodb |
PostgreSQL | composer require tina4stack/tina4php-postgresql |
MSSQL | composer require tina4stack/tina4php-mssql |
PDO | composer require tina4stack/tina4php-pdo |
Features
- Auto templating with TWIG
- Auto inclusions & project structure
- Open API Annotations for quick Swagger documentation & security
- Annotation driven testing, write unit tests as you code
- Tina4 ORM
- Service Runner
- Async triggers and events
- Out of the box support for Swoole
- Modular programming, each project is a potential module.
composer test
composer start-service
composer tina4
Note The above command only seems to run on Linux and Mac
On Windows do the following:
php bin\tina4
This requires you to have your docker environment already running
We assume /app is the internal path for the current project Installing
docker run -v $(pwd):/app tina4stack/php:latest composer require tina4stack/tina4php
docker run -v $(pwd):/app tina4stack/php:latest composer exec tina4 initialise:run
Upgrading
docker run -v $(pwd):/app -p7145:7145 tina4stack/php:latest composer upgrade
Running
docker run -v $(pwd):/app -p7145:7145 tina4stack/php:latest composer start
On a different port like 8080 for example
docker run -v $(pwd):/app -p8080:8080 tina4stack/php:latest composer start 8080
The folder layout is as follows and can be overridden by defining PHP constants for TINA4_TEMPLATE_LOCATIONS
, TINA4_ROUTE_LOCATIONS
& TINA4_INCLUDE_LOCATIONS
:
- src
- app (helpers, PHP classes)
- public (system twig files, images, css, js)
- orm (ORM objects - extend \Tina4\ORM)
- routes (routing)
- scss - style sheet templates
- services (service processes - extend \Tina4\Process)
- templates (app twig files)
Tina4 uses a .env file to set up project constants, a .env will be created for you when the system runs for the first time. If you specify an environment variable on your OS called ENVIRONMENT then .env.ENVIRONMENT will be loaded instead.
[Section] <-- Group section
MY_VAR=Test <-- Example declaration, no quotes required or escaping, quotes will be treated as part of the variable
# A comment <-- This is a comment
[Another Section]
VERSION=1.0.0
Do not include your .env files with your project if they contain sensitive information like password, instead create an example of how it should look.
Creating API end points and routers in Tina4 is simple as indicated below. If you are adding swagger annotations, simply hit up the /swagger end point to see the OpenApi rendering.
/**
* @description Swagger Description
* @tags Example,Route
*/
\Tina4\Get::add("/hello-world", function(\Tina4\Response $response){
return $response ("Hello World!");
});
Routes can also be mapped to class methods, static methods are preferred for routing, but you can mix and match for example if you want to keep all functionality neatly together.
/**
* Example of route calling class , method
* Note the swagger annotations will go in the class
*/
\Tina4\Get::add("/test/class", ["Example", "route"]);
Example.php
class Example
{
public function someThing() {
return "Yes!";
}
/**
* @param \Tina4\Response $response
* @return array|false|string
* @description Hello Normal -> see Example.php route
*/
public function route (\Tina4\Response $response) {
return $response ("OK!");
}
}
You can add lines like this by using the tina4 tool or by pasting the example below into your index.php file.
global $DBA;
$DBA = new \Tina4\DataSQLite3("test.db");
class Address extends \Tina4\ORM
{
public $id;
public $address;
public $customerId;
//Link up customerId => Customer object
public $hasOne = [["Customer" => "customerId"]];
}
class Customer extends \Tina4\ORM
{
public $primaryKey = "id";
public $id;
public $name;
//Primary key id maps to customerId on Address table
public $hasMany = [["Address" => "customerId"]];
}
And some code using the above objects
$customer = (new Customer());
$customer->id = 1;
$customer->name = "Test";
$customer->save();
$address = (new Address());
$address->address = "1 Street";
$address->customerId = 1;
$address->save();
$customer = (new Customer());
$customer->addresses[0]->address = "Another Address";
$customer->addresses[0]->address->save(); //Save the address
$customer->load("id = 1");
$address = new Address();
$address->load("id = 1");
$address->address = "New Street Address";
$address->customer->name = "New Name for customer"
$address->customer->save(); //save the customer
$address->save();
Give this a try and see what happens
composer test
Writing unit tests is easy and can be done as an annotation in your code comments
/**
* Some function to add numbers
* @tests
* assert (1,1) === 2, "1 + 1 = 2"
* assert is_integer(1,1) === true, "This should be an integer"
*/
function add ($a,$b) {
return $a+$b;
}
Tina4Php supports a very limited threading or triggering of events using popen to execute and "thread" out triggered code. There are some caveats as the code cannot have comments in and only simple variables can be used. Other than that almost anything can be accomplished.
//Example of the triggered event, notice the sleep timer which should shut down most code on windows or linux making PHP wait for the result.
\Tina4\Thread::addTrigger("me", static function($name, $sleep=1, $hello="OK"){
$iCount = 0;
while ($iCount < 10) {
file_put_contents("./log/event.log", "Hello {$name} {$hello}!\n", FILE_APPEND);
sleep($sleep);
$iCount++;
}
});
Here the trigger is fired on 2 routes, hit each one up in your browser to see the output in the event.log
\Tina4\Get::add("/test", function(\Tina4\Response $response){
\Tina4\Thread::trigger("me", ["Again", 1, "Moo!"]);
return $response("OK!");
});
\Tina4\Get::add("/test/slow", function(\Tina4\Response $response){
\Tina4\Thread::trigger("me", ["Hello", 3]);
return $response("OK!");
});
The output to the event.log file should happen asynchronously whilst the routes return back immediately to the user browsing.
There is a built-in path that will trigger a deployment from a github webhook on your system
https://<site-name>/git/deploy
This requires the following to be in your .env to work; and you will need to generate a secret to be shared between the systems.
Additionally, you can specify directories from your repository to be included in your deployment with GIT_DEPLOYMENT_DIRS
Make sure you give permissions to git on the system you deploy to if you work with a private repository.
[DEPLOYMENT]
GIT_TINA4_PROJECT_ROOT=.
GIT_BRANCH=master
GIT_REPOSITORY=https://github.com/tina4stack/tina4-php.git
GIT_SECRET=0123456789
GIT_DEPLOYMENT_STAGING=..\staging
GIT_DEPLOYMENT_PATH=deploy-test
GIT_DEPLOYMENT_DIRS=["branding", "bin"]
SLACK_NOTIFICATION_CHANNEL="general"
docker run --rm -v %cd%:/data phpdoc/phpdoc:3 -d Tina4
docker build . -t tina4stack/php:7.4
docker push tina4stack/php:7.4
https://gist.github.com/rhacker/3550309
- Add health check
- Add GUID for each request, flow through to the rest of the code
sudo chown -R "$(id -un)":"$(id -gn)" /opt/homebrew
Example of a PHP info route if needed.
Route::get("/phpinfo", function(Response $response){
ob_start();
phpinfo();
$data = ob_get_contents();
ob_clean();
return $response($data, HTTP_OK, TEXT_HTML);
});
Example installing IMAP extension
brew tap kabel/php-ext
brew install php-imap