AscendPHP Framework is about Ascending developers to the next level of development by providing:

  • Simplified Development
  • Optimized Framework Speed
  • Separation of Framework Components
  • MVC Structure aka Model/View/Controller
  • PSR Standards

Simplified Development by replicating similarly liked parts of other frameworks.

Optimized Framework Speed by keeping code simple, clean, and focused on its purpose.

Separation of Framework Components by allowing developers to only have to use a small part of the framework without having to use the whole.

MVC Structure aka Model/View/Controller by using structure to organize the code.

PSR Standards by giving a standard for developers to follow.


AscendPHP has been developed to provide similar simplistic development to other frameworks but with more optimized code focused on only what is needed to make each part work.

It also has a focus on not just building out a framework but providing tools to easily develop CMS aka Content Management System through REST features, Authorization, Permissions, etc.

A few key concepts in the development of AscendPHP is the want to keep all the sql logic inside the models and the controllers just to be the mediator between the views and the models. Also, wanted to separate the logic for services aka Third Party Services outside the controllers as well.

With all this said the framework has a mysql database requirement to work because that has been what is needed for each of the projects which have so far been created using it. However, this does not have to be a requirement and could easily be decoupled if enough requests for the use without a database are made. Again, this is why it was designed how it is; to easily be separated out so it can do specifically what the developer needs.


AscendPHP Framework has many features so here is a list:

  • Command Line Wrapper with Interface
  • Session built on Database
  • Modules
  • MVC

Command Line Wrapper with Interface

Easy to created command line scripts within the Command Line Wrapper feature. It also includes a command line interface. Check out Command Lines tutorial.

Session built on Database

Currently the reason the framework requires a database no matter what is sessions are stored in the database but this id done for easy management and speed.

Modules

Added as recent as Sept 1, 2019. This allowed us to move the Examples out of the AscendPHP structure code and into the AscendPHP-Core but under the namespace Examples and then within an MVC framework same as AscendPHP structure. The future plans for this feature is to add another module for authentication which is already pre-built and can easily be used by developers without even writing a single line of code. However, if they want to change something they can easily copy/paste it out of AscendPHP-Core and into AscendPHP structure and modify it to their needs. More to come as we develop this out.

Modules

AscendPHP is built on the concept of MVC aka Model, View, Controller with additional CommandLine and Services to come sections for organization of code. Read in more detail about these in thier own sections.


AscendPHP Framework has many features built out but not implemented or that we want to expand. Here are just a few of the exciting features to come:

  • Authentication Area with Admin
  • Command Line Colors
  • Cron's in One Place
  • Model Chaining
  • REST Route
  • Validation
And many, many more as AscendPHP grows.

Authentication Area with Admin

Inclusion of a basic members area with register, confirmation, login, forgot password, roles, permissions, and basic admin control panel. This was in our previous version and want to bring it back.

Command Line Colors

Ability to do self::success('message') and see message in green or self::failed('error') to see errors in red. This was implemented in the previous version and want to bring this back.

Cron's in One Place

Load one cron master php file into crontab and then it runs all your crons for you.

Model Chaining

Extend the abilities of the model chaining to multi-table inclusion and more. See Model section to see our simple implentation until we expand.

REST Routes

The ability to have one Route line like below:

Route::rest($uri, $end_point);

Route::rest('/api/', 'user');

And it handle all of the following in the below format: GET (One/Many), POST, PUT, and DELETE.

  • GET /api/user/{id} :: Get 1 record.
  • GET /api/users :: Get all record.
  • GET /api/users?page=# :: Get all record; paginated.
  • GET /api/users?action=search&key=field&value=find-this :: Find only these records.
  • POST /api/user :: Create a record.
  • PUT /api/user :: Update a record by ID.
  • DELETE /api/user :: Soft delete a record by ID.

** Please, understand this is just a rough draft of our plans and they can change.

Also, included is a commandline tool which would make creating the model and class easy and fast.

Validation

Our previous framework version has an extensive list of validations and we want to bring that back.



Requires:

  • MySQL 5.5+
  • PHP 5.6+ (Eventually PHP 7+ Only)
  • PHP PDO Extension

Follow AscendPHP readme. AscendPHP-Core is the composer package which has the core files. More components, later.


Folders:

  • App - Stores specific files for this application
  • App/CommandLine - Custom command line classes
  • App/Controller - Middleman which controls data from Models to Views aka Database to Display
  • App/Model - Structure of tables for database and all sql calls in function form
  • App/View - Framework code for content to display to users and/or public
  • public - Files for the public to see
  • public/js - Javascript
  • public/css - CSS
  • public/fonts - Fonts
  • storage - Files to be stored
  • storage/cache - Cache files
  • storage/data - Data files
  • storage/log - Log files
  • vendor - Third parties through composer

