Giter Club home page Giter Club logo

framework's Introduction

PPI Framework

Gitter Latest Stable Version Latest Unstable Version Travis-CI Build Status Scrutinizer Code Quality License

PPI is the PHP Interoperability Framework. It provides an equal and open platform to empower PHP developers to pick the best tools from the best PHP frameworks

PPI bootstraps framework components for you from the top frameworks such as ZendFramework2, Symfony2, Laravel4 and FuelPHP.

Requirements

  • PHP 5.4.0 or above

Installation

There is no actual "installation" of PPI, you can download it from http://www.ppi.io/downloads and drop it in your document root.

Contributing

PPI is an open source, community-driven project. If you'd like to contribute, check out our issues list. You can find us on IRC, Google Plus or Twitter (@ppi_framework).

If you're submitting a pull request, please do so on your own branch on GitHub.

Start by forking the PPI Framework repository and cloning your fork locally:

$ git clone [email protected]:YOUR_USERNAME/framework.git
$ git remote add upstream git://github.com/ppi/framework.git
$ git checkout -b feature/BRANCH_NAME master

Apply PPI Coding Standards using the PHP-CS-Fixer tool (uses PPI custom fixers):

$ ./vendor/bin/php-cs-fixer fix -v

After your work is finished rebase the feature branch and push it:

$ git checkout master
$ git fetch upstream
$ git merge upstream/master
$ git checkout feature/BRANCH_NAME
$ git rebase master
$ git push --force origin feature/BRANCH_NAME

Go to GitHub again and make a pull request on the ppi/framework repository. Thank you for making PPI better!

framework's People

Contributors

alfrekjv avatar avdg avatar dragoonis avatar elazar avatar evandotpro avatar frankdejonge avatar gitter-badger avatar ralphschindler avatar syntaqx avatar taylorotwell avatar vitorbrandao avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

framework's Issues

add getEnv() or getEnvironment() methods to Action layer

$this->getEnvironment() should return 'development' or 'production' or a custom one, which you set via your bootstrap into PPI\App.

PPI\App is a make-shift DIC and should be turned into a proper DIC after functions like this get added

ForumModule

We need ForumModule, going to test the waters with this on our website repo first, we need basic question/answer functionality, with up/down voting of answers just like StackOverflow.

Restructure the skeletonapp and framework/composer include structure

  1. Change the PPI framework composer psr-0 include path to not look inside ./PPI/ and instead just jump to ./
    Meaning the PPI framework will no longer have a ./PPI/ folder but will be changed to /src/

Thus the PPI library path from the skeletonapp path will change from:
./PPI/vendor/ppi/ppi/PPI/Autoload.php
to:
./vendor/ppi/framework/src/Autoload.php

  1. The skeletonapp composer.json file require 'ppi/framework/' instead of 'ppi/ppi'.
  2. The skeletonapp composer.json file will be moved from ./PPI/composer.json to just ./composer.json.
  3. The skeletonapp init.php file will be moved from ./PPI/init.php to ./app/init.php

PPI SmartyEngine Plugin

@noisebleed is interested in making a PPI Module for registering the SmartyEngine

I have currently developed the code necessary for SmartyEngine. Futher development on this is required such as Extensions, Filters and Plugins for Smarty3 and I believe this is where @noisebleed comes in.

Modules can create 'services' which are globally shared using the ServiceLocator.

The default templating service is here: https://github.com/ppi/framework/blob/2.0/PPI/App.php#L198

The modules can create their own service in their /modules/<module>/Module.php class on the initServices method.
An example of this is here: https://github.com/ppi/skeletonapp/blob/2.0/modules/User/Module.php#L38

Now any controller can perform $this->getService('mailerClass') if they wanted to.

The SmartyEngine Module in question should register a 'templating' service key in its initServices method, holding an instance of PPI\Templating\Smarty\SmartyEngine.php

