Develop Your First Package
Follow the guide below to gain a base understanding of Apex, and within minutes be up and running with your first published Apex package on your new SVN repository.
Install Apex
If Apex is not already installed, you may either use the standard installation guide, or simply use the four step Apex install by running the below commands. Please note, this does not require PHP to be installed on your machine.
git clone https://github.com/apexpl/apex
cd apex && mv install_example.yml install.yml
sudo docker-compose up -d
sudo docker-compose exec apex apex
That's it! Your new fully featured administration panel with various base packages can now be found at http://127.0.0.1/admin/
Various places in the below guide will ask you to run apex commands. If using Docker, you may access your container's bash prompt with the following command:
sudo docker-compose exec apex bash
Create and Configure Package
Let's develop out a quick package that provides random advice to our visitors, and saves the advice to the database. Run the command:
apex package create advisor
This will create the base structure and directories for the new package. In a text editor open the newly created file at ~/etc/Advisor/package.yml, and replace it with the following contents:
general:
description: Random Advice Generator
access: public
price: 0
acl:
branches: public
releases: maintainers
trunk: team
config:
default_term: life
menus:
admin_menus:
area: admin
type: parent
position: after users
icon: fa fa-fw fa-chat
alias: advisor
name: Advisor
menus:
view: View Advice
admin_settings_page:
area: admin
parent: settings
alias: advisor
name: Advisor
Save and close the file, and run the command:
apex scan advisor
This will scan the contents of the package.yml file, and update the database accordingly. Refresh your administration panel, and you will notice the new menus that you defined.
Create Settings Page
Let's quickly develop out the new Settings->Advisor menu. Run the command:
apex opus admin-settings advisor admin/settings/advisor
You may now visit the Settings->Advisor menu within your administration panel, where you will be able to define the configuration variables added to the package.yml file. Naturally auto-generated code only goes so far, and the view for this menu can be found at the files:
- /views/html/admin/settings/advisor.html
- /views/php/admin/settings/advisor.php
Create Database and Model
We will also want to save all advice obtained to the database. Open the file at /etc/Advisor/install.sql, and enter the following contents:
CREATE TABLE advice (
id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
term VARCHAR(100) NOT NULL,
advice_id INT NOT NULL,
advice TEXT NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
Next, execute the SQL code against the database with the command:
apex migration install advisor
Alternatively, you may connect directly to the database and copy and paste the SQL code by running the sql
command without any arguments:
apex sql
Next, create the model for the new database table with the command:
apex opus model Advisor/Models/Advice --dbtable advice --magic
Confirm creation of the parent directory when prompted, and this will create a new model class located at /src/Advisor/Models/Advice.php. Open the file, and you can see it's a straight forward PHP class that utilizes constructor property promotion, and has one property for each column in the database table. Due to adding the --magic
flag in the above command, all properties can be accessed directly at $obj->prop_name
and as you will notice there is no standard get / set methods within the class. If you would prefer to use the standard get / set methods simply omit the --magic
flag from the above command, and they will be generated within he model class.
NOTE: Although it is highly recommended you write your database schemas in SQL, Apex does also have full support for Eloquent and Doctrine models and migrations if you prefer to use either of those. You may view full details in the Database section of the documentation.
Add Some Code
The /src/Advisor directory is your blank canvas where you may develop and structure anything you wish, and its root namespace is App\Advisor
. For example, add a file to /src/Advisor/ApiClient.php with the following code:
<?php
declare(strict_types = 1);
namespace App\Advisor;
use Apex\Svc\HttpClient; // PSR-18 compatible http client, defaults to Guzzle with installation.
use App\Advisor\Models\Advice;
class ApiClient
{
#[Inject(HttpClient::class)]
private HttpClient $http;
/**
* Get advice
*/
public function getAdvice(string $term):?Advice
{
// Send HTTP request to Adviceslip API
$res = $this->http->get("https://api.adviceslip.com/advice/search/$term");
// Decode JSON
if (!$json = json_decode($res->getBody()->getContents(), true)) {
throw new \Exception("Did not receive valid JSON as response.");
}
$slips = $json['slips'] ?? [];
// Return null, if no results found
if (count($slips) == 0) {
return null;
}
// Get random advice
$slip = $slips[array_rand($slips)];
// Add to database
$advice = Advice::insert([
'term' => $term,
'advice_id' => $slip['id'],
'advice' => $slip['advice']
]);
// Return
return $advice;
}
}
This class contains one method called getAdvice()
that simply sends a request to the free API service to obtain a random piece of advice. It then inserts the advice received into the database, and returns the new model instance created.
Create View
Now that we can get advice, we need to give it. Create a new view with the command:
apex create view advisor advice
echo "<h1>Advice for ~term~</h1> <p>Your advice is ~advice~</p>" > views/html/advice.html
This will create the new view and register it to the advisor
package so it's included when publishing the package to the repository. Next, open the file at /boot/routes.yml, and add an additional line to the routes
section:
routes:
default: PublicSite
"advice/:term": PublicSite
Simply add the new line "advice/:term": PublicSite
to the routes.yml file, which signifies one dynamic path parameter is accepted for the /advice path.
Now open the file at /views/php/advice.php, and enter the following contents:
<?php
declare(strict_types = 1);
namespace Views;
use Apex\Svc\{App, View};
use App\Advisor\ApiClient;
/**
* Render the template.
*/
class advice
{
/**
* Render
*/
public function render(View $view, App $app, ApiClient $client):void
{
// Get term
$default_term = $app->config('advisor.default_term');
$term = $app->pathParam('term', $default_term);
// Get advice
$advice = $client->getAdvice($term);
// Assign variables to view
$view->assign('term', $term);
$view->assign('advice', $advice->advice);
}
}
That's it, now open your browser to http://127.0.0.1/advice/love or any term you wish to gain some insightful wisdom on!
The above view first retrives the term to search for from the URL being viewed, and if no term is specified, uses the default term as defined within the administration panel. It then makes the API call to retrieve the advice, and assigns the two template variables to display within the web browser.
Publish Your Package
Run the command:
apex commit advisor -m "Initial commit"
This will step you through the initial process to register your Apex account, and create the necessary keys for digital signatures and to access your repositories over SSH. It will only take a couple quick minutes, and upon completion your new repository can be found at:
[data-line=-1]
https://code.apexpl.io/your-username/advisor
Before you can install the package on other Apex systems, create a release with the command:
apex release create advisor 0.1
You will be prompted for your signing password, and upon success you can now instantly install the package on other Apex systems with the command:
apex install username/advisor
Congratulations, you've successfully developed and released your first Apex package! Apex also has full support for commercial and private packages, allowing you to instantly begin earning money from your code, or keep your code private as desired. If running your own repository is preferred, Apex Enduro is also available.
To continue, check out the various other available guides or the full developer documentation. If you ever need any assistance with Apex, you can always ask on the /r/apexpl sub Reddit.