2017 © Pedro Peláez
 

library spark-mvc

Web MVC Framework

image

tahona/spark-mvc

Web MVC Framework

  • Thursday, July 26, 2018
  • by primosz67
  • Repository
  • 1 Watchers
  • 1 Stars
  • 228 Installations
  • PHP
  • 1 Dependents
  • 0 Suggesters
  • 1 Forks
  • 0 Open issues
  • 60 Versions
  • 65 % Grown

The README.md

README

What is this repository for?

Very fast PHP framework with autoloading and annotations. All configuration is handled by annotations and beans., (*1)

How it works

Framework automatically load beans from app/src path it just need to be annotated with one annotation of: @Component, @Service, @Configuration or @Repository., (*2)

Bean injection can be achieved with @Inject annotation., (*3)

Initialization is done on the first request. The second request execute Controllers action, that has already injected beans in it., (*4)

Request execution time is very small because it's time of user code execution only., (*5)

Thanks to this, for real production code we got 20ms-40ms per request for dynamic data., (*6)

Quick Start

For quick start donwload example project: https://github.com/primosz67/spark-mvc-example, (*7)

Index php - explained

app/public/index.php, (*8)

error_reporting(E_ALL);

define("__ROOT__", __DIR__ . "/../../");
define("__VENDOR__", "../../vendor");

require __VENDOR__ . "/autoload.php";

Note: If you will use doctrine db framework add here line - "AnnotationRegistry::registerLoader('class_exists');", (*9)

Framework setup:, (*10)

$profileName ="someNameProfile";
$engine = new Engine("przemek_config", $profileName, __ROOT__ . "app");
$engine->run();

Configuration

app/src/MyAppConfig.php, (*11)

/**
 * @Configuration()
 * @EnableApcuBeanCache(resetParam="reset")
 */