An example of setting up SmartyEngine is here: https://github.com/ppi/framework/blob/2.0/PPI/App.php#L276
The code is also below for easy reference, the class names are 'use' statements at the top of PPI\App:

<?php
defined('SMARTY_DIR') || define('SMARTY_DIR', PPI_VENDOR_PATH . 'Smarty/');
$smartyDriver = new \PPI\Templating\Smarty\Smarty();
$engine = new SmartyEngine(
    $smartyDriver,
    new TemplateNameParser(),
    new FileSystemLoader($templateLocator)
);

Making PPI Module Routing Multi-Vendor

One of the key points about PPI is to alleviate vendor-lockin. This means your PPI module can be using ZF2 routing, SF2 routing or li3 routing (to name a few).

As demonstrated in this example, $module->getRoutes() will always return a symfony2 RouteCollection:
https://github.com/ppi/skeletonapp/blob/master/modules/Application/Module.php#L18

This is great as an initially working implementation, but the idea is to let the developer on a per-module basis choose which routing he/she wants.

I'm keen to hear people's ideas/patterns on making an extensible matching system that will do, "oh this module is using symfony, lets ask symfony to match it", which is what it currently does. It must detect a Zend2 route collection and ask ZF2 to match it.. and so on.

Form Dropdown Changes

The key => val order on PPI\Form\Tag\Select is backwards.

The value of the array is the value of the tag, which is logically correct, but the direction is wrong. Meaning the following is the current state of it:

<?php
echo $form->select('settings', array(
    'key1' => '1',
    'key2' => '2'
));
<select name="settings">
    <option value="1">key1</option>
    <option value="2">key2</option>
</select>

Notice how they're backwards? A BC change has to happen ASAP to invert them before more adoption of this component occurs.

View Asset Helpers for TwigEngine

  • Make sure the 'asset' helper is loaded, so users can load asset files (images/css/js)
  • Make sure the 'generator' view helper is loaded so users can reverse engineer routes.

New View Layer

Currently in PPI there is a PPI\View component.

  1. It supports specifying a 'layout file'.
  2. Then you have an 'action file' which is specified by your controller's action.
  3. You can pass parameters into your template process from the controller.
  4. You can pass options to the rendering process to tell it wether this is a 'parital' load, to just load the action file, or load the entire template as normal.
  5. It has multiple "Template Adapters" which consist of PHP, Smarty, Twig.

I would much prefer to re-use an existing libraries implementation of the above, have something to connect my controller to.

I looked at ZF2's View implementation, it looked a bit crazy and over-complicated, but maybe theres parts we can cherry pick ?
What about symfony?

"Debug" mode hides info, yet production gets everything

See: https://github.com/ppi/framework/blob/master/PPI/App.php#L160
This handler intercepts any php error output (whatever the E_ level is set to), and displays it in a custom handler. While the addition of a stacktrace is nice for errors, it is often unneeded and other valuable information is absorbed as well as functionality broken. A developer is no longer able to use, for example, $http_response_headers after a failed file_get_contents(), because the warning from file_get_contents is raised to an exception, and then thrown from within the ErrorHandler context (so, even a try/catch around the file_get_contents won't work). This also modifies the PHP errorlog output:

Error (E_WARNING) caught by PPI:
[Wed Oct 24 13:24:20 2012] in -STRIP-/vendor/ppi/framework/PPI/Exception/Handler.php on line 84
Error (E_FATAL) NOT caught by PPI:
[24-Oct-2012 15:10:43 UTC] PHP Fatal error: Maximum execution time of 30 seconds exceeded in -STRIP-/modules/OffersModule/Classes/Offer.php on line 285

I think it works the wrong way around. Dev mode should give more info, not less. Intercepting errors/exceptions in production makes sense (don't present a stacktrace to a clueless user), in dev it should only give more info, like turning on display_errors, showing all errors including E_NOTICE, etc etc etc imho

Add a PHPUnit test suite

Add tests to the PPI library so each contributor can run them before sending PRs to assure everything still works.

Run the PSR1 sniffer

Run the PSR1 sniffer on PPI project and produce a list of all offending lines of code.

PPI\Form\Rule

Discussion ported from: https://github.com/dragoonis/ppi-framework/issues/44

  1. Update PPI\Form\Tag->setRule() API
    1.1) Update referenced code to this change.
    1.1.1) Update PPI\Crud code to reflect the new API

  2. Update unit tests to reflect new API
    2.1) Test all variations of setRule() with all possible rules implemented.

