<commit_before># tipy

Tiny PHP MVC framework.

## Prerequisites

* PHP 5.5+
* Apache 2
* MySQL
* Git
* Composer

## Installation

Clone [tipy-project](https://github.com/smetana/tipy-project) to quickly bootstrap your tipy web app.
This is an application skeleton for a typical tipy project.

```shell
git clone https://github.com/smetana/tipy-project myproject
cd myproject
composer.phar install
```
You can also use [tipy-example](https://github.com/smetana/tipy-example) as a demo.

## Convention over Configuration

tipy follows "Convention over Configuration" paradigm therefore you have
to maintain only one small config file for database connection but you have
to follow tipy conventions in code.

## Routes

tipy uses Apache's .htaccess for routing.<br/>
Using combination of predefined rewrite rules and tipy conventions it is very
easy to define new routes.

/public/.htaccess
```apache
RewriteRule ^$        /blog [QSA,L]
# => BlogController::index()

RewriteRule ^/code$   /code/open_source [QSA,L]
# => CodeController::openSource()
```

## Models
app/models/BlogPost.php
```php
class BlogPost extends TipyModel {
    protected $hasMany = [
        'comments' => ['class' => 'Comment', 'dependent' => 'destroy']
    );
}
```
app/models/Comment.php
```php
class Comment extends TipyModel {
    protected $belongsTo = [
        'post' => ['class' => 'BlogPost', 'foreign_key' => 'blog_post_id']
    ];
}
```

## Controllers
app/controllers/BlogController.php

```php
class BlogController extends TipyController {

    public function article() {
        $blogPost = BlogPost::load($this->in('id'));
        $this->out('blogPost', $blogPost);
        $this->out('comments', $blogPost->comments);
        $this->renderView('blog/article');
    }

}
```

## Views
tipy views are plain php files. Simple and powerful. No heavy template systems. And all your application data is isolated from views.
You pass to view only you what to want to show.

app/controllers/BlogController.php
```php
class BlogController extends TipyController {

    public function article() {
        $post = BlogPost::load($this-in('id'));
        $this->out->set('title', $post->title);
        $this->out->set('message', $post->message);
        $this->renderView('blog/article');
    }
}
```
app/views/blog/article.php

```html
<!DOCTYPE html>
<html>
<head>
    <title><?= $title ></title>
</head>
<body>
    <h1><?= $title ?></p>
    <p><?= $message ?></p>
</body>
</html>
```
<commit_msg>- Added apache config example to "Installation" section of README.md - Compact code samples<commit_after># tipy

Tiny PHP MVC framework.

## Prerequisites

* PHP 5.5+
* Apache 2
* MySQL
* Git
* Composer

## Installation

Clone [tipy-project](https://github.com/smetana/tipy-project) to quickly bootstrap your tipy web app:

```shell
git clone https://github.com/smetana/tipy-project myproject
cd myproject
composer.phar install
```
Add virtual host to apache2

```apache
# /etc/apache2/sites-available/tipy-conf

<VirtualHost 127.0.0.1:80>
    ServerName localhost
    DocumentRoot /home/user/projects/tipy-project/public
    <Directory "/home/user/projects/tipy-project">
        AllowOverride All
        Require all granted
    </Directory>
</VirtualHost>
```
You can also use [tipy-example](https://github.com/smetana/tipy-example) as a demo.

## Convention over Configuration

tipy follows "Convention over Configuration" paradigm therefore you have
to maintain only one small config file for database connection but you have
to follow tipy conventions in code.

## Routes

tipy uses Apache's .htaccess for routing.<br/>
Using combination of predefined rewrite rules and tipy conventions it is very
easy to define new routes:

```apache
# public/.htaccess

RewriteRule ^$        /blog [QSA,L]
# => BlogController::index()

RewriteRule ^/code$   /code/open_source [QSA,L]
# => CodeController::openSource()
```

## Models
```php
// app/models/BlogPost.php

class BlogPost extends TipyModel {
    protected $hasMany = [
        'comments' => ['class' => 'Comment', 'dependent' => 'destroy']
    );
}
```
```php
// app/models/Comment.php

class Comment extends TipyModel {
    protected $belongsTo = [
        'post' => ['class' => 'BlogPost', 'foreign_key' => 'blog_post_id']
    ];
}
```

## Controllers
```php
// app/controllers/BlogController.php

class BlogController extends TipyController {

    public function article() {
        $blogPost = BlogPost::load($this->in('id'));
        $this->out('blogPost', $blogPost);
        $this->renderView('blog/article');
    }

}
```

## Views
```html
<!-- app/views/blog/article.php -->

<!DOCTYPE html>
<html>
<head>
    <title><?= $blogPost->title ></title>
</head>
<body>
    <h1><?= $blogPost->title ?></p>
    <p><?= $blogPost->body ?></p>
    <? foreach($blogPost->comments as $comment) ?>
        <p><?= $comment->body ?></p>
    <? } ?>
</body>
</html>
```

{'fraction_non_alphanumeric': 0.15467919901920718, 'fraction_numerical': 0.0036779730281977932, 'mean_word_length': 3.7203471552555447, 'pattern_counts': {'":': 0, '<': 47, '<?xml version=': 0, '>': 83, 'https://': 6, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 1, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '551172', 'n_tokens_mistral': 1624, 'n_tokens_neox': 1538, 'n_words': 439}