Getting Started


Meet Zap

Zap is simply a framework for creating a PHP-based web application, employing the PHP Model-View-Controller (MVC) paradigm, where JavaScript Single-Page-Application (SPA) style can also be applied.

Zap offers flexibility without unnecessary complexity. Thus who are familiar with other popular PHP frameworks will find Zap simpler and easier to use. Even when you are new in PHP-based web development, Zap suits you.

Zap can be used for building PHP-based web apps in any scale. Is it a small project or larger? Zap can be your choice. As with other frameworks, Zap also supports Vite, if you like to work with JavaScript-based frontend.

Not familiar with Vite? No problem! Zap uses Litewire, which is an inherent part of the framework. Litewire is an HTML-first AJAX engine and dynamic component loader designed to build modern, interactive single-page-like applications with minimal client-side JavaScript configuration.

Backend

Pure PHP!

Behind the screen, Zap works with controllers, models, middlewares, and a list of other backend utilities. For database, currently Zap only supports MySql and Sqlite. However, you can use other database layers, though you will need to make adjustments.

Frontend

Zap PHP uses BladeOne, just like Laravel. However, as said, Vite is also welcome. JavaScript components can also be injected or imported using Zap Litewire. We haven't tested whether Zap can work with other frontend frameworks like React, Vue, Svelte, etc.

By default, Zap includes Bootstrap for styling, but you can replace it with other CSS frameworks like Tailwind, Bulma, Material CSS, etc.

The look of your web app will depend on how creative you are, by the way.

Between both

Well, with Litewire, you can call a method in the controller, as long as it is defined in the route, and put whatever it returns to the target element. Form validation, for instance, can be made without doing AJAX manually.

Assets (CSS and JS) are loaded dynamically, depending on how you set them in the controller. You can also decide whether a JS asset is put on the header or footer. You can learn about Dynamic Assets Loading later.

Zap Features

Zap is a lightweight PHP framework, not as robust as Laravel or others. We do not want to make a full-stack PHP framework. However, users can always extend and expand the functionalities of their Zap-based app.

Familiar Routing Pattern

Zap uses familiar routing patterns for routes, with middleware and named routes supported.

// routes/web.php
use Zap\Core\Routing\RouteFacade as Route;
Route::get('/', 'HomeController@index')->name('home.index')->middleware('guest');
Route::post('/upload', 'HomeController@upload')->name('upload');

With named routes, you can get the route by using our route() helper anywhere in the app.

route('home.index')

Familiar Controller Pattern

Zap also uses familiar controller pattern. Given the example routes above, the HomeController may look like this:

<?php
namespace Zap\App\Controllers;

use Zap\Core\Base\BaseController;
use Zap\Core\Http\Request;
use Zap\Core\Utils\Security;

class HomeController extends BaseController {
 public function index(){
 $data = [
 'assets' => $this->assets->setAssets(source: 'local', header_css: ['icons', 'aos'], header_js: [], footer_js: ['aos']),
 //'vite' => ['resources/css/app.css','resources/js/app.js'],
 '_title' => 'Zap PHP',
 '_description' => "" ,
 '_robots' => 'index, follow',
 '_bodyClass' => 'bg-light',
 //'navbar' => 'navbars.home',
 //'footer' => 'footers.home',
 ];
 
 $html = $this->render('home/index', $data);
 return $this->response($html);
 }

 public function upload(Request $request, Security $security){
 $security->get_instance();
 if(!$security->validate_request()){
 return $this->json(['error'=>'Invalid token'], 403);
 }

 $file = new File;
 $upload_path = $request->input('upload_path');
 $file_name = $request->input('file_name', null);

 $encrypt_name = ($file_name === null);
 
 $upload_config = [
 'upload_path' => BASE_PATH . $upload_path,
 'max_size' => $request->input('maxsize'),
 'allowed_types' => ['jpg', 'png'],
 'encrypt_name', $encrypt_name
 ];

 $file->init_upload($upload_config);
 $file->do_upload('file', $file_name);
 return $this->json($file->get_upload_errors());
 }
}

As you can see, the index() method returns a view, while the upload() method does not.

When a method (or route, in this case) returns a view, except for components, assets are managed. In the example above, Vite is not implemented.If the page has a navbar and footer, uncomment the keys and make sure that the file home-navbar.blade.php exists in the navbars directory, also with the footer, respectively.