New Config System

Looking to re-use an existing component library if its simple and fast enough then we can cherry-pick from it.

Usually PPI doesn't need all the fancy features from configuration that zf/symfony ship with.
In the past this has lead PPI to create a similar but very trimmed down and faster version.

This is no longer a project goal for PPI to make its own components completely so re-using existing code is important.

The wiki for this part of the system is here: https://github.com/ppi/framework/wiki/PPI-v2-Configuration

** Please read the wiki document before commenting on this discussion

PPI\Module\Module should be called PPI\Module\Base?

It's a very minor point, but I noticed in the docs that the example code does:

use PPI\Module\Module as BaseModule

Maybe it'd make sense to call the class PPI\Module\Base or PPI\Module\BaseModule instead?

When a 404 occurs, throw an exception

Need to wait for ticket #29 to be finished before starting this.

Once the router can't match any routes, throw an exception.

This exception should turn into a dispatchable process so that application modules can render an acceptable HTML/CSS page for when errors occur.

A user-land hook for this should also be useful to control the exception process, adding in extra loggers..etc

Note: the PPI\Exception class does follow the Observer design pattern and allows custom events to be added into it, for custom logging calls.

PPIv2 Twig Integration

Now that native PHP support is enabled via phpEngine, then we'll need to have Twig in here too.

Perhaps have to look at TwigBundle and see if it does any custom stuff, I would imagine it does TemplateNameParser and the likes to get the names converting and params over to Twig, just like I've done for phpEngine in the PPI\Module\Templating component.

Composer Integration With Vendor Libraries

We need to be able to manage our vendor libraries in different versions, so that Composer can tie things up nicely.

@elazar would you like to recap on what you discussed with me earlier? just detailing the high level steps required so we can get a discussion going, with say @Seldaek ?

  • Paul.

Re-Integrate PPI\Form

  • Take PPI\Form from v1 move it to v2.
  • Enhance the Rules on each form tag.
  • Think about TagCollection, which is something you can append tags into. Perhaps PPI\Form itself can be a TagCollection
  • TagCollection->add('element_name', $tag)
  • TagCollection->has('element_name')
  • TagCollection->remove('element_name');

Implement DelegateEngine to allow multiple templating engines to be used

We should still let people disable this new feature and go direct to their chosen engine, such as PhpEngine, this will let you fine tune PPI to be more optimized.

$app->templatingEngine = 'php'; would perhaps be the override, and by default 'templatingEngine' will be set to 'delegate'.

I'll leave this up to developer creativity to come up with a 'delegate' and 'direct' option.

PPIv2 Sessions

Need to register the session class, and put it into the Request class for convenience and so it's clear where to fetch it from.

<?php

$session = new \Symfony\Component\HttpFoundation\Session(
    new \Symfony\Component\HttpFoundation\Session\Storage\NativeFileSessionStorage()
);

$request = new Request();
$request->setSession($session);

Set up PPI\MicroApp

This will allow closures against routes.

You will still be able to talk to all standard components, use all functionality you'd expect from a controller, but no more routing since you specify it in your microapp call.

Think of how to still access the service locator here, perhaps $app is still available and you can do $app->getService('UserStorage').

PPI\Session Abstraction

It would be useful to introduce session abstraction to allow us to work with custom session save handlers in addition to the built-in file based session storage provided. Implementing session handlers for database and Memcached add more flexibility and the possibility of building distributed systems.

