How to get started with PHP Jet

1. Put other frameworks out of your head ;-)

PHP Jet is not just "another" PHP framework. PHP Jet does a number of things differently (and I believe better for most situations) than other frameworks. For example, you won't find any "routes", no template system, but also no non-standard procedures and technologies or data formats. PHP Jet builds only on standard PHP 8 and standard generally applicable software development principles.

PHP Jet has no dependencies on anything (not even on composer, which is possible but not necessary to use) except for the Bootstrap CSS framework, which it uses by default, but which can be "swapped" for something completely different. PHP Jet does not need any special (non-standard) web server or regular web hosting settings.

To work with PHP Jet, you won't have to learn many new things, apart from knowing PHP itself and understanding the philosophy of this framework. PHP Jet is extremely simple.

PHP Jet is relatively small in terms of volume / size of source codes and very simple in its essence, but it is all the more powerful. A full-fledged sample application is already available in the base, containing the basis of everything a standard web project needs, and last but not least, it is part of Jet Studio, where you can (but you don't have to) simply and conveniently "click" everything "annoying".

The strength of PHP Jet is precisely in the purity and maximum flexibility of the SW architecture design, which will allow creating quality online applications much more efficiently and straightforwardly. During the 12-year evolution of PHP Jet, I did not focus on adding more and more features, but on verifying whether the design is really good for practical use in the real world, even at the cost of removing some features. It is a framework that arose in practice and was created by a person from practice, and I release it only after I have tested it in practice.

But in order to properly understand PHP Jet, it is necessary to detach from a number of dogmas that arose especially in the last decade.

It is necessary to have an open mind, because it is not important to "cram: how to do what, but to understand correctly what and how it works and why. If you understand the essentially ridiculously simple philosophy of PHP Jet, you will already master this framework easily and quickly, and I believe that it will be a good partner for your projects.

2. Installation

If you just want to get your hands on PHP Jet, the procedure is very simple:

  • Make sure you have PHP 8 installed, including all the usual INTL , PDO , and mbstring modules.
  • Download the package from GitHub and unzip it.
    You can use composer: composer create-project mirekmarek/php-jet
  • Navigate to the directory where you downloaded and unzipped PHP Jet.
  • Run this command: php _playground/start.php
  • Open the URL http://localhost:8000/ in your browser (if you did not specify a different address and port during startup procedure).
  • If you want, then you can create some MariaDB/MySQL test database (in the near future also PgSQL, Oracle and MS SQL) for testing purposes, but it is not necessary. PHP Jet also supports SQLite and that is good enough for testing purposes.
  • Complete the installation using the web installer.

Installation on a full-fledged web server (Apache, NGINx) is also simple. See the documentation .

3. Quick introduction to the sample application

After you "click through" the installer (which, by the way, is the general basis of the installer, on the basis of which you can create your installer - for your SW product), then you will see the entire sample application, which includes:

  • A simple website containing many subpages, which mostly represent a demonstration of PHP Jet's standard capabilities and at the same time a test of various functions, be it localizability , forms , ORM , or REST server and client, and so on.
  • A non-public part of the website for demonstration and testing of authentication and authorization options, including integration into the Jet MVC .
  • Administration with a number of modules (e.g. for managing users and roles, viewing logs, but also a primitive CMS base).
  • REST API server and at the same time client for testing.
  • A very helpful Jet Studio development environment with a web-based graphical UI.
  • Integrated profiler .
  • ... And all of this divided into application modules (micro-applications) to keep the project organized. Of course, the sample application fully uses the unique philosophy of Jet MVC , of course the ORM DataModel and a whole range of other capabilities of the PHP Jet framework.

Everything is set up in such a way that you can immediately examine everything, try it, change it, simply "play". You immediately have the basis of a real application neatly divided into a clear structure .

4. The first "route"

As I already wrote - PHP Jet has no routes in the sense that you know them from other frameworks. In PHP Jet, it is simply not the case that the URL is bound to some route , which is bound, for example, to some controller (but don't worry, controllers are really blessed in PHP Jet ;-) ).

How Jet MVC works is a topic in itself, but I'll try to explain as briefly as possible here:

  • The URL of the request does not represent any "route", but the URL of the base and the page .

  • The base determines which part of the application it is. Is it the administration? Is it a REST API (or other API) server? Is the website visible to visitors? Or anything else? (the number of bases is not limited)
    And what localization does this part of the site have and what localization does the given URL rebuild?

  • The base has some basic URL that also corresponds to the locale .
    So, for example, a URL
    represents the en_US locale of the e-shop while the URL
    represents german locale.

    However, this applies to the production environment. During development, the URL of these bases can be:

    Just change the base definition - nothing more needed.

  • Just like a page (we'll show that in a moment), a base is an entity (=something more complex, not just a route definition) that can be worked with in different ways. Here is a small example: /*
     * List of locales of a base divided into active / inactive
    $base MVC::getBase('some-base');

    $base->getLocales() as $locale) {
    $base->getLocalizedData($locale)->getIsActive()) {
    'Locale '.$locale->getName().' is active<br>';
        } else {
    'Locale '.$locale->getName().' is not active<br>';

     * Generating homepage URL of a base for Czech locale

    $locale = new Locale('cs_CZ');
    $URL MVC::getBase('some-base')->getHomepage$locale )->getURL();

     * Generating title of page for Czech locale
    $locale = new Locale('cs_CZ');
    $title MVC::getBase('some-base')->getLocalizedData$locale )->getTitle();
    You can find much more in the documentation.

  • Each base and locale contains separated set of pages. For example, the complaint form can have a URL production in en_US locale

    On the cs_CZ locale

    However, development URLs can be defined like this:


And before we get further, let's stop at one important thing and the core of the whole idea. Surely you have not missed the fact that the URL is a variable thing! The same page (here, for example, the claim form) is always the same from the point of view of the application logic - the same micro-application / application module always takes care of the claim form, regardless of which URL it is located on. Only the locale and the URL change depending on whether the page is currently on localhost, on the test environment or on production environment. Despite the fact that the customer (project sponsor) can decide to change the URL at any time.


The URL of the request / page is not a fixed / constant value - it can change at any time and it is therefore pointless to integrate such an entity into the application logic . Connecting the application directly to the URL by defining some routes within the application is a bad way.

Moreover, the whole problem is not only about the URL. The pages must be linked within the navigation, the pages must have a lot of meta information and so on . Therefore, in this respect, PHP Jet may resemble some kind of CMS, but it is only a different perspective on the issue. And it's a view that corresponds more to the real world and is much more flexible and convenient than somehow writing down "routes" and perhaps even naming them.

But let's go back. So I already have a base, a specified locale and a page. What's next?

  • The page has a layout (Note: If it is not an API server, or anything that sends back data and not HTML output intended for the end user - for example, the following does not apply to the REST API, of course. But now let's solve normal page.)

  • Individual positions are defined within the layout.

  • Content is linked to these positions:

  • The content on individual positions can be static (just a static piece of HTML determined by the definition), but most often an application module / micro-application is bound to the given position.

  • For example, on the left side of the page there can be a menu displayed by one module, at the top of the page there is a small navigation generated by another module, and in the middle of page is an article displayed by another module. An application module is actually a micro-application that runs within a page. And of course you can define the positions as you like.

  • Individual application modules / micro-applications already have their own controllers and views.

  • Pages can be operated in different ways. A page is not just a "named route" (for example), but it is much more. It is an entity with which you can create links, operate with meta information and so on - there's really a lot of it, see the documentation.
    Examples: /*
     * Generation pages URL (specific page, current base, current locale)
    $URL MVC::getPage('some-page-id')->getURL();

     * Generation menu title  (specific page, current base, current locale)
    $title MVC::getPage('some-page-id')->getMenuTitle();

     * Inserting a meta tag into the current page
    $custom_meta_tag Factory_MVC::getPageMetaTagInstance();
    $custom_meta_tag->setContent('Jára Cimrman');

    MVC::getPage()->addMetaTag$custom_meta_tag );

  • By the way... A page does not necessarily have a layout and associated application modules. Even in PHP Jet, a page (some URL) can be associated directly to a controller, similarly to other frameworks (however, the MVC system of bases and pages is still present). But it is not the main line of thinking about the application. It is only an option for a situation where such a solution would be more appropriate. In PHP Jet, it is assumed that what is right for a project is best known by the developer of the a project and not by the framework.

I promised the first "route" and there will be none. Sorry ... But you know what? Try making your first page in Jet Studio. Believe me, it is much better and much more natural for our work than the commonly used routes.

5. Locability

You may have already noticed that locability is an integral part of PHP Jet. Already Jet MVC firmly calculates the localizability of the application. And therefore, of course, a translator or formatting of information according to national customs must not be missing.

6. Application modules / micro-applications

You did not miss the constantly repeated topic of application modules . There has been a lot of talk lately about micro-services architecture. Know that this is actually the same thing. It's the same philosophy and the same benefits - dividing the project into small easy-to-maintain and ideally reusable micro-applications. That's PHP Jet itself - it's been conceived and designed that way from the ground up. It's just that there's no need to create any complex server infrastructure to run such an application.

7. ORM

The integrated ORM DataModel is typical mainly in that it is truly an ORM. Thus, it does not look at data entities from the perspective of data tables in relational databases and SQL, but from the perspective of classes. When you design (click in Jet Studio - why do it manually?), for example, an entity representing an article or goods in an e-shop, then it is considered primarily in terms of classes and their arrangement. The DataModel then takes care of such "annoying" things as saving, loading, updating and deleting data.

Don't look for anything like the migrations directory. Definitions of entities (as they are stored in the database) are where they should be - directly in the classes representing the entities. Which is not so unique - in that PHP Jet is not original and resembles, for example, Doctrine.

The basic philosophy is similar, but unlike, for example, the mentioned Doctrije, Jet DataModel is much smaller and simpler , it solves many things much more simply, and at the same time a tool is available within Jet Studio, where it is possible to "click" entities . For example, Jet DataModel doesn't need anything like Entity Manager, proxy classes and so on. Using the DataModel is as straightforward, natural and simple as possible.

Example? There are:

* Get Article by ID
$article Content_Article::get$id );

* Change of article date:
$article->setDateTimeData_DateTime::now() );

* Get instances of all articles
$articles Content_Article::fetchInstances();

 * Get instances of articles that are created a year ago 
 * and have the word PHP or Jet in their LOCALIZED title 
 * using an INNER RELATIONSHIP entity
$articles Content_Article::fetchInstances(
where: [
'date_time <=' => new Data_DateTime('-1 year'),
'article_localized.title *' => ['PHP''Jet']

 * Loading of the map of article titles in the Czech localization. (Field key = article ID, value = title)
$articles Content_Article_Localized::dataFetchAssoc(
select: ['article_id''title'],
where: [
'locale' => new Locale('cs_CZ')

ORM DataModel is designed in such a way that it is possible to achieve the best possible performance of the application. So it offers different options for example how to load data (partial loading, raw data loading, loading using different procedures, ...) and so on.

With a proper understanding of the ORM DataModel , it is possible to develop very powerful applications that can be transferred to different database systems and at the same time save a lot of routine and annoying work. However, DataModel does not interfere with your work and does not try to think for you! . It helps you with your routine and leaves the thinking to you - you know best what and why you are doing.

If you want, go to Jet Studio and click on your own entity, or modify one of those that the sample application already has. It's simple, absolutely simple.

8. Configuration

You have already performed the configuration by "clicking" in the web installer.

Jet has two levels of configuration. The configuration of the platform itself is basic. This is used to set such things as turning on / off developer mode, cache and many other things. Nothing special ...

However, you filled out several forms in the installer. For example, you were creating a database connection, but not only that. And that's more interesting ;-)

PHP Jet has an application configuration system. The point is that you can create configuration entities (classes with a configuration definition) and bind forms to them, and then very easily create, for example, that installer you went through.

9. Forms

And of course, working with forms cannot be missing in PHP Jet. It's another very broad topic, because the form support in PHP Jet is really very sophisticated - but still very simple in principle.

What can it do?

  • Of course, the basic definition of the form and its fields using the appropriate classes.
  • All kinds of field types are pre-implemented, but nothing prevents you from changing the implementation or creating new field types .
  • Capturing input data (including, for example, from a REST request), data validation, working with errors and also input security.
  • Cooperation with locale and translator - translation of everything from field labels to error messages.
  • A system for easy, unified, but still very flexible rendering of forms .
  • Mapping forms directly to classes.
  • Tool for clicking form definitions mapped to classes in Jet Studio.

10. And so on...

And that's not all Jet can do... There's more:

  • Thanks to the factories system, you have the possibility to replace the "guts" of PHP Jet with your own implementations without breaking the application. For example, do you not like how the MVC page is implemented? Nothing prevents you from creating your own implementation and simply putting it into the system while maintaining the entire philosophy and functionality.
  • The authorization and authorization system is also very interesting.
  • No developer should definitely forget to use profiler .
  • There is no lack of facilitation of general work with application navigation .
  • Jet also includes a server-side UI generation system and, of course, AJAX support.
  • And many other useful things like sending e-mails , working with images , working with data tree structure , and so on, ...

If you want to ask something, I recently activated discussions on GitHub , where I will definitely be happy to answer you, or you can still contact me directly.

Thanks for reading and I hope PHP Jet makes your work more enjoyable!