The Spiral framework provides open and modular Rapid Application Development (RAD) environment, database tools, code re-usability, extremely friendly IoC, IDE integration, PSR-7, simple syntax and customizable scaffolding mechanisms.
Skeleton App | Guide | Twitter | Modules | CHANGELOG | Contributing | Forum
class HomeController extends Controller
{
/**
* IoC Container can automatically deside what database/cache/storage
* instance to provide for every action parameter based on it's
* name or type.
*
* @param Database $database
* @param Database $logs Can be physical or virtual database
* @param HttpConfig $config
* @return string
*/
public function indexAction(Database $database, Database $logs, HttpConfig $config): string
{
dump($config->basePath());
$logs->table('log')->insertOne(['message' => 'Yo!']);
return $this->views->render('welcome', [
'users' => $database->table('users')->select()->where(['name' => 'John'])->all()
]);
}
}
Bootloaders, Factory Methods:
class MyBootloader extends Bootloader
{
const BINDINGS = [
ParserInterface::class => DefaultParser::class,
'someService' => SomeService::class
];
const SINGLETONS = [
ReaderInterface::class => [self::class, 'makeReader'],
];
protected function makeReader(ParserInterface $parser, Database $database): Reader
{
return new Reader($parser, $database->table('some'));
}
}
Declarative/lazy singletons and services:
class SomeService implements SingletonInterface
{
private $reader;
public function __construct(ReaderInterface $reader)
{
$this->reader = $reader;
}
public function readValue(string $value): string
{
return $this->reader->read($value);
}
}
JSON responses, method injections, IoC scopes, container shortcuts, IDE helpers:
public function indexAction(ServerRequestInterface $request, SomeService $service): array
{
dump($service->readValue('abc'));
//Shortcuts
dump($this->someService === $service);
return [
'status' => 200,
'uri' => (string)$request->getUri()
];
}
Spiral application(s) can be used as middleware/endpoint inside other PSR7 frameworks:
use Zend\Diactoros\Server;
use Zend\Expressive\Application;
use Zend\Stratigility\MiddlewarePipe;
$app = new Application();
$app->any('/spiral', SpiralApp::init(...)->http);
ORM with scaffolding/migrations for MySQL, PostgresSQL, SQLite, SQLServer:
class Post extends RecordEntity
{
use TimestampsTrait;
//Database partitions, isolation and aliasing
const DATABASE = 'blog';
const SCHEMA = [
'id' => 'bigPrimary',
'title' => 'string(64)',
'status' => 'enum(published,draft)',
'body' => 'text',
//Simple relation definitions
'comments' => [self::HAS_MANY => Comment::class],
//Not very simple relation definitions
'collaborators' => [
self::MANY_TO_MANY => User::class,
self::PIVOT_TABLE => 'post_collaborators_map',
self::PIVOT_COLUMNS => [
'time_assigned' => 'datetime',
'type' => 'string, nullable',
],
User::INVERSE => 'collaborated_posts'
],
//Pre-compiled relations
'author' => [
self::BELONGS_TO => AuthorInterface::class,
self::LATE_BINDING => true
],
//Hybrid databases
'metadata' => [
Document::ONE => Mongo\Metadata::class
]
];
}
$posts = $postSource->find()->distinct()
->with('comments', ['where' => ['{@}.approved' => true]]) //Automatic joins
->with('author')->where('author_name', 'LIKE', $authorName) //Fluent
->load('comments.author') //Cascade eager-loading (joins or external query)
->paginate(10) //Quick pagination using active request
->getIterator();
foreach($posts as $post) {
echo $post->author->getName();
}
$post = new Post();
$post->publish_at = 'tomorrow 8am';
$post->author = new User(['name' => 'Antony']);
$post->tags->link(new Tag(['name' => 'tag A']));
$post->tags->link($tags->findOne(['name' => 'tag B']));
$transaction = new Transaction();
$transaction->store($post);
$transaction->run();
dump($post); //You can also use AR or UoW approach
And much more: Skeleton App | Guide
composer install
vendor/bin/phpunit