I propose PPI\Session acts as an abstraction layer, passing calls to, for instance, PPI\Session\Disk or PPI\Session\Memcached.

Thoughts?

PPI Logger

We need a logging class. Does it deserve to be its own component ?

My initial use case for this internally is to throw a deprecated notice for functionality that we want to phase out gradually.

More thoughts required here

@benthedesigner you built the exception component.. any thoughts here?

View Asset Helpers for PhpEngine

  • Make sure the 'asset' helper is loaded, so users can load asset files (images/css/js)
  • Make sure the 'generator' view helper is loaded so users can reverse engineer routes.

Modularity

Big topic, going to be calling them 'Extensions' instead of Plugins/Modules..etc

Trying to keep consistency with PHP project, since our names are similar.

PHP Extension
PPI Extension <-- consistency

PPI's approach is to embrace, not replace so who's got the most effective but fast plugin system.

How is SF2's ? (sfEvent)

How is ZF2's ? (also, stability?)

Who else has a good one?

@Seldaek are you good to elaborate on symfony here?
@Bittarman, @juozas being zf guys, are you yet aquiainted with v2?

Refactor PPI\Console\ModuleCommand

We need to remove all hard coded paths in this framework code as it's decoupled from the skeletonapp.

I believe we need some way of asking for 'options' for each Command, like this:

Current: $application->add(new ModuleCommand());
Proposed: $application->add(new ModuleCommand($appOptions));

Now we can have options such as where the skeleton_module lives.

By default this will be ./utils/skeleton_module, but can be overriden from the app.config.php file.

New Exception Handler

Re-introduce the exception handler from PPI1, using the observer design pattern to register custom exception handlers, consider using the ZF event manager since it's being used for the PPI\Module anyway and autoloading has already occured.

Create a system requirements script for skeletonapp

App and user-level configuration - v2.0

Current status

User config comes from app.config.php

Currently we load configuration from app/app.config.php:

<?php
$config = array(
    'environment'            => 'development',
    'templating.engines'     => array('php', 'smarty', 'twig'),
    'templating.globals'     => array(
        'ga_tracking' => 'UA-XXXXX-X'),
    'datasource.connections' => include (__DIR__ . '/datasource.config.php')
);

// Are we in debug mode ?
if ($config['environment'] !== 'development') {
    $config['debug']     = $config['environment'] === 'development';
    $config['cache_dir'] = __DIR__ . '/cache';
}
return $config; // Very important

Setting App properties is how we do this

we let the user set App properties using magic setters after the PPI\App instance is created:

$app = new PPI\App();
$app->moduleConfig = include 'app/modules.config.php';
$app->config = include 'app/app.config.php';

// Do you want twig engine enabled?
//$app->templatingEngine = 'twig';

// If you are using the DataSource component, enable this
$app->useDataSource = true;

Everything is stored in AppOptions (aka ParameterBag)

app and module configuration is store in App::$options['config'] and App::$options['moduleConfig'] respectively being $options an instance of PPI\ServiceManager\Options\AppOptions which is based on Symfony ParameterBag.

Some ParameterBag characteristics:

  • Allows the usage of placeholders (example: %app.cache_dir%) which are later resolved.
  • All keys are lowercased ('moduleConfig' becomes 'moduleconfig').
  • It is not designed to store n-levels of config keys. One-level only.

App internal configuration is also stored in AppOptions

This means parameters that identify which class to use for a given component is stored alongside user configuration.

    'app.session.class'                  => 'Symfony\Component\HttpFoundation\Session\Session',
    'app.session.storage.class'      => 'Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage',

Where to go now?

  • Should we store everything in the same AppOptions instance?
  • Should we allow users to set a App property like we do now or centralize all user configuration?
  • Can we work with a single-level (array deepness) implementation like ParameterBag. This class resolves placeholders automatically but only for root-level keys.