class MyAppConfig {
}
  • resetParam - parameter for clearing cache. (GET http://app.com?reset). It's for development environment and should be deleted for production.

Controller

1. Standard Controller with annotation controller

app/src/MyAppController.php, (*12)

/**
* @Controller
*/
class MyAppController {

    /**
     * @Path("/index", method="GET")
     */
    public function indexAction(Request $request) {
        return new PlainViewModel("Hello World");
    }

   /**
     * @Path("/save", method="POST")
     */
    public function saveAction(SomeForm $form, Request $req, $beanName) {
        return new JsonViewModel(array(
            "user"=>"TODO"
        ));
    }
}

Go to localhost/get or localhost/index;, (*13)

  • Request is injected to method by Type
  • SomeForm is filled by "POST" form params using "spark-form" module.
  • $beanName - framework can inject any bean or service needed for action by name or type.
2. Rest Controller
/**
* @RestController
*/
class MyRestController {

    /**
     * @Path("/index")
     */
    public function indexAction(Request $request) {
        return new SomeResultDto();
    }
}

Note: All methods in RestController will resolve to JSON., (*14)

SomeResultDto - will resolve to json., (*15)

3. Old method of creating Controller

app/src/MyAppController.php, (*16)

class MyAppController extends Controller {


    /**
     * @Path("/index")
     */
    public function indexAction() {
        return new PlainViewModel("Hello World");
    }

    /**
     * @Path("/get")
     */
    public function getAction() {
        return new JsonViewModel(array(
            "user"=>"TODO"
        ));
    }

    /**
     * @Path("/newView")
     */
     public function showNewViewAction() {
        return new ViewModel(array(
            "user"=>"TODO"
        ));
     }

}

Go to localhost/get or localhost/index;, (*17)

2. Define bean for autoload.

Injection

1. Define bean for autoload.

/** * @Service() */ class UserService { //...some methods }

Note: for enabled apcu @EnableApcuBeanCache("reset") to autoload injection, call http://website?reset, (*18)

2. Define other beans and inject out bean.

/** * @Component() */ class AddUserHandler { /** * @Inject() * var UserService */ private $userService; /** * @PostConstruct() */ public function init() { $this->userService->doSomething(); } }
3.Inject in controller
class UserController extends Controller {

    /**
    * @Inject()
    * var UserService
    */
    private $userService;

    /**
     * @Path("/newView")
     */
     public function showNewViewAction() {
        return new ViewModel(array(
            "users"=>$this->userService->getAllUsers()
        ));
     }
}
4.Inject in action method of controller
/**
* @Controller
*/
class UserController {

    /**
     * @Path("/newView")
     */
     public function showNewViewAction(Request $request, UserService $userService ) {
        return new ViewModel(array(
            "users"=>$userService->getAllUsers()
        ));
     }
}

View

apc/view/{controller package}/{controllerName (without "Controller")}/{action}.tpl, (*19)

  1. For app/src/MyAppController@showNewViewAction we get: apc/view/myapp/showNewView.tpl
  2. For app/src/some/serious/package/controller/MyAppController@showNewViewAction we get: apc/view/some/serious/package/myapp/showNewView.tpl

Keywords action and controller are deleted by default., (*20)

Smarty built-in path plugins

Function path can be used in tpl file (example: index.tpl), (*21)

{path path="/user/register"}

Command will resolve to : www.example.com/user/register, (*22)

{path path="RegisterController@registerAction"}

Command will resolve to : www.example.com/user/register * com.example.RegisterController - optional Controller class Name * registerAction - method name in RegisterController, (*23)

{path path="@removeAction@id:4,type:blogpost"}

Command will resolve to : www.example.com/blogpost/remove/4 * {controller} - current request controller will be used * removeAction - method name in RegisterController * id:4,type:blogpost - params will resolve /{type}/remove/{id} to it's final form, (*24)

Apcu Bean Cache

if @EnableApcuBeanCache annotation is added with @Configuration the only way to reset beans and init them once more is by requestin localhost:80?reset (GET parameter "reset")., (*25)

Mailer

  • @EnableMailer -TODO
  • spark.mailer.enabled (true/false)- property

@Annotations

The heart of Spark Framework., (*26)

  • @Component,@Service,@Repository,@Configuration - do the same thing, but purpose is the key.
  • @Bean
  • @PostConstruct
  • @Inject
  • @Bean

Application Parameters

$this->config, (*27)

Base parameters: app.path - pierwsza ścieżka do katalogu /app src.path - ścieżka do katalogu /app/src app.paths - ścieżka albo ścieżki do katalogu /app w różnych kontekstach, (*28)

to fetch parameters:, (*29)

 $appPath = $this-config->getProperty("app.path");

update or set Params, (*30)

 $this-config->setProperty("customModule.some.property.", "/my/new/path");

Custom module loading

If you create common module to use in other project remember to create beans by @Bean annotation. It will be easier to add new module in one go., (*31)

In some your app configuration add others OtherModuleConfig., (*32)

/**
* @Bean
*/
public function otherBeanConfiguration () {
    return new OtherModuleConfig();
}

All @Bean annotation in OtherModuleConfig will be created and inject to your classes., (*33)

Multiple DataBase connection (example)

Handle multiple connections. To create Doctrine's EntityManager you can use simple EntityManagerFactory., (*34)


/** * @Inject() * @var EntityManagerFactory */ private $entityManagerFactory; /** * @Bean() */ public function entityManager() { return $this->entityManagerFactory->createEntityManager($this->getDataSource()); } /** * @Bean() */ public function superEntityManager() { return $this->entityManagerFactory->createEntityManager($this->getDataSourceSuper()); } public function getDataSource() { $dbConfig = new DataSource(); $dbConfig->setDbname("my-db"); $dbConfig->setHost("127.0.0.1"); $dbConfig->setUsername("root"); $dbConfig->setPassword("test"); $dbConfig->setPackages([ "com/myapp/user/domain" //path to doctrine entity ]); return $dbConfig; } public function getDataSourceSuper() { $dbConfig = new DataSource(); $dbConfig->setDbname("super"); $dbConfig->setHost("127.0.0.1"); $dbConfig->setUsername("root"); $dbConfig->setPassword("test"); return $dbConfig; }

Note: for using CrudDao with other enityManager than basic use @OverrideInject annotation, (*35)

/**
* @OverrideInject(oldName="entityManager", newName="houseManager")
*/
class MySuperDao extends CrudDao {
}

Internalization

Bean definition, (*36)


/** * @Bean */ public function anyPrefixNameMessageResource() { return new LangResourcePath(array( "pl"=>array( "/house/house_pl.properties" ), "cz"=> array(...), "en"=>array(...), )); }

Where "pl","cz","en" are cookie value with key "lang";, (*37)

  • Property file /house/house_pl.properties
core.thank.you.message=Thank You {0} and {1}
  • Use in php
    /**
     * @Inject
     * @var langMessageResource
     */
    private $langMessageResource;


    ...

    $this->langMessageResource->get("core.thank.you.message", array("John", "Trevor"));

  • Use in smarty
{lang code="core.thank.you.message" value=["John", "Trevor"]}

Results: Thank You John and Trevor, (*38)

@Path

Annotation Defonition, (*39)

@Path(path="/login/{test}", method="get")

Fetch path paramether in Controller class;, (*40)

$this->getParam("test");

MULTI fetch by component

Example is for dynamic menu module that will popup when new project or classes are added., (*41)


/** * @Inject */ private $beanProvider; public function getMenuModules() { return $beanProvider->getByType(MenuModule::class); }

Interceptors

/**
* @Component
*/
class UserInterceptor implements HandlerInterceptor {

    /**
    * @Inject
    */
    private $someUserHolder;

    public function preHandle(Request $request) {
        //Do something like redirect or add values to request or auto-conversion(id to entity);
    }

    public function postHandle(Request $request, ViewModel $viewModel) {
        $viewModel->add("loggedUser", $someUserHolder->getUserFromSession())
    }
}

Command behaviour for PHP cli

First, create class Command implementation, (*42)

/**
 * @Component()
 */
class ExampleCommand implements Command {

    /**
     * @Inject()
     * @var SomeBean
     */
    private $someBean;

    public function getName() :string{
        return "example:exampleCommandCommand";
    }

    public function execute(InputInterface $in, OutputInterface $out) : void {
        $out->writeln("executing " . $this->getName());

        //Example ....
        $this->someBean->doSomething()
        $out->writeObject($this->someBean->getSomething());


        $out->writeln("finish!");
    }
}

in console execute:, (*43)

php app/public/index.php command=example:exampleCommand profile=production

Output:, (*44)

executing example:exampleCommand

object(...)

finish!

Built-in cache service

Great thing for caching DB request or loading files data. Annotation can be used with different cache. Even custom cache bean that implement spark/cache/Cache, (*45)

How To

In Bean class add @Cache annotation., (*46)

/**
 * @Cache(name="cache", key="user {0}.id", time=10)
 */
public function getLeaderByCompany($company){
    return $this->someDao->getByCompanyId($company->getId())
}

  • "name" is a name of bean that implement spark\cache\Cache interface.
  • ApcCache needed for application is added as default name="cache"
  • "time" - optional parameter that is in minutes(10 minutes)
  • "key" parameter is for distinguish cached values

Profiles

$profileName = "production";
$engine = new Engine("przemek_config",$profileName,  __ROOT__ . "app");
@Configuration
@Profile(name="production")
class SomeProductionConfig(){
..
}

@Configuration
@Profile(name="development")
class SomeDevelopmentConfig(){
..
}

In this case SomeDevelopmentConfig won't be added to container and bean declared in it (@Bean) as well., (*47)

Error handling - example

class NotFoundErrorHandler extends ExceptionResolver {

    public function doResolveException($ex) {
        if ($ex instanceof RouteNotFoundException || $ex instanceof EntityNotFoundException) {
            ResponseHelper::setCode(HttpCode::$NOT_FOUND);

            $viewModel = new ViewModel();
            $viewModel->setViewName("/house/web/error/notFound");
            return $viewModel;
        }
        return null;
    }

    public function getOrder() {
        return 400;
    }
}

where error handler with order equal 0 , will be first to invoke. If you return Viewmodel the handling will stop and the view will be return as response., (*48)

Event Bus

/**
* @Inject
*/
private $eventBus;
...
$this->eventBus->post(new SomeEvent());

Event definition :, (*49)

class SomeEvent implements Event {...}

Subscription, (*50)


@Component class SomeListener { /** * @Subscribe */ public function handleSomeCase(SomeEvent $event) { //...logic } }

AnnotationHandler

Add Your own annotation, (*51)

class NewAnnotationHandler extends AnnotationHandler{
    ...
}

Installation - Composer - Speed up

composer dump-autoload -a

Performance - Some numbers

Tested Case: Real project with small database. AB(Apache benchmark) requests 10000 and 1000 parallel connections., (*52)

  • Smarty compile: Smarty template rendering for each request (Development mode).
  • Smarty: smarty with production setup.
  • Smarty + @Cache (Redis): request to database are cached with @Cache annotation (we use Redis for caching). It can give big improvement to performance when there is more calls to DB.
Mode Request time (per request)
Smarty compile ~130ms
Smarty ~45ms
Smarty + @Cache (Redis) ~25ms

Installation - Composer

{
    "autoload": {
        "psr-4": {"": "app/src/"}
    },

    "require": {
        "smarty/smarty": "3.1.27",
        "tahona/spark-mvc": "*"
    }
}

The Versions

26/07 2018

dev-master

9999999-dev https://github.com/primosz67/spark-spark

Web MVC Framework

  Sources   Download

MIT

The Requires

 

mvc

26/07 2018
21/07 2018
20/07 2018
29/06 2018
12/06 2018
10/06 2018
08/06 2018
04/06 2018
04/06 2018
27/05 2018
25/05 2018
23/05 2018
23/05 2018
22/05 2018
20/05 2018
06/05 2018
06/05 2018
06/05 2018
05/05 2018
05/05 2018
03/05 2018
29/04 2018
16/04 2018
17/12 2017
12/11 2017
08/11 2017
02/11 2017
21/10 2017
21/10 2017

3.0.7

3.0.7.0 https://github.com/primosz67/spark-spark

Web MVC Framework

  Sources   Download

MIT

The Requires

 

mvc

06/10 2017

3.0.6

3.0.6.0 https://github.com/primosz67/spark-spark

Web MVC Framework

  Sources   Download

MIT

The Requires

 

mvc

27/09 2017

3.0.5

3.0.5.0 https://github.com/primosz67/spark-spark

Web MVC Framework

  Sources   Download

MIT

The Requires

 

mvc

12/09 2017

3.0.4

3.0.4.0 https://github.com/primosz67/spark-spark

Web MVC Framework

  Sources   Download

MIT

The Requires

 

mvc

12/09 2017

3.0.3

3.0.3.0 https://github.com/primosz67/spark-spark

Web MVC Framework

  Sources   Download

MIT

The Requires

 

mvc

12/09 2017

3.0.2

3.0.2.0 https://github.com/primosz67/spark-spark

Web MVC Framework

  Sources   Download

MIT

The Requires

 

mvc

11/09 2017

dev-package-change

dev-package-change https://github.com/primosz67/spark-spark

Web MVC Framework

  Sources   Download

MIT

The Requires

 

mvc

11/09 2017

3.0.0

3.0.0.0 https://github.com/primosz67/spark-spark

Web MVC Framework

  Sources   Download

MIT

The Requires

 

mvc

11/09 2017

3.0.1

3.0.1.0 https://github.com/primosz67/spark-spark

Web MVC Framework

  Sources   Download

MIT

The Requires

 

mvc

09/09 2017

2.0.21

2.0.21.0 https://github.com/primosz67/spark-spark

Web MVC Framework

  Sources   Download

MIT

The Requires

 

mvc

09/09 2017

2.0.20

2.0.20.0 https://github.com/primosz67/spark-spark

Web MVC Framework

  Sources   Download

MIT

The Requires

 

mvc

23/08 2017

2.0.19

2.0.19.0 https://github.com/primosz67/spark-spark

Web MVC Framework

  Sources   Download

MIT

The Requires

 

mvc

22/08 2017

2.0.18

2.0.18.0 https://github.com/primosz67/spark-spark

Web MVC Framework

  Sources   Download

MIT

The Requires

 

mvc

09/08 2017

2.0.17

2.0.17.0 https://github.com/primosz67/spark-spark

Web MVC Framework

  Sources   Download

MIT

The Requires

 

mvc

15/07 2017

2.0.16

2.0.16.0 https://github.com/primosz67/spark-spark

Web MVC Framework

  Sources   Download

MIT

The Requires

 

mvc

14/07 2017

2.0.14

2.0.14.0 https://github.com/primosz67/spark-spark

Web MVC Framework

  Sources   Download

MIT

The Requires

  • php >=5.3

 

mvc

14/07 2017

2.0.15

2.0.15.0 https://github.com/primosz67/spark-spark

Web MVC Framework

  Sources   Download

MIT

The Requires

  • php >=5.3

 

mvc

24/06 2017

2.0.13

2.0.13.0 https://github.com/primosz67/spark-spark

Web MVC Framework

  Sources   Download

MIT

The Requires

  • php >=5.3

 

mvc

18/05 2017

2.0.12

2.0.12.0 https://github.com/primosz67/spark-spark

Web MVC Framework

  Sources   Download

MIT

The Requires

  • php >=5.3

 

mvc

07/05 2017

2.0.11

2.0.11.0 https://github.com/primosz67/spark-spark

Web MVC Framework

  Sources   Download

MIT

The Requires

  • php >=5.3

 

mvc

22/04 2017

2.0.10

2.0.10.0 https://github.com/primosz67/spark-spark

Web MVC Framework

  Sources   Download

MIT

The Requires

  • php >=5.3

 

mvc

21/02 2017

2.0.9

2.0.9.0 https://github.com/primosz67/spark-spark

Web MVC Framework

  Sources   Download

MIT

The Requires

  • php >=5.3

 

mvc

05/02 2017

2.0.8

2.0.8.0 https://github.com/primosz67/spark-spark

Web MVC Framework

  Sources   Download

MIT

The Requires

  • php >=5.3

 

mvc

04/02 2017

2.0.7

2.0.7.0 https://github.com/primosz67/spark-spark

Web MVC Framework

  Sources   Download

MIT

The Requires

  • php >=5.3

 

mvc

04/02 2017

2.0.6

2.0.6.0 https://github.com/primosz67/spark-spark

Web MVC Framework

  Sources   Download

MIT

The Requires

  • php >=5.3

 

mvc

04/02 2017

2.0.5

2.0.5.0 https://github.com/primosz67/spark-spark

Web MVC Framework

  Sources   Download

MIT

The Requires

  • php >=5.3

 

mvc

01/02 2017

2.0.4

2.0.4.0 https://github.com/primosz67/spark-spark

Web MVC Framework

  Sources   Download

MIT

The Requires

  • php >=5.3

 

mvc

01/02 2017

2.0.3

2.0.3.0 https://github.com/primosz67/spark-spark

Web MVC Framework

  Sources   Download

MIT

The Requires

  • php >=5.3

 

mvc

29/01 2017

2.0.2

2.0.2.0 https://github.com/primosz67/spark-spark

Web MVC Framework

  Sources   Download

MIT

The Requires

  • php >=5.3

 

mvc

29/01 2017

2.0.0

2.0.0.0

Web MVC Framework

  Sources   Download

The Requires

  • php >=5.2

 

29/01 2017

2.0.1

2.0.1.0

Web MVC Framework

  Sources   Download

The Requires

  • php >=5.2