PHPackages                             rasshofer/papprika - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. rasshofer/papprika

Abandoned → [silex/silex](/?search=silex%2Fsilex)ArchivedLibrary[Utility &amp; Helpers](/categories/utility)

rasshofer/papprika
==================

The papprika application toolkit.

04PHP

Since Nov 13Pushed 11y ago1 watchersCompare

[ Source](https://github.com/rasshofer/papprika)[ Packagist](https://packagist.org/packages/rasshofer/papprika)[ RSS](/packages/rasshofer-papprika/feed)WikiDiscussions master Synced 2d ago

READMEChangelogDependenciesVersions (1)Used By (0)

papprika
========

[](#papprika)

> papprika is a small but spicy application toolkit created to help you building awesome RESTful web applications with ease.

papprika is in active development, (see note below) offers you everything you need but nothing you don’t and is easy to use for both beginners and professionals. All you need to use papprika is a web server like Apache or nginx running PHP &gt;=5.3. You’re going to love it.

Deprecation (\* 2012 † 2014)
----------------------------

[](#deprecation--2012--2014)

Please note that papprika is abandoned and no longer maintained as of 2014. This repository is kept alive in order to provide the neccessary documentation for maintaining existing papprika projects. If you’re looking for an alternative to papprika, you should have a look at the awesome [Silex micro-framework](https://github.com/silexphp/Silex) and all the wonderful [Symfony components](http://symfony.com/de/components).

Yet another PHP toolkit?
------------------------

[](#yet-another-php-toolkit)

I made papprika because I wanted to help awesome people make awesome things. More than anything else, that’s entirely why I work on papprika whenever I can. It started off as a resource to help make better looking and more usable internal tools at [fapprik](http://fapprik.com/) and all along the development process, I knew others could use this to do cool things, too. Since I’m a huge proponent of open source tools, I wanted to give back to the community with this one, too.

Getting started
---------------

[](#getting-started)

### Download papprika

[](#download-papprika)

At first, you have to [download](https://github.com/rasshofer/papprika/zipball/master) the current papprika version and unzip it into your virtual host’s public directory.

### Set up your webserver

[](#set-up-your-webserver)

To have beautiful URLs like `http://example.com/about`, papprika requires you to do some little server configuration—which is pretty easy as you can find everything you need below.

#### Apache

[](#apache)

If you’re running papprika on an Apache webserver, please check if your hosting provider enabled the `mod_rewrite` module (nowadays it’s usually enabled). If it’s enabled, you’ve to create a `.htaccess` file in the root directory of your papprika installation (if it doesn’t exist already) and add the following rewrite rules to it.

```
RewriteEngine on
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
```

#### nginx

[](#nginx)

If you’re running papprika on an nginx webserver, you’ve to add the following rewrite rules to your sites’s configuration.

```
location / {

    root /path/to/papprika;
    index index.php;

    if (!-f $request_filename) {
        rewrite ^(.*)$ /index.php last;
        break;
    }

    if (!-d $request_filename) {
        rewrite ^(.*)$ /index.php last;
        break;
    }

}
```

papprika\\Application
---------------------

[](#papprikaapplication)

To get started with papprika, all you need to do is `require` the `papprika.php` file and create an instance of `papprika\Application`. After your controller definitions, call the `run` method on your application.

```
require_once './papprika.php';

$app = new papprika\Application();

// your controller-definitions

$app->run();
```

### Sub directories

[](#sub-directories)

Of course papprika also works in sub directories, too. Just pass the sub directory path through the constructor (without a trailing slash).

```
$app = new papprika\Application('/sub/directory');
```

### Routing

[](#routing)

Using papprika, you’ve to define routes and the appropriate controller(s), which are called when the route is matched. At the start of every route, you have to choose the appropriate method (`GET`, `POST`, `PUT` or `DELETE`), which describes the interaction with the resource. If you can’t decide which method to choose, you can use `$app->any('/home', …)` to use all four methods. Each route has one or more patterns, which define the paths that point to your resources and can include variables which you’re able to catch and work with. If you want to use more than one pattern for a route, simply pass an array instead of a string. Last but not least you’ve to provide your controllers using closures or methods (see »Scaling papprika« for more information and examples).

```
$app->get('/home', function() {
    // do something
});
```

That was easy, huh? Don’t worry, the rest is equally simple. Let’s have a look at a more detailed example, which shows the advantages of closures—anonymous functions that can import stuff from outside of their definition. This is different from globals, because the outer state doesn’t have to be global.

```
$news = array(
    1 => array(
        'date' => '2010-01-01',
        'author' => 'thomas',
        'title' => 'Hello World!',
        'text' => 'Hello World!'
    ),
    2 => array(
        'date' => '2011-01-01',
        'author' => 'thomas',
        'title' => 'papprika 0.1 released',
        'text' => 'Hello World!'
    ),
    3 => array(
        'date' => '2012-01-01',
        'author' => 'thomas',
        'title' => 'papprika 0.2 released',
        'text' => 'Hello World!'
    )
);

$app->get('/news', function() use ($news) {
    echo '';
    foreach($news as $id => $post) {
        echo ''.$post['title'].'';
    }
    echo '';
});
```

Visiting `/news` will return a list of news. The `use`-statement tells the closure to import the `$news`-variable from the outer scope, which allows us to use it within the closure.

### Dynamic routing

[](#dynamic-routing)

Now we need another controller for viewing individual news, which is realized through dynamic routing.

```
$app->get('/news/:id', function($id) use ($news) {
    if(!array_key_exists($id, $news)) {
        die('Post #'.$id.' wasn\'t found…');
    }
}, function($id) use ($news) {
    echo ''.$news[$id]['title'].'';
    echo ''.$news[$id]['date'].'';
    echo nl2br($news[$id]['text']);
});
```

Noticed the two changes? On the one hand we appended `:id` to the pattern, which causes that this route definition has a variable called `id`, which is passed to the closure. Of course you can use as many of these variables as you want. On the other hand we’re using two controllers for the pattern in this example. You may provide an unlimited number of these in-between callbacks, which must be callable closures/methods and which will be invoked in the order specified. This has no bigger reason, but allows you to separate your code (first check if the passed ID exists and then show it).

As you know everything about getting pages now, it’s time for a first post route: a contact form wherefore we’ll use the `mail`-function to send an email.

```
$app->post('/contact', function() use ($app) {
    $message = $app->request('message');
    mail('&#112;&#097;&#112;&#112;&#114;&#105;&#107;&#097;&#064;&#116;&#104;&#111;&#109;&#097;&#115;&#114;&#097;&#115;&#115;&#104;&#111;&#102;&#101;&#114;&#046;&#099;&#111;&#109;', 'Contact', $message);
});
```

papprika offers you a simple opportunity to fetch transmitted variables depending on the request method. In the example above, `$app->request('message')` returns `$_POST['message']`. This works for all methods.

### Add routes from a configuration file

[](#add-routes-from-a-configuration-file)

Sometimes it may make sense to separate your routes from your `index.php`—for example if you want to make your `index.php` reusable and independent of an application’s routes. Therefore you can add routes from a configuration file (INI files).

```
$app->ini('./routing.ini');
```

```
[get]
/contact = Thomas\TestApp\Controller\ContactController::indexAction

[post]
/contact = Thomas\TestApp\Controller\ContactController::sendAction
```

As you may have noticed, you have to use methods for defining callbacks to your routes. For more information and examples, see »Scaling papprika«.

You should deny any access to this configuration file through your webserver for security reasons.

### Conditions

[](#conditions)

You may want to only match certain expressions in some cases—therefore papprika allows you to define conditions using regular expressions by calling `assert` on the controller object, which is returned by the routing methods.

```
$app->get('/news/:id', function($id) use ($news) {
    // do something
})->assert('id', '\d+');```

```php
$app->get('/hello/:name', function($name) {
    echo 'Hello, '.$name;
})->assert('name', '([a-zA-Z]+)');
```

The example above makes sure the `id` argument is numeric, since `\d+` is a regular expression for matching any amount of digits.

### before / after / error

[](#before--after--error)

papprika allows you to run code before and after every request or if the requested page wasn’t found. All you need to do is passing closures/methods.

```
$app->before(function() {
    echo '';
    echo '';
        echo '';
            echo '';
        echo '';
        echo '';
            echo 'Test-Application';
})->after(function() {
            echo '© papprika';
        echo '';
    echo '';
})->error(function() {
    echo 'The page you requested couldn’t be found.';
});
```

As you see, `before` and `after` are pretty handsome for some header/footer stuff. Did you notice the routes in the example above were chained? This is a bit jQuery-inspired and perfect for organizing/grouping your routes.

```
$app->get(array('/', '/news'), function() use ($news) {
    // do something
})->get('/news/:id/:title', function($id, $title) use ($news) {
    // do something with $id and $title
});
```

papprika\\Templates
-------------------

[](#papprikatemplates)

While there are several template-systems available, none of their approaches makes really happy. Many of them use their own pseudo syntax which makes things more complicated instead of simplifying the whole templating-thing. Therefore papprika brings its own small template system, which is really easy to understand and use. This may be a bit dangerous regarding the separation of layout and logic and requires special care at this point, but it’ll be rewarded by a very fast implementation and highly variable applications. So always think twice where functions belong.

Because 3 lines of code are worth a thousand words, let’s have a look at how easy it is to use templates in your papprika application!

```
echo new papprika\Template('./footer.php', array(
    'copyright' => 2011-'.date('Y')
));
```

Wow, that was quick and painless, huh? Let’s have a look at the `footer.php`-file…

```
        echo '© '.$this->copyright.' papprika';
    echo '';
echo '';
```

That’s it.

### Customizing / beforeParse / afterParse

[](#customizing--beforeparse--afterparse)

If you need/want, you can customize the class. Additionally there are two methods called `beforeParse` and `afterParse`, which are executed before and after the template is parsed and filled with your contents. They also need some customization. Want an example?

```
class tpl extends papprika\Template {

    public function __construct($file, $data = array()) {
        parent::__construct('/var/www/templates/'.$file, $data);
    }

    function afterParse() {
        $this->_output = str_replace('HTML', 'HTML', $this->_output);
    }

}
```

papprika\\File
--------------

[](#papprikafile)

papprika also provides some useful and handy functions for working with files in your application.

MethodDescription`$file->name()`Returns the name of the file (without extension)`$file->filename()`Returns the file’s entire name`$file->extension()`Returns the file extension`$file->modified()`Returns the file’s last modify date (as unix timestamp)`$file->size()`Returns the raw filesize (in bytes)`$file->niceSize()`Returns the readable filesize (KB, MB, …)```
$latest = new papprika\File('./latest.zip');
echo 'Download '.$latest->name().'.'.$latest->extension().' ('.$latest->niceSize().')';
```

By the way: There are further informations provided to every file for images.

MethodDescription`$file->width()`Returns the width of the image`$file->height()`Returns the height of the image`$file->mime()`Returns the mime-type of the image```
$team = new papprika\File('./team.jpg');
echo ' height="'.$team->height().'">';
```

Unfortunately papprika has no built-in image resizer yet, but it provides you some useful functions for recalculating your image’s sizes. Of course you won’t get smaller files, but you can embed your images into your application with different sizes.

```
$logo = new papprika\File('./logo.jpg')->max(200);
echo '';
```

```
$logo = new papprika\File('./logo.jpg')->maxWidth(200);
echo '';
```

```
$logo = new papprika\File('./logo.jpg')->maxHeight(200);
echo '';
```

papprika\\MySQL\\Connection
---------------------------

[](#papprikamysqlconnection)

papprika offers a simple opportunity to use MySQL databases in your application. At first, you connect to your database using the host, username and password and select the database.

```
$db = new papprika\MySQL\Connection('localhost', 'root', '123', 'app');
```

### Charset

[](#charset)

You can also set the default character set for the appropriate connection easily.

```
$db->charset('utf8');
```

papprika\\MySQL\\Queries
------------------------

[](#papprikamysqlqueries)

As we now have a connection established, we can start to execute some queries and fetch the result rows, which are returned as objects.

```
$res = new papprika\MySQL\Query('SELECT * FROM news', $db);
echo '';
while($post = $res->fetch()) {
    echo ''.$post->title.'';
}
echo '';
```

Besides the `fetch` method, there are three other methods which may also be interessting for your daily database business.

### Get rows

[](#get-rows)

The `rows` method retrieves the number of rows from the appropriate result set. This command is only valid for statements like `SELECT` or `SHOW` that return an actual result set.

```
$res = new papprika\MySQL\Query('SELECT * FROM news', $db);
echo $res->rows().' news found.';
```

### Affected rows

[](#affected-rows)

To retrieve the number of rows affected by a `INSERT`, `UPDATE`, `REPLACE` or `DELETE` query, the `affected` method is your friend.

```
$res = new papprika\MySQL\Query('UPDATE news SET title = "abc"', $db);
echo $res->affected().' news were affected.';
```

### Inserted ID

[](#inserted-id)

Last but not least you may want to retrieve the ID generated for an `AUTO_INCREMENT` column by the appropriate query.

```
$res = new papprika\MySQL\Query('INSERT INTO news (title) VALUES ("Hello World")', $db);
$newsId = $res->id();
```

### Escaping

[](#escaping)

As we all know, there are several evil people around who try to do some SQL injections to your app. papprika hates these guys just like you, therefore it offers a really easy syntax to build your queries while it prepares and escapes everything to prevent injections. Let’s have a look at an example.

```
$a = $app->request('a');
$b = $app->request('b');
$query = 'SELECT * FROM news WHERE a = "%s" && b = "%s"';
$res = new papprika\MySQL\Query($query, $a, $b, $db);
```

`$a` and `$b` get automatically escaped and inserted for the `%s` placeholders. The usage is equivalent to [`sprintf`](http://php.net/manual/en/function.sprintf.php).

### Only MySQL? :(

[](#only-mysql-)

As you may have noticed, we swaped the MySQL stuff into its own sub-namespace (`papprika\MySQL`). So, guess what! The implementation of other database extensions in the near future is already planned! :)

Scaling papprika
----------------

[](#scaling-papprika)

While working on big projects with papprika, you may have 20-30 of long inline controllers and everything gets a bit confusing. One of the common complaints that I hear is that papprika forces you to put all of your code into a single file. But you aren’t forced to do so, instead I highly recommend to move your controllers into classes.

```
namespace Thomas\TestApp\Controller;

class ChatController {

    public function messageAction($id) {
        …
    }

}
```

```
$app->get('/chat/message/:id', 'Thomas\TestApp\Controller\ChatController::messageAction');
```

And if those class names are too long, you can easily write a fancy function to shorten them.

```
function controller($name) {
    list($class, $method) = explode('/', $name, 2);
    return sprintf('Thomas\TestApp\Controller\%sController::%sAction', ucfirst($class), $method);
}

$app->get('/chat/message/:id', controller('chat/message'));
```

So, as you hopefully see, papprika is able to grow organically as your code base grows.

papprika vs. frameworks
-----------------------

[](#papprika-vs-frameworks)

It’s difficult to draw the line between papprika and its big brothers, all these fancy frameworks. papprika is no framework, but it provides you all you need to build your own framework with. Use papprika if you’re comfortable with making all of your own architecture decisions and use a full stack framework if not. To put it in other words: it really doesn’t matter how large your application is and how many routes, controllers and services you have. You’ll always find a solution for that on a technical level. The challenge you’ll actually face is people.

Full example
------------

[](#full-example)

Concluding the following example shows the combination of several things mentioned above.

```
$app = new papprika\Application();

$app->before(function() {
    echo new papprika\Template('./header.php', array(
        'title' => 'News @ '.$_SERVER['HTTP_HOST'],
        'time' => time()
    ));
})->after(function() {
    echo new papprika\Template('./footer.php', array(
        'copyright' => '2011-'.date('Y')
    ));
})->error(function() {
    echo new papprika\Template('./404.php');
});

$db = new papprika\MySQL\Connection('localhost', 'root', '123', 'app');
$db->charset('utf8');

$app->get('/news', function() use ($db) {
    $news = new papprika\MySQL\Query('SELECT * FROM news', $db);
    echo '';
    while($post = $news->fetch()) {
        echo ''.$post->title.'';
    }
    echo '';
});

$app->get('/news/:id', function($id) use ($db, $templates) {
    $query = 'SELECT title, text, date FROM news WHERE id = "'.$id.'"';
    $res = new papprika\MySQL\Query($query, $db);
    if($res->rows() == 0) {
        echo 'FOUR OH FOUR';
    } else {
        $post = $res->fetch();
        echo new papprika\Template('./post.php', array(
            'title' => $post->title,
            'text' => nl2br($post->text),
            'date' => date('F jS Y', $post->date)
        ));
    }
})->assert('id', '\d+');

$app->get('/search', function() use ($db, $app) {
    $q = $app->request('q');
    $query = 'SELECT title, text, date FROM news WHERE title = "%s"';
    $res = new papprika\MySQL\Query($query, $q, $db);
    if($res->rows() == 0) {
        echo 'Nothing found…';
    } else {
        echo '';
        while($post = $res->fetch()) {
            echo ''.$post->title.'';
        }
        echo '';
    }
});

$app->run();
```

License
-------

[](#license)

Copyright (c) 2012-2014 [Thomas Rasshofer](http://thomasrasshofer.com/)
Licensed under the MIT license.

See LICENSE for more info.

###  Health Score

19

—

LowBetter than 9% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity3

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity41

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

### Community

Maintainers

![](https://www.gravatar.com/avatar/2469d7a8677c55d57805c53e563a3d95fd117443652d9c8c570364dc323a65c0?d=identicon)[rasshofer](/maintainers/rasshofer)

---

Top Contributors

[![rasshofer](https://avatars.githubusercontent.com/u/497973?v=4)](https://github.com/rasshofer "rasshofer (26 commits)")

### Embed Badge

![Health badge](/badges/rasshofer-papprika/health.svg)

```
[![Health](https://phpackages.com/badges/rasshofer-papprika/health.svg)](https://phpackages.com/packages/rasshofer-papprika)
```

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