Routes dont work when browser 'auto insert' an end slash /

I'm new to PPI2 and I'm trying to implement the issue #31 as an exercise
ppi/website#31

I've declare a route, like this:

Ideas:
    pattern:  /ideas
    defaults: { _controller: "Application:Ideas:index"}

On the web browser, when I try the URL localhost/ideas everything works as expected
BUT, if I add an end slash to the URL, localhost/ideas/ , I get an 404 error.

In addition, a warning is raized by PHP

Warning: strpos(): Empty delimiter in C:\try\skeletonapp\vendor\ppi\framework\PPI\App.php on line 421

For the sake of report:
Win Server 2008 R2
IIS 7
PHP 5.4.4
Localhost URL is set to skeletonapp/public
IIS Rewrite is on, and working fine :)

Proposal PPI\Array\Rename (draft name)

The PPI\Request* are array objects which contains their data.
Using these objects should be pretty simple.

<?php
$session = new PPI\Request\Session;

if ($session['foo'] === null) {
    $session['foo'] = 'bar';
}

echo $session['foo'];
?>

This works fine, as long you only have to deal with 1 application.
If you have to deal with multiple applications, you do not want to have conflicts.
To avoid such an issue, you could use namespaces, just as php has them.

A way to solve this issue, is to add a layer on top of it which acts as a translator.
Note: the idea is to make the translator a separate generic object which works on every normal array

    +----------------------------------------------------------------------+
    | +--------+                            +------------+                 |
    | | object | <------------------------- | translator | <- $obj['foo']; |
    | +--------+                            +------------+                 |
    |             $obj['namespace']['foo']                                 |
    |                                                                      |
    |  ^- Actual object     Translation object-^    Actual array call-^    |
    +----------------------------------------------------------------------+

The idea of the interface would be like this:

<?php

namespace PPI\Array\Translator;

class abstract extends /*array stuff over here*/ {
    /**
     * Constructor
     *

* @param string $object Object to be redirected

     * @param mixed $var Variables which might be used in the translator
     */
    public function __construct($object) {
        /* implementation */
    }

    /*array stuff*/

    /**

* Translates names

     * Returns variable reference
     *
     * @param string $key Key to be translated
     *

* @return string

     * @return mixed Variable reference
     */
    abstract translator($key)
}

Advantages

  • No need to modify array or object, all translations/renaming are done in 1 layer
  • Separate component and easy to use on every array (object)
  • Easy to maintain

Disadvantages

  • Slower than direct access
  • Total concept might be harder to learn as the number of components expands (we might need good documentation for this)

UPDATE

Return type method translator

I think its better to let the abstract method translator (which is used to get the translated reference, which the user should implement) return a reference instead of a string which has to be parsed by the abstraction layer itself. In case the string use case may be useful, someone could implement a layer on top of it.

TODO:
- subarray notation: would probably be a "/"

  • investigate possible array behavior issues
  • rewording?
  • Opinions

View Helpers

I guess this could be more of a 'Skeleton App' discussion since it's not really functionality native to the framework, but just some glue between them.

The Goal

To load view helper classes easily as part of your rendering process in your controller.

Current Implementation

Really you just load a class and pass it on.. which is kinda manual labour.

<?php
$form = new \PPI\Form();
$this->render('user/login', compact('form'));

Ideal Implementation

Maybe somewhere on your controller, such as preDispatch() you can register all view helpers that your controller uses by default. This could cut down code re-use but it's still manually maintained so theres no "load all helpers in this $dir" approach which would result in unnecessary helper loads.

<?php
namespace App\Controller;
class User {

    function preDispatch() {
         $this->addViewHelper('formHelper', new \PPI\Form());
    }

    function index() {
           $this->render('user/index');
    }

    function login() {
           $this->render('user/login');
    }

}

And then in your view you can just access it like:

<div><?= $formHelper->text('username'); ?></div>

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.