Files:

  • App/config.php - Configurations
  • App/config.sample.php - Example Configurations
  • App/routes.php - List of routes for applications
  • php ascend - Command line tools

How to use AscendPHP Command Line

Inside the App\CommandLine folder is where of course all the framework command line scripts will be. To use the command line type the following into the terminal.

php ascend

The above will give you all available commands. Currently only sql:migrate is available. sql:migrate will take all Models and create the database for them. Make sure you have setup config.php and filled out the required database files.

php ascend sql:migrate

How to Create a Command Line Script

Below is an example of a command line script.

<?php namespace Ascend\Examples\App\CommandLine; use Ascend\Core\CommandLineWrapper; class ExampleCommandLine extends CommandLineWrapper { protected static $command = 'example'; protected static $name = 'Example Command Line Script'; protected static $help = 'example [arg1] [arg2] [etc]'; public static function run($arguments = null) { if (is_null($arguments)) { self::out(' >> Start << '); // call some static function here self::out(' >> Complete <<'); } else { // call some static function here if arguments are passed and do if/else or switch to check } } }

Line 1. Make sure model is in namespace App\CommandLine.

Line 3. Add the use Ascend\Core\CommandLineWrapper which is what all command lines are built off of.

Line 5. Declare the class, then the command line name CamelCase, then extends CommandLineWrapper.

Line 7. Create a private static with name $command and write its value for the name of the command you want to create.

Line 8. Create a private static with name $name and write information about it.

Line 9. Create a private static with name $help and write how the command will be called and list arguments available for example. These are listed when calling just "php ascend" in the command line.

Line 11+. Create a public static function named run and start building out the command line script. Currently, there are few builtin functions but self::out('message goes here to screen') is one. The framework did have the capability to do colors within the command line from our previous version but it needs to be re-implemented it.


How to use AscendPHP Controller

Inside AscendPHP all functions called by the Route class are static.

<?php namespace Ascend\Examples\App\Controller; use Ascend\Core\View; class ExampleController { public static function viewIndex() { $tpl = []; $tpl['container'] = View::html('index.php', $tpl, 'Examples'); echo View::html('_template.php', $tpl, 'Examples'); } }

Line 1. Make sure controller is in namespace App\Controller;

Line 3. Do a use Ascend\Core\View; // This is used for getting view files easily and also allows passing variables.

Line 5. Define class [ClassNameController]. We always append Controller and CamelCase.

Line 7. Within the class naming is up to you but we choose to name things like so:

  • viewPageName(); // its a view then its name
  • getUser(); // to say method then whats it doing
  • postUser(); // to say method then whats it doing

Now, why do we call View::html() twice. The reason is the first one on line 10 is to get the page content. The 2nd on line 12 is to get the template. If you look it loaded line 10 into $tpl['container'] then we loaded $tpl into line 12 and inside the template is a variable $container. You could also pass $tpl['title'] = 'name of site'; and that is a variable inside the template we made.


A few things to keep in mind about our models:

  • They are loaded through running a command line script listed below.
  • They are stored in a migration table which keeps up with changes so every time a Model field change is made; run the migration.
  • Models should hold all sql. No sql should ever be in a controller.

php ascend migrate

Eventually the command rollback will be added for 1 or more.

php ascend migrate rollback [#]

Required Model Features

  • $table = Name of table
  • $fields = Array of fields names key and value sql type set

Below is the skeleton of a model. Below the skeleton there are explanations per line.

<?php namespace Ascend\Examples\App\Model; use Ascend\Core\Model; class Example extends Model { protected static $table = 'examples'; protected static $fields = [ // 'id' => 'int unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY', // this is automatically created for every model 'sub_id' => 'INT UNSIGNED NOT NULL', 'name' => 'VARCHAR(255) NOT NULL', 'is_active' => 'TINYINT UNSIGNED NOT NULL', ]; protected static $seeds = [ ['sub_id' => 0, 'name' => 'Example 1'], // 1 ['sub_id' => 1, 'name' => 'Example 2'], // 2 ]; /* protected static $seeds_skip = true; protected static $seeds = [ 'file' => 'baby-names.csv', 'map' => [ 'name' => 1, ] ]; */ public static function getAllActive() { $table = self::getTableName(); // $sql = "SELECT * FROM {$table} WHERE is_active = :is_active AND deleted_at IS NULL"; // return self::many($sql,['is_active' => 1]); return self::where('is_active', '=', 1)->orderBy('created_at', 'desc')->all(); } }

Line 1. Make sure model is in namespace App\Model;

Line 3. Add the use Ascend\Core\Model which is what all models are built off of.

Line 5. Declare the class, then the model name CamelCase, then extends Model

Line 7. Define a protected static $table variable with "table name"

Line 8: Define a protected static $field variable as an array.

Line 9+: List each table field as key and mysql type as value in array per line.

** id is by default listed as the primary key for the table. I plan to have a way to change the primary key in the future.

** Also, created_at, updated_at, and deleted_at are default.ly created for every time. I plan to have a way to add a variable later to disable this.

That is all that is required to create a Model. The rest of the features below are optional.

Optional Model Features

Seeding the table on first load either manually or by csv

Line 15-18: When adding $seeding = [] into the model it allows for pre-filled data to be loaded immediately after creation. Every row should have the keys/values for each field in the table.

Line 20-27: Because having manually loaded seed data vs loading from a csv is not allowed at the same time; the data coming from a csv is commented out. However, if you have a massive amount of data you need preloaded then follow these steps to load from a csv.

Line 23: Start of array to make each row in csv to a field in table. 'map' is always used.

Line 24: Key is the $fields[key] and value is the column in csv. Add as many as you like and not all table fields have to be filled.

Creating functions to call for getting results

Line 29: Defines how to create a static function for the Model to be called on. If I were to call line 29 in a controller I would do such in example below. All called functions are static functions.

$rows = Example::getAllActive();

Line 31: Gets the name of the table from the model you are within.

There are 2 ways to write sql: raw or chaining.

First, the commented out version is raw.

Line 33-34: Has the raw sql and then returns many results as a multi dimensional array and the key being the primary id.

Line 34: If you were to change it to return self::one($sql) it would result in a single array with key/values.

Second way is to call a query through chaining. Now, I will warn it it still under heavy development and is minimally built out but we will be working to add more in the future for easier code-ability.

Chaining will work as displayed on line 36. First, call self to reference model inside or call the model by name if within a controller. Next, define where and you can define as many as you like chained. Then, define orderBy as displayed.

And last, either call ->first() or ->all().

->first() will only bring the first record in and return a key/value array.

->all() will return a multi dimensional array with primary key as key and array with key/values.


AscendPHP tries to keep things separate to make it easy to manage and maintain. The 2 main parts to a few are the template and the page. AscendPHP likes to name the template files _template.php to keep them at the top easily findable then all the pages below. Within these files php is allows so instead of using a templating engine we just allow easy access for now. The way variables are passed in are loaded as key/value $tpl[key] = value but they are extracted so they turn into the real variable; $key. Just for now if you want examples to the App/View or vendor/dvarner then Ascend/Examples. More documents as we develop this more.


Ok, to get started with routes you must open App/routes.php.

Once you have the file open, there are a few things to keep in mind.

First, the two "use" at the top are required at all times to make the page work.

Lets go over what those are:

Route -> is used to call all your routes; pretty self explanitory.

SiteLog -> logs every action on the site. As you see its a model.

Next, SiteLog::insertUri() is the action which does the logging. If you choose you do not want to log every action to the site then comment this out. The use behind this is to build your own user stats for the site.

Then, there is Route::display404(). This should always be at the end of the script so a 404 is displayed to the user if no pages are called. So basically the way Route:: works is it goes through every one like if statements until it finds a match then executes and dies.

So now lets look at the current route we have. It has 3 parts:

Route::view('/','Page','viewIndex');

The "/" which is the uri it matches aka the part after the domain.com -> /everything-that/is-here.

The "Page" which is the Controller inside App/Controller folder.

Then, "viewIndex" which is the static function inside the "Page" Controller.

**Keep in mind all classes and functions in routes are case sensitive.


To get started, lets created a duplicate route to Controller Page and static function viewIndex.

Route::view('/test','Page','viewIndex');

Now type "your-domain.com/test" the above will route to the same page as the index.

Lets say we want the route to return as a json.

Route::json('/test','Page','viewIndex');

GET Method: Just example.

Route::get('/test','Page','getUser');

POST Method: Just example.

Route::post('/test','Page','postUser');

PUT Method: Just example.

Route::put('/test','Page','putUser');

DELETE Method: Just example.

Route::delete('/test','Page','deleteUser');

REST Method: (UNDER CONSTRUCTION).

Route::rest('/test','Page','restUser');