Wallogit.com
2017 © Pedro Peláez
Core of my framework
Framework core build as composer module (https://getcomposer.org/)., (*1)
<?php
require_once('vendor/autoload.php');
require_once('config.php');
$project = new \MyProject\EntryPoint\Site();
$project->init();
\Core\Config::setDb('default', [
'host' => '192.168.0.1',
'name' => ‘dbname’,
'user' => 'user',
'password' => 123456,
'charset' => 'utf8'
]);
Config::registerProject('MyProject', 'default');
{
"require": {
"follower/core": "dev-master"
},
"autoload": {
"classmap": [
"vendor/follower/core/backend",
"app"
]
}
}
“app” - is your app folder. Recommended backend project structure:, (*2)
Api/, (*3)
Controller/, (*4)
Service/, (*5)
EntryPoint/, (*6)
Object/, (*7)
Routes/, (*8)
In “Api” and “Controller” folders there are controllers for different application entry points (i.e. api.php and index.php)., (*9)
Here are classes with methods like methodGet, methodList, which using Orm, OrmMapper, ActiveRecord, or Service for data processing., (*10)
class Entry extends Api
{
public function methodGet($args)
{
$entry = \MyProject\Object\Entry::find($args[‘id’]);
return $entry->getValues();
}
}
In “Service” folders there are service providers. You should write business logic there (not in models and controllers). Controllers are for output, models are for logic regarding only its attributes., (*11)
class UserProvider
{
public function getUsersWithPermissions($permissions)
{
return \MyProject\Object\User::all()
->addFilter(‘permissions.alias’’, $permissions)
->load();
}
}
Here you should setup access rules, controllers namespace setup, register routes, and other setting for concrete entry point, and run application., (*12)
class Site extends \Core\EntryPoint
{
public function init()
{
Config::set('site.language', 'ru');
Routes::register();
$this->setLib('\Accounting\Controller');
$app = new App($this);
$app->run();
}
}
Object classes are models. It contains description of data table fields, name, and relations to other entities. Here is config example., (*13)
self::$_config->setTable('User');
self::$_config->setFields([
'name' => [
'type' => 'varchar',
'default' => '',
'null' => false,
],
'password' => [
'type' => 'varchar',
'default' => '',
'null' => false,
]);
In “Routes” you can create routing class for each entry point and redefine default routing rules. Add custom route example:, (*14)
\Core\Router::register(['/add', 'post'], 'Index', 'new', []);
It means that POST query to /add url will go to controller: Index, method: methodNew()., (*15)
Default routing rules:, (*16)
/controller/ -- Controller, methodIndex()., (*17)
/controller/action -- Controller, methodAction()., (*18)
Object is a model, which represents some entity, (*19)
Main methods: $obj->setValue(‘property’, $value); // or setValues, for multiple values set $obj->getValue(‘property’); // or getValues, for getting all values, (*20)
Also in ActiveRecord-style: $obj->property = $value; $obj->save();, (*21)
Framework supports relations between models., (*22)
Represents wrapper class for objects array with methods and properties., (*23)
getData() - returns array of full objects, keys are object ids., (*24)
getHashMap(‘id’,’name’) - returns hash array, id => name, (*25)
getValues(‘id’) - returns simple array of ids, (*26)
Uses for complex filtering objects in collections. Example:, (*27)
$stream = $collection->stream();
$filter1 = function($obj) { /* complex filtering logic */ };
$stream = $stream->filter($filter1);
$filter2 = function($obj) { /* complex filtering logic */ }
$stream = $stream->filter($filter2);
//And then return filtered collection:
$stream->find();
You can still write raw mysql queries using PDO., (*28)
$db = \Core\Database\PDO::getInstance();
$result = $this->db->rows("SELECT * FROM `Entry` WHERE user_id = ?", array($user_id));
Also there is small class for trivial queries., (*29)
MySQL::insert($table, $params); MySQL::update($table, $params, $conditions); MySQL::delete($table, $conditions);
Examples:, (*30)
MySQL::update(‘User’, array(‘name’ => $new_name), array(‘id’ => 1)); MySQL::delete(‘User’, array(‘id’ => 1));
For step-by-step queries constructing with different conditions. Also used internally in \Core\Orm., (*31)
composeSelectQuery() method will return raw query string for executing., (*32)
$query = new QueryBuilder(‘User’);
$query->setBaseAlias('pc')
->select('id', 'title', 'name')
->join('left', User_Catalog, 'pc', ['catalog', 'another.id'])
->where('somevalue', [124, 125])
->where('max(count)', 20, '<')
->where('title', '%test', 'like')
->where('test', null);
->orderBy('id', 'asc')
->groupBy('param1')
->limit(20);
echo $query->composeSelectQuery();
Layer for working with Database, which encapsulate queries and supports relations., (*33)
Main methods:, (*34)
Orm::create($class_name); Orm::save($object); Orm::delete($object); Orm::find($class_name, $filterFields, $filterValues, $params); Orm::findOne($class_name, $filterFields, $filterValues, $params); Orm::load($class_name, $id); Orm::count($class_name, $filterFields, $filterValues);
Simple examples:, (*35)
$user = Orm::create(‘User’); $user->setValues(array(‘name’ => $name, ‘password’ => $password)); Orm::save($user); $users = Orm::find(‘User’, array(‘name’, ‘type’), array($name, $type))); $user = Orm::load(‘User’, 12); Orm::delete($user);
Another class, more flexible., (*36)
$mapper = OrmMapper::create(User); $mapper->setFields(['test', 'name', 'amount']); ->setFilter(['test', 'name', 'amount'], [1,2,3]); ->load(); $users = $mapper->getCollection();
Convenient way to work with objects. Some examples:, (*37)
$users = User::all() ->addFilter(‘type’, $id) ->load() ->getCollection(); $user = User::find($id); $user->name = ‘Peter’; $user->save();