The upload() method in this example receives request via AJAX and returns a json response. It uses the Security class to validate the request to prevent CSRF attack. This also applies with normal non-GET requests via forms.

Familiar View Pattern

Zap uses BladeOne, a Blade templating engine for non-Laravel apps. In the index() method above, a blade file index.blade.php exists in the home directory.

@extends('layouts.base')
@section('content')
 Content goes here...
@endsection 
@push('scripts')
<script>
 JavaScript here...
</script>
@endpush

This view extends a layout, which is base.blade.php, which exists in the layouts directory.

Familiar Model Pattern

Models are used to interact with database, and they are called from the controller method. For instance, inside the Models directory, there is a TestModel class with a method like sayHello(string $name). The model may look like this:

<?php
namespace Zap\App\Models;
use Zap\Core\Base\BaseModel;

class TestModel extends BaseModel {
 public function sayHello(string $name){
 return "Hello " . $name;
 }
}

In the controller method, this model method can be called and the return can be stored into a $data key:

$data = [
 //other keys...,
 'hello' => $this->model('TestModel')->sayHello('John Doe')
];

When working with the database, one can use the db() method or built-in CRUD methods from the BaseModel class.

public function addNewUser(array $userdata){
 $table = 'users';
 try{
 //$this->db()->query(string sqlquery..., array parameters...);
 $this->create($users, $userdata);
 return [
 'error' => false,
 'message' => 'New user added'
 ];
 } catch (\Exception $e) {
 return [
 'error' => true,
 'messagge' => 'Error: ' . $e->getMessage()
 ];
 }
}

Security

Zap is not a fort or castle, but it is secure. By default, a CSRF token is added in the head as a meta tag. This token will be sent along with Litewire AJAX and validated in the controller method. With normal form, one can add the following line to add the token:

{!! service('\Zap\Core\Utils\Security')->set_token_field() !!}

Alternatively, enable litewire-auto-csrf-plugin in the config/js.php file by setting the default key to footer. This will automatically add a token field in the forms. The upload method above shows how you can validate the token.

To prevent your app directories from being accessed, except for public directory, two .htaccess files have been added. However, you may want to put another .htaccess or an index.html file into each directory to make it more secure.

Dynamic Assets Loading

You do not want to load jQuery or Datatables assets on pages that do not need them, but you want some assets to load on all pages by default. This helps you prevent loading unneeded CSS and JS assets. Also, you can determine whether a JS assets should be put within the header or somewhere right before the closing body tag.

In Zap, you do this in the controller methods that return a view.

$data = [
 'assets' => $this->assets->setAssets(source: 'local', header_css: ['css1', 'css2'], header_js: ['js1', 'js2'], footer_js: ['js3', 'js4']),
 //other keys...
];

The array keys in the header_css, header_js, and footer_js are "nicknames" of the assets. Meanwhile, the source can be either "local" or "cdn". You do not put full URLs here, but the nicknames. First, you need to register the assets in the css.php and js.php files in the config directory.

If there is no other assets to load but the default ones, just leave the arrays empty, except for the source.

"local" means local assets stored in the public/assets/css and public/assets/js directories.

Whenever you add new assets to your app, register them first.

<?php
//config/css.php
//By default, local reads the file in public/assets/css directory

return [
 //other css registry
 'assetnickname' => [
 'local' => 'assetfilename.css', //if in subdirectory, dir/dir/assetfilename.css
 'cdn' => 'cdn URL of the asset',
 'default' => 'header' //or none
 ],
 //other css registry
];
<?php
//config/js.php
//By default, local reads the file in public/assets/js directory

return [
 //other js registry
 'assetnickname' => [
 'local' => 'assetfilename.js', //if in subdirectory, dir/dir/assetfilename.js
 'cdn' => 'cdn URL of the asset',
 'default' => 'header' //or footer or none,
 'type' => 'text/javascript', //or module
 'attributes' => '' // or defer
 ],
 //other js registry
];

Litewire

Zap introduces to you Litewire, a partial blend of Livewire, HTMX, and AlpineJS. Litewire is as Livewire to Laravel, but Litewire can be used in any PHP frameworks.

Due to its vast coverage, it will be documented in another page.

Command Line Interface (CLI)

Zap has a simple console for making controllers, models, migrations, etc. This too, will be documented in another page.