Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
panique committed Feb 8, 2014
1 parent 2e8e8b8 commit a03ba2d
Show file tree
Hide file tree
Showing 29 changed files with 855 additions and 3 deletions.
20 changes: 20 additions & 0 deletions .htaccess
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Necessary to prevent problems when using a controller named "index" and having a root index.php
# more here: http://httpd.apache.org/docs/2.2/content-negotiation.html
Options -MultiViews

# Activates URL rewriting (like myproject.com/controller/action/1/2/3)
RewriteEngine On

# Disallows others to look directly into /public/ folder
Options -Indexes

# When using the script within a sub-folder, put this path here, like /mysubfolder/
# If your app is in the root of your web folder, then leave it commented out
RewriteBase /php-mvc-advanced/

# General rewrite rules
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-l

RewriteRule ^(.+)$ index.php?url=$1 [QSA,L]
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
CHANGE LOG
==========

**January 4th 2014**
- fixed htaccess issue when there's a controller named "index" and a base index.php (which collide)

**December 29th 2013**
- fixed case-sensitive model file loading (thanks "grrnikos")
156 changes: 153 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,154 @@
php-mvc-advanced
================
# PHP-MVC-ADVANCED

A simple and easy to understand MVC skeleton application. Same like php-mvc, but with more features.
*Note: This is the same like panique/php-mvc, but with additional features.*
*This repo is in development, more to come...*

*New in the advanced version: Twig*

An extremely simple and easy to understand MVC skeleton application, reduced to the max.
Everything is **as simple as possible**, as **manually as possible** and as readable as possible.
This project is - by intention - NOT a full framework, it's a bare-bone structure, written in
purely native PHP ! The php-mvc skeleton tries to be the extremely slimmed down opposite of big frameworks
like Zend2, Symfony or Laravel.

## Why does this project exist ?

One of the biggest question in the PHP world is "How do I build an application ?".
It's hard to find a good base, a good file structure and useful information on that, but at the same time
there are masses of frameworks that might be really good, but really hard to understand, hard to use and extremely
complex. This project tries to be some kind of naked skeleton bare-bone for quick application building,
especially for the not-so-advanced coder.

### Goals of this project:

- give people a clean base MVC structure to build a modern PHP application with
- teach people the basics of the Model-View-Controller architecture
- encourage people to code according to PSR 1/2 coding guidelines
- promote the usage of PDO
- promote the usage of external libraries via Composer
- promote development with max. error reporting
- promote to comment code
- promote the usage of OOP code
- using only native PHP code, so people don't have to learn a framework

## Installation

First, copy this repo into a public accessible folder on your server.
Common techniques are a) downloading and extracting the .zip / .tgz by hand, b) cloning the repo with git (into var/www)

```
git clone https://github.com/panique/php-mvc-advanced.git /var/www
```

1. Install mod_rewrite, for example by following this guideline:
[How to install mod_rewrite in Ubuntu](http://www.dev-metal.com/enable-mod_rewrite-ubuntu-12-04-lts/)

2. Run the SQL statements in the *application/_install* folder.

3. Change the .htaccess file from
```
RewriteBase /php-mvc-advanced/
```
to where you put this project, relative to the web root folder (usually /var/www). So when you put this project into
the web root, like directly in /var/www, then the line should look like or can be commented out:
```
RewriteBase /
```
If you have put the project into a sub-folder, then put the name of the sub-folder here:
```
RewriteBase /sub-folder/
```

4. Edit the *application/config/config.php*, change this line
```php
define('URL', 'http://127.0.0.1/php-mvc-advanced/');
```
to where your project is. Real domain, IP or 127.0.0.1 when developing locally. Make sure you put the sub-folder
in here (when installing in a sub-folder) too, also don't forget the trailing slash !

5. Edit the *application/config/config.php*, change these lines
```php
define('DB_TYPE', 'mysql');
define('DB_HOST', '127.0.0.1');
define('DB_NAME', 'php-mvc');
define('DB_USER', 'root');
define('DB_PASS', 'mysql');
```
to your database credentials. If you don't have an empty database, create one. Only change the type `mysql` if you
know what you are doing.

## A quickstart tutorial

You can also find these tutorial pictures in the *_tutorial* folder.

![php-mvc introduction tutorial - page 1](_tutorial/tutorial-part-01.png)
![php-mvc introduction tutorial - page 2](_tutorial/tutorial-part-02.png)
![php-mvc introduction tutorial - page 3](_tutorial/tutorial-part-03.png)
![php-mvc introduction tutorial - page 4](_tutorial/tutorial-part-04.png)
![php-mvc introduction tutorial - page 5](_tutorial/tutorial-part-05.png)

## You like what you see ?

Then please also have a look on ...

#### My other project php-login

A collection of 4 similar login scripts for PHP, from a super-simple one-file
script with a SQLite one-file to a highly professional MVC frameworks solution. All scripts use the most advanced
hashing algorithms possible in PHP, exactly like the PHP core developers want you to use them.

https://github.com/panique/php-login (full MVC framework)

https://github.com/panique/php-login-minimal (minimal)

https://github.com/panique/php-login-advanced (advanced)

https://github.com/panique/php-login-one-file (one-file)

#### My PHP and frontend blog

Lots of non-boring development stuff and tutorials there.

http://www.dev-metal.com

## Useful information

1. SQLite does not have a rowCount() method (!). Keep that in mind in case you use SQLite.

2. Don't use the same name for class and method, as this might trigger an (unintended) *__construct* of the class.
This is really weird behaviour, but documented here: [php.net - Constructors and Destructors](http://php.net/manual/en/language.oop5.decon.php).

## Add external libraries via Composer

To add external libraries/tools/whatever into your project in an extremely clean way, simply add a line with the
repo name and version to the composer.json! Take a look on these tutorials if you want to get into Composer:
[How to install (and update) Composer on Windows 7 or Ubuntu / Debian](http://www.dev-metal.com/install-update-composer-windows-7-ubuntu-debian-centos/)
and [Getting started with Composer](http://www.dev-metal.com/getting-started-composer/).

## License

This project is licensed under the MIT License.
This means you can use and modify it for free in private or commercial projects.

## Contribute

Please commit into the develop branch (which holds the in-development version), not into master branch
(which holds the tested and stable version).

## Support / Donate

If you think this script is useful and saves you a lot of work, then think about supporting the project:

1. Donate via [PayPal](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=P5YLUK4MW3LDG) or [GitTip](https://www.gittip.com/Panique/)
2. Rent your next server at [A2 Hosting](http://www.a2hosting.com/4471.html) or [DigitalOcean](https://www.digitalocean.com/?refcode=40d978532a20).
3. Contribute to this project. Feel free to improve this project with your skills.
4. Spread the word: Tell others about this project.

## Linked music tracks in the demo application

The linked tracks in this naked application are just some of my personal favourites of the last few months.
I think it's always a good idea to fill boring nerd-code stuff with quality culture.

## Statistics (by BitDeli)

[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/panique/php-mvc/trend.png)](https://bitdeli.com/free "Bitdeli Badge")
Binary file added _tutorial/tutorial-part-01.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added _tutorial/tutorial-part-02.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added _tutorial/tutorial-part-03.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added _tutorial/tutorial-part-04.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added _tutorial/tutorial-part-05.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions application/.htaccess
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<Files *.twig>
Order Deny,Allow
Deny from all
</Files>
1 change: 1 addition & 0 deletions application/_install/01-create-database.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
CREATE DATABASE IF NOT EXISTS `php-mvc`;
8 changes: 8 additions & 0 deletions application/_install/02-create-table-song.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
CREATE TABLE `php-mvc`.`song` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`artist` text COLLATE utf8_unicode_ci NOT NULL,
`track` text COLLATE utf8_unicode_ci NOT NULL,
`link` text COLLATE utf8_unicode_ci,
PRIMARY KEY (`id`),
UNIQUE KEY `id` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=31 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
31 changes: 31 additions & 0 deletions application/_install/03-insert-demo-data-into-table-song.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
INSERT INTO `php-mvc`.`song` (`id`, `artist`, `track`, `link`) VALUES
(1, 'Dena', 'Cash, Diamond Ring, Swimming Pools', 'http://www.youtube.com/watch?v=r4CDc9yCAqE'),
(2, 'Jessy Lanza', 'Kathy Lee', 'http://vimeo.com/73455369'),
(3, 'The Orwells', 'In my Bed (live)', 'http://www.youtube.com/watch?v=8tA_2qCGnmE'),
(4, 'L''Orange & Stik Figa', 'Smoke Rings', 'https://www.youtube.com/watch?v=Q5teohMyGEY'),
(5, 'Labyrinth Ear', 'Navy Light', 'http://www.youtube.com/watch?v=a9qKkG7NDu0'),
(6, 'Bon Hiver', 'Wolves (Kill them with Colour Remix)', 'http://www.youtube.com/watch?v=5GXAL5mzmyw'),
(7, 'Detachments', 'Circles (Martyn Remix)', 'http://www.youtube.com/watch?v=UzS7Gvn7jJ0'),
(8, 'Dillon & Dirk von Loetzow', 'Tip Tapping (Live at ZDF Aufnahmezustand)', 'https://www.youtube.com/watch?v=hbrOLsgu000'),
(9, 'Dillon', 'Contact Us (Live at ZDF Aufnahmezustand)', 'https://www.youtube.com/watch?v=E6WqTL2Up3Y'),
(10, 'Tricky', 'Hey Love (Promo Edit)', 'http://www.youtube.com/watch?v=OIsCGdW49OQ'),
(11, 'Compuphonic', 'Sunset feat. Marques Toliver (DJ T. Remix)', 'http://www.youtube.com/watch?v=Ue5ZWSK9r00'),
(12, 'Ludovico Einaudi', 'Divenire (live @ Royal Albert Hall London)', 'http://www.youtube.com/watch?v=X1DRDcGlSsE'),
(13, 'Maxxi Soundsystem', 'Regrets we have no use for (Radio1 Rip)', 'https://soundcloud.com/maxxisoundsystem/maxxi-soundsystem-ft-name-one'),
(14, 'Beirut', 'Nantes (Fredo & Thang Remix)', 'https://www.youtube.com/watch?v=ojV3oMAgGgU'),
(15, 'Buku', 'All Deez', 'http://www.youtube.com/watch?v=R0bN9JRIqig'),
(16, 'Pilocka Krach', 'Wild Pete', 'http://www.youtube.com/watch?v=4wChP_BEJ4s'),
(17, 'Mount Kimbie', 'Here to stray (live at Pitchfork Music Festival Paris)', 'http://www.youtube.com/watch?v=jecgI-zEgIg'),
(18, 'Kool Savas', 'King of Rap (2012) / Ein Wunder', 'http://www.youtube.com/watch?v=mTqc6UTG1eY&hd=1'),
(19, 'Chaim feat. Meital De Razon', 'Love Rehab (Original Mix)', 'http://www.youtube.com/watch?v=MJT1BbNFiGs'),
(20, 'Emika', 'Searching', 'http://www.youtube.com/watch?v=oscuSiHfbwo'),
(21, 'Emika', 'Sing to me', 'http://www.youtube.com/watch?v=k9sDBZm8pgk'),
(22, 'George Fitzgerald', 'Thinking of You', 'http://www.youtube.com/watch?v=-14B8l49iKA'),
(23, 'Disclosure', 'You & Me (Flume Edit)', 'http://www.youtube.com/watch?v=OUkkaqSNduU'),
(24, 'Crystal Castles', 'Doe Deer', 'http://www.youtube.com/watch?v=zop0sWrKJnQ'),
(25, 'Tok Tok vs. Soffy O.', 'Missy Queens Gonna Die', 'http://www.youtube.com/watch?v=EN0Tnw5zy6w'),
(26, 'Fink', 'Maker (Synapson Remix)', 'http://www.youtube.com/watch?v=Dyd-cUkj4Nk'),
(27, 'Flight Facilities (ft. Christine Hoberg)', 'Clair De Lune', 'http://www.youtube.com/watch?v=Jcu1AHaTchM'),
(28, 'Karmon', 'Turning Point (Original Mix)', 'https://www.youtube.com/watch?v=-tB-zyLSPEo'),
(29, 'Shuttle Life', 'The Birds', 'http://www.youtube.com/watch?v=-I3m3cWDEtM'),
(30, 'Santé', 'Homegirl (Rampa Mix)', 'http://www.youtube.com/watch?v=fnhMNOWxLYw');
40 changes: 40 additions & 0 deletions application/config/config.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php

/**
* Configuration
*
* For more info about constants please @see http://php.net/manual/en/function.define.php
* If you want to know why we use "define" instead of "const" @see http://stackoverflow.com/q/2447791/1114320
*/

/**
* Configuration for: Error reporting
* Useful to show every little problem during development, but only show hard errors in production
*/
error_reporting(E_ALL);
ini_set("display_errors", 1);

/**
* Configuration for: Project URL
* Put your URL here, for local development "127.0.0.1" or "localhost" (plus sub-folder) is fine
*/
define('URL', 'http://127.0.0.1/php-mvc-advanced/');

/**
* Configuration for: Database
* This is the place where you define your database credentials, database type etc.
*/
define('DB_TYPE', 'mysql');
define('DB_HOST', '127.0.0.1');
define('DB_NAME', 'php-mvc');
define('DB_USER', 'root');
define('DB_PASS', 'mysql');

/**
* Configuration for: Views
*
* PATH_VIEWS is the path where your view files are. Don't forget the trailing slash!
* PATH_VIEW_FILE_TYPE is the ending of your view files, like .php, .twig or similar.
*/
define('PATH_VIEWS', 'application/views/');
define('PATH_VIEW_FILE_TYPE', '.twig');
41 changes: 41 additions & 0 deletions application/controller/home.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php

/**
* Class Home
*
* Please note:
* Don't use the same name for class and method, as this might trigger an (unintended) __construct of the class.
* This is really weird behaviour, but documented here: http://php.net/manual/en/language.oop5.decon.php
*
*/
class Home extends Controller
{
/**
* PAGE: index
* This method handles what happens when you move to http://yourproject/home/index (which is the default page btw)
*/
public function index()
{
$this->render('home/index');
}

/**
* PAGE: exampleone
* This method handles what happens when you move to http://yourproject/home/exampleone
* The camelCase writing is just for better readability. The method name is case insensitive.
*/
public function exampleOne()
{
$this->render('home/example_one');
}

/**
* PAGE: exampletwo
* This method handles what happens when you move to http://yourproject/home/exampletwo
* The camelCase writing is just for better readability. The method name is case insensitive.
*/
public function exampleTwo()
{
$this->render('home/example_two');
}
}
76 changes: 76 additions & 0 deletions application/controller/songs.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
<?php

/**
* Class Songs
* This is a demo class.
*
* Please note:
* Don't use the same name for class and method, as this might trigger an (unintended) __construct of the class.
* This is really weird behaviour, but documented here: http://php.net/manual/en/language.oop5.decon.php
*
*/
class Songs extends Controller
{
/**
* PAGE: index
* This method handles what happens when you move to http://yourproject/songs/index
*/
public function index()
{
// load a model, perform an action, pass the returned data to a variable
// NOTE: please write the name of the model "LikeThis"
$songs_model = $this->loadModel('SongsModel');
$songs = $songs_model->getAllSongs();

// load another model, perform an action, pass the returned data to a variable
// NOTE: please write the name of the model "LikeThis"
$stats_model = $this->loadModel('StatsModel');
$amount_of_songs = $stats_model->getAmountOfSongs();

// render the view, pass the data
$this->render('songs/index', array('songs' => $songs, 'amount_of_songs' => $amount_of_songs));
}

/**
* ACTION: addSong
* This method handles what happens when you move to http://yourproject/songs/addsong
* IMPORTANT: This is not a normal page, it's an ACTION. This is where the "add a song" form on songs/index
* directs the user after the form submit. This method handles all the POST data from the form and then redirects
* the user back to songs/index via the last line: header(...)
* This is an example of how to handle a POST request.
*/
public function addSong()
{
// if we have POST data to create a new song entry
if (isset($_POST["submit_add_song"])) {
// load model, perform an action on the model
$songs_model = $this->loadModel('SongsModel');
$songs_model->addSong($_POST["artist"], $_POST["track"], $_POST["link"]);
}

// where to go after song has been added
header('location: ' . URL . 'songs/index');
}

/**
* ACTION: deleteSong
* This method handles what happens when you move to http://yourproject/songs/deletesong
* IMPORTANT: This is not a normal page, it's an ACTION. This is where the "delete a song" button on songs/index
* directs the user after the click. This method handles all the data from the GET request (in the URL!) and then
* redirects the user back to songs/index via the last line: header(...)
* This is an example of how to handle a GET request.
* @param int $song_id Id of the to-delete song
*/
public function deleteSong($song_id)
{
// if we have an id of a song that should be deleted
if (isset($song_id)) {
// load model, perform an action on the model
$songs_model = $this->loadModel('SongsModel');
$songs_model->deleteSong($song_id);
}

// where to go after song has been deleted
header('location: ' . URL . 'songs/index');
}
}
Loading

0 comments on commit a03ba2d

Please sign in to comment.