Sugarcore Intro

Also dein Forschergeister gefällt mir :D allerdings ists so dass das System noch in der beta steckt und hier und da es noch nicht so ist wie geplant. Dennoch baue ich gerade das dritte Projekt damit, welches natürlich auch dazu beiträgt den Core stable zu kriegen und dann auch mal die Doku zu schreiben vorher macht es für mich leider auch nicht so viel Sinn etwas zu dokumentieren was sich noch ändern kann, aber ich frag trotzdem mal kurz an für dich, weil du so nett gefragt hast =)

also wenn du es schon am laufen hast und diesen besagten Screen bekommst, ists wohl schonmal installiert, aber es gibt noch keine Anwendung. Das einfachste wäre nun folgendes:

Du öffnest eine Konsole / Terminal / Eingabefenster / SSH Session, wie immer man das nennen mag und navigierst zum Projekt. Dann einfach mal "php sugar" eingeben und schauen was passiert Dort gibt's dann einen Befehl um eine neue Anwendung generieren zu lassen... das geht z.B. mit php sugar app create myapp, dann sollte die Website schonmal Hello World ausgeben. Falls die Anwendung noch nicht aktiv ist muss du sie ggf noch als default-app setzen,.. das geht auch über die console.

Die "App" ist dann im App Ordner und am Ende nix weiter als ein Frontcontroller wie man ihn sich auch sonst mit F3 in der index.php zusammenbauen würde.. also configs laden, routen definieren, addons initialisieren etc. sowas kann man da machen. Die Default-App wird standardmäßig ausgeführt - andere Apps können z.b. unter anderen Domains / Sub-Domains oder in Unterverzeichnissen (Routen) gestartet werden (nur so am Rande) .. also z.B. eine Backend-App unter /admin oder auch unter admin.mydomain.de

Components sind ein weiterer Grundbaustein. Out of the Box gibts derzeit nur 2 Komponenten, ein Basismodel (Cortex basierend) und "Template". Weitere Components kann man sich selbst über die config.ini in deinem app/myapp Ordner definieren, oder man installiert sie in ext/

Candyland ist die Komponentensammlung die ich gerade da habe. Die soll später mal über eine API entsprechend zu installieren/aktualiseren sein und dann halt auch nur die die man braucht, aber soweit bin ich nocht nicht. Du kannst dir aber einfach stumpf alles reinladen: geh in den Ordner ext/ und dort check candyland aus mit:

git clone https://github.com/ikkez/candyland.git sugar

dann wird es in den Ordner sugar gepackt.. dann zurück ins Hauptverzeichnis und folgendes starten:

php sugar registry scan --install

.. dann sollte er alles installieren. Falls dabei ein dependency Fehler passiert, einfach den Befehl nochmal ausführen bis alles cool ist.. das wird noch gefixt

ja und die Komponenten kann man dann benutzen in seinem Projekt. Es ist noch nicht alles an Ort und stelle und ein paar Dinge könnte man noch auslagern aber an sich funktioniert das wie folgt: Angefangen bei der Config. Es gibt ein paar App-spezifische Variablen, die kommen alle in [APP], so z.B.


[APP]
UI = ui/
LOCALES = language/

man könnte es auch in die [globals] packen wie immer, aber es gibt ein paar extras wenn man es für die App definiert.. gerade UI sollte schon dort sein.

Routen wie folgt:

[APP.ROUTES]
GET @home: / = Page.home
GET /setup = Controller\Setup->setup
GET @foo: /foo = Page.foo

Routes pro App definieren.. die Syntax ist die gleiche für Vanilla F3, allerdings kann man statt Controller->method nun auch Component.method schreiben.

Components sind vorkonfigurierte Klassen, können also auch einfach auf Controller\Page zeigen, aber bekommen noch ein paar Variablen gesetzt oder aber auch Dependency-Injection!

Die default-Template Komponente sieht so aus (vendor/ikkez/sugarcore/config.ini):


[COMPONENTS.Template]
class = Sugar\Component\Template\Template
dic.view = Sugar\View\TemplateInterface, Sugar\View\Template
config.set_app_ui = true
config.baseURL = false
config.template = templates/layout.html
config.use_hive = true
config.exclude_hive_vars = HEADERS,AUTOLOAD,BITMASK,BODY,...
ports = render,beforerender,afterrender

hier wird über dic.view eine Instanz von Sugar\View\Template in die $view Variable im __construct übergeben. Nice! Außerdem gibts noch ein paar Voreinstellungen, z.B. set_app_ui überträgt den in APP.UI Template Pfad beim rendern.

Components können auch modifizierte Kopien anderer Components sein. Wollen wir nun also Template benutzen, aber es noch auf unsere Bedürfnisse anpassen, erstellen wir eine Kopie / Instance davon.. also gehst du in deine config.ini und packst rein:


[COMPONENTS.TemplateExt]
instance = Template
config.template = templates/index.html
components.assets = TemplateAssets
components.uikit = uikit3
components.jquery = jquery
extend.assets.dic.tmpl = Sugar\View\Template, < view

wir benutzen nun in unserer Template Variante einen anderen Pfad zum Haupttemplate, laden außerdem noch die Komponenten uikit3, jquery und den Assetmanager (js/css compress+minify)... dieser selbst hat auch eine Dependency und braucht ein Template.. zum Glück haben wir selbst eins geladen, also linken wir die Variable rein mit extend.assets.dic.tmpl = Sugar\View\Template, < view Ob diese Syntax so bleibt weiß ich noch nicht so recht. Mittlerweile kann man auch Aliase erzeugen und dann wahrscheinlich einfacher die Dependencies handln, aber für jetzt ists so.

Nun noch die Page Komponente:


[COMPONENTS.Page]
class = Controller\Page
dic.tmpl = Sugar\View\TemplateInterface, $TemplateExt

Und die Klasse dazu anlegen: (app/myapp/controller/page.php)


<?php

namespace Controller;

use Sugar\Component;
use Sugar\View\TemplateInterface;

class Page extends Component {

   /** @var \Sugar\View\TemplateInterface */
   protected $tmpl;

   function __construct(TemplateInterface $tmpl) {
      $this->tmpl = $tmpl;
   }

   function home() {
      $this->tmpl->set('sub_template','templates/content/home.html');
   }

   function afterroute(\Base $f3,$params) {
      $this->tmpl->dump();
   }
}

So und dann sollte schon die Startseite gehen inkl. SASS Compiler, Uikit Frontend framework, jquery und alles fertig minified. Also gut die Templates musst du dir noch anlegen.. aber was einfaches reicht, wie z.b:


<!DOCTYPE html>
<html lang="de">
<head>
   <base href="{{ @baseURL }}" />
   <meta charset="UTF-8">
   <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
   <meta http-equiv="X-UA-Compatible" content="IE=edge">
   <title>my website</title>
   <link rel="stylesheet" href="scss/main.scss" priority="1" />
</head>
<body>

<header id="main-header">
   <div class="uk-container">
      <h1>my website</h1>
   </div>
</header>

<div class="main-content" id="main-content">
   <F3:include if="{{isset(@sub_template)}}" href="{{ @sub_template }}" />
</div>

<script src="js/main.js" priority="5" slot="end"></script>

</body>
</html>

Ich benutze viel UIkit in letzter Zeit.. man kann über das System auch noch die Variablen anpassen und sich seine eigene Version bauen, oder auch Bootstrap oder was anderes benutzen, kein Problem.

Sooo, ich hab für den Teil der Mail jetzt schon knapp 2 Stunden gebraucht :D ich muss das jetzt mal abkürzen hier, weil ich auch gerade eigentlich keine Zeit dafür hab ^^ Also für den Queue Dienst brauchst du noch nen CronJob:


[CRON]
log = true
web = TRUE
silent = false

[CRON.jobs]
queue = Controller\Cron->queue, @hourly

Diesen vorher initialisieren in Controller\App->load:

\Cron::instance();

Dann werden wir noch ne Datenbank brauchen, da jeder Job in einer Tabelle steht. Per Default gibt es eine core-db, weeeelches eine Jig DB ist.. also quasi in data/table.json Man kann also auch diese benutzen,.. das geht mit:


[COMPONENTS.Sugar\Processing\Queue\JobModel]
config.db = core

Möchtest stattdessen lieber eine SQL Datenbank.. muss du folgendes tun. In der Config:

DB definieren:

[APP.database.sql]
type = mysql
host = localhost
port = 3306
dbname = myapp
username = root
password = root

[COMPONENTS.Sugar\Model\Base]
config.db = sql

(man kann auch unterscheidliche DBs pro Model vergeben wenn man das mal braucht)

und in die Controller\App->load noch die DB laden:


// initialize database
$dbs = $this->fw->get('APP.database');
$this->fw->clear('APP.database');
foreach ($dbs as $name => $db)
   Storage::instance()->load($db,$name);

Und dann erstell dir mal eine Setup funktion wie schon oben in den Routes verlinkt (Controller\Setup->setup) :

    function setup() {
      \Sugar\Processing\Queue\JobModel::setup();
      echo "setup ok";
   }

Das geht leider noch nicht automatisch

Um jetzt einen Job zur Queue hinzuzufügen:

$que = \Sugar\Service\Registry::instance()->create('Queue');
$que->enqueue('Mailer.send_Spam_Mails',$args,'SPAM verschicken');

Mailer.send_Spam_Mails ist in dem Fall die Komponente Mailer und dessen Methode send_Spam_Mails() Man dann dort auch einen F3 callstring einsetzen also Controller\Foo->tueDiesUndDas Oder du implementierst das JobInterface und packst das in den 1. parameter. der 2. Parameter $args kann ein Array oder Object sein welches dann der Zielfunktion übergeben wird.

Wenn alles klappt siehst du den Eintrag in der DB und wenn du f3-cron im crontab eingerichtet hast, werden automatisch jede Stunde alle noch offenen Jobs ausgeführt.. oder per web via /cron/queue zum testen Ich hab für eine Art Notification über neue Suchergebnisse 2 Jobs.. der eine läuft z.B. einmal am Tag und findet neue Ergebnisse und erstellt dann den Job für den individuellen Newsletter, welcher dann in 500er Blöcken alle 15min verschickt wird. Funzt super soweit. Jede Component hat eine package.ini .. dort findest du auch noch einige Standardwerte die man für sich anpassen kann, für queue unter: ext/sugar/processing/queue/package.ini Man kann diese Werte auch direkt überschreiben in deiner config.ini, man muss nicht erst eine instance davon basteln.. und Vorsicht beim copy/pasten.. in der package.ini ist es [COMPONENT] aber in deiner config.ini muss es [COMPONENTS] sein.

sooo das wars jetzt aber erstmal. Bin gespannt ob du noch durchblickst.. ich weiß ist ganz schon viel und komplex geworden.. aber es wird später eine Backend-App geben, da soll man sich genau sowas einfach zusammenklicken können, was dann die config automatisch generiert.. und dann wirds richtig verrückt