Skip to content

Commit 56125d2

Browse files
committed
I wanted to build a little app for something and I felt like playing with this framework.
* Added migrations. * Added authentication, login bar. * Added a Session,Log,Db Wrapper that can be gotten from the DI container. * Setup PDO by default * General console commands. * Modified how templates work.
1 parent ef80730 commit 56125d2

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+990
-135
lines changed

README.md

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# Web Application Framework
22
A tiny PHP web application framework.
33

4+
# NOTE: THIS IS A TOY PROJECT, DO NOT USE IT!
5+
46
I had some issues with other frameworks, so this was just intended to be a demo of implemented solutions. A few other people and I are each writing our own minimalist web app solution just for the exercize of having done so.
57

68
## Keeping it simple
@@ -73,10 +75,6 @@ In PHPStorm I set the new server as the default and set the autoload option on t
7375

7476
Check to make sure the files ended up on your test VM where you expected them to be.
7577

76-
Rename the directory src/YourName/YourProject to be your name or your organizations name for your namespace root followed by the name of this project. This may feel like a lot of directories but it keeps it PSR-0 complient for when you want to package your project or use it with another PSR-0 compliant autoloader.
77-
78-
Then replace all the instances of YourName/YourProject in the template with the new values... what can I say the result won't have any magic since these are the example classes for you to edit, not something in the framework namespace.
79-
8078
Edit the configuration options in public_html/config.php to match where you put everything.
8179

8280
You should have a working hello world example.
@@ -85,7 +83,7 @@ You should have a working hello world example.
8583
So the idea is you set up all of the different things you need to inject in your own Di class that extends DiBase that is included with the framework. You then create one additional class to extend that class for each environment such as Dev/Prod/Testing.
8684
Then you set your environment in the config.php file.
8785

88-
In your Dev environment the system creates an instance of your DiDev class, and sets it as a singleton on the DiBase object. Throughout your project when you say Di::instance()->getWhateverComponent() you are actually calling DiDev so that it can optionally override any of your methods in your Di class but autocomplete still works fine because everything is declared in your Di class.
86+
In your Dev environment the system creates an instance of your DiDev class, and sets it as a singleton on the DiBase object. Throughout your project when you say Di::getWhateverComponent() you are actually calling DiDev so that it can optionally override any of your methods in your Di class but autocomplete still works fine because everything is declared in your Di class.
8987

9088
A common example is that you want a database PDO object that you can use in your widget repository. So in your Di class you create the method:
9189
```

template/app/config.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<?php
2+
/**
3+
* This should only be the super basic configuration requirements that won't really change.
4+
* Put the rest of the configuration in the Config classes so that you can manage them in git.
5+
*/
6+
define('ENVIRONMENT', 'Dev');
7+
define('APP_LOCATION', '/var/web-app-framework/template/app');

template/app/init.php

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,12 @@
11
<?php
2+
/**
3+
* This is the general init file for all things within this framework. It is for web/console/whatever so do not put
4+
* things related to the context in here.
5+
*
6+
* Place those things in initWeb.php and initConsole.php
7+
*/
8+
9+
require_once('config.php');
210
require 'errorHandler.php';
311

412
// Uncomment if using the composer auto loader
@@ -8,11 +16,9 @@
816
require 'autoload.php';
917

1018
// Load the config system.
11-
$configName = PROJECT_NAMESPACE . '\Config\Config' . ENVIRONMENT;
19+
$configName = '\Config\Config' . ENVIRONMENT;
1220
$configName::setInstanceForEnvironment();
1321

1422
// Setup dependency injection container based on environment
15-
$diName = PROJECT_NAMESPACE . '\Di\Di' . ENVIRONMENT;
16-
$diName::setInstanceForEnvironment();
17-
18-
session_start();
23+
$diName = '\Di\Di' . ENVIRONMENT;
24+
$diName::setInstanceForEnvironment();

template/app/initConsole.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?php
2+
3+
require_once('init.php');
4+
5+
/**
6+
* Save adding end of line after each line.
7+
*
8+
* @param $msg
9+
*/
10+
function say($msg)
11+
{
12+
echo($msg . PHP_EOL);
13+
}

template/app/initWeb.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<?php
2+
/**
3+
* Things required for setting up the framework for web connections (as opposed to the console)
4+
*/
5+
require_once('init.php');
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?php
2+
/**
3+
* Example that simply says that it ran
4+
*
5+
* Note that this file is ran as an include into the applyMigrations.php code so you don't need to set
6+
* anything up.
7+
*/
8+
say("Example migration ran. This will cause no harm.");
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
DROP TABLE IF EXISTS users;
2+
CREATE TABLE `users` (
3+
`user_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
4+
`first_name` varchar(200) DEFAULT '',
5+
`last_name` varchar(200) DEFAULT '',
6+
`email` varchar(200) DEFAULT '',
7+
`password` varchar(255) DEFAULT '',
8+
`entered_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
9+
PRIMARY KEY (`user_id`),
10+
KEY `first_name_idx` (`first_name`),
11+
KEY `last_name_idx` (`last_name`),
12+
KEY `email_idx` (`email`)
13+
) ENGINE=InnoDB DEFAULT CHARSET=UTF8MB4;

template/app/scripts/README

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
General location to put things you want to run on the command line.
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
<?php
2+
/**
3+
* The purpose of this script is to run any migrations you may have
4+
*/
5+
6+
use Config\Config;
7+
use Di\Di;
8+
9+
require_once('../../initConsole.php');
10+
11+
// Get a list of migrations
12+
$migrationFileNames = glob(APP_LOCATION . '/migrations/*');
13+
14+
// Get a list of applied migrations
15+
$pdo = Di::getPdo();
16+
$appliedMigrations = $pdo->query("SELECT name FROM migrations")->fetchAll(PDO::FETCH_COLUMN);
17+
18+
function applyFileThroughMysqlConsole($migrationFileName)
19+
{
20+
say("Applying migration $migrationFileName");
21+
22+
$config = Config::instance();
23+
24+
$user = escapeshellarg($config->databaseUsername);
25+
$pass = $config->databasePassword;
26+
if ($pass) {
27+
$pass = escapeshellarg("-p" . $pass);
28+
}
29+
$host = escapeshellarg($config->databaseHost);
30+
$name = escapeshellarg($config->databaseName);
31+
$port = escapeshellarg($config->databasePort);
32+
$mysqlConsoleCommand = $config->databaseConsoleCommand;
33+
$escapedMigrationFileName = escapeshellarg($migrationFileName);
34+
35+
$cmd = "cat $escapedMigrationFileName | $mysqlConsoleCommand -h $host -P $port -u $user $pass $name ";
36+
exec($cmd, $output, $return);
37+
if ($return) {
38+
say("Command failed with return value $return.");
39+
if ($output) {
40+
print_r($output);
41+
}
42+
exit();
43+
}
44+
}
45+
46+
foreach ($migrationFileNames as $migrationFileName) {
47+
$migrationName = basename($migrationFileName);
48+
if (!in_array($migrationName, $appliedMigrations)) {
49+
$suffix = substr($migrationFileName, -4);
50+
switch ($suffix) {
51+
case '.sql':
52+
applyFileThroughMysqlConsole($migrationFileName);
53+
break;
54+
case '.php':
55+
require($migrationFileName);
56+
break;
57+
default:
58+
say("Skipping file $migrationFileName as it is not in the types I can apply.");
59+
}
60+
$pdo->prepare("INSERT INTO migrations SET name=?")->execute([$migrationName]);
61+
} else {
62+
say("Skipping $migrationName, it is already applied.");
63+
}
64+
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
<?php
2+
/**
3+
* Help setting everything up
4+
*/
5+
use Di\Di;
6+
7+
require_once('../../initConsole.php');
8+
9+
say("Setting up the " . ENVIRONMENT . ' environment.');
10+
11+
// Check the app location field
12+
if (!defined('APP_LOCATION')) {
13+
say("You must edit the config.php file to set the app location!");
14+
exit();
15+
}
16+
17+
$whereImAt = APP_LOCATION . '/scripts/web-app-framework/setup.php';
18+
if ($whereImAt != __FILE__) {
19+
say("The web app location does not seem to be correct. Update your config.php file.");
20+
say("$whereImAt != " . __FILE__);
21+
exit();
22+
}
23+
say("The App Location in the config.php file seems to be correct.");
24+
25+
// Check the basic database connection works
26+
try {
27+
$pdo = Di::getPdo();
28+
say("Database connection ok.");
29+
} catch (PDOException $e) {
30+
say("It looks like your database is not set up correctly.");
31+
say("Verify your PDO connection information in the Config classes.");
32+
say($e->getMessage());
33+
}
34+
35+
// Check that the migrations table exists
36+
$pdo = Di::getPdo();
37+
$result = $pdo->query("SHOW TABLES LIKE 'migrations'")->fetchAll(PDO::FETCH_ASSOC);
38+
$found = count($result);
39+
40+
if (!$found) {
41+
say("Unable to find the migrations table in the database. Attempting to create it.");
42+
$sql = "CREATE TABLE migrations (name VARCHAR(200) DEFAULT '' PRIMARY KEY, applied_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP)";
43+
$pdo->query($sql);
44+
say("The migrations table has been created.");
45+
} else {
46+
say("The migrations table already exists.");
47+
}
48+
49+
// Run the migrations that come with this framework
50+
require_once('applyMigrations.php');
51+
52+
$sql = "SELECT COUNT(*) cnt FROM users";
53+
$usersFound = $pdo->query($sql)->fetchColumn();
54+
55+
if (!$usersFound) {
56+
$result = false;
57+
while ($result !== true) {
58+
say("No user found, creating your admin user.");
59+
$firstName = readline("First Name: ");
60+
$lastName = readline("Last Name: ");
61+
$email = readline("Email: ");
62+
$password = readline("Password: ");
63+
64+
$result = Di::getAuth()->addUser($email, $password, $firstName, $lastName);
65+
if ($result !== true) {
66+
say("That didn't work:" . Di::getAuth()->getErrorAsString($result));
67+
}
68+
}
69+
70+
say("User $firstName $lastName created with email $email");
71+
} else {
72+
say("A user has already been found, not creating another.");
73+
}

template/app/src/Config/Config.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
namespace Config;
3+
4+
use WebAppFramework\ConfigBase;
5+
6+
/**
7+
* Class Config
8+
*
9+
* @package Config
10+
*/
11+
class Config extends ConfigBase
12+
{
13+
// Where is this website?
14+
public $websiteRoot = 'http://192.168.1.19';
15+
16+
// Basic connection from PHP to a mysql database.
17+
public $databaseHost = 'localhost';
18+
public $databaseName = 'test';
19+
public $databasePort = 3306;
20+
public $databaseUsername = 'test';
21+
public $databasePassword = 'test';
22+
public $databaseConsoleCommand = 'mysql'; // Where to pipe mysql migration scripts to
23+
}

template/app/src/Config/ConfigDev.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
namespace Config;
3+
4+
/**
5+
* Class ConfigDev
6+
*
7+
* Use this class to override any configurations in the Config class that are
8+
* specific to your development environment.
9+
*
10+
* @package Config
11+
*/
12+
class ConfigDev extends Config
13+
{
14+
15+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
namespace Config;
3+
4+
/**
5+
* Class ConfigProd
6+
*
7+
* Use this class to override any configurations in the Config class that are
8+
* specific to your production environment.
9+
*
10+
* @package 0Config
11+
*/
12+
class ConfigProd extends Config
13+
{
14+
15+
}
Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
The configuration class is chosen by the environment variable in config.php in the app directory. Throughout
22
your project however you just call Config::instance()->parameterName. This allows for auto complete in the IDE.
33
Every parameter should be defined in Config and other environment dependent changes should be made in ConfigDev,
4-
ConfigProd etc.
5-
6-
Generally works like the Di.
4+
ConfigProd etc.
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<?php
2+
/**
3+
* Created by PhpStorm.
4+
* User: Tom
5+
* Date: 2/28/2016
6+
* Time: 1:14 PM
7+
*/
8+
9+
namespace Controller;
10+
11+
12+
use Config\Config;
13+
use Di\Di;
14+
use WebAppFramework\ControllerBase;
15+
use WebAppFramework\Template;
16+
17+
class AuthController extends ControllerBase
18+
{
19+
public function loginAction()
20+
{
21+
$login = Di::getAuth()->login($this->request->get('email'), $this->request->get('password'));
22+
if ($login === true) {
23+
$websiteRoot = Config::instance()->websiteRoot;
24+
header("Location: $websiteRoot/");
25+
return;
26+
}
27+
28+
// Failed :-(
29+
$template = new Template('users/loginFailed.php');
30+
$template->setVariable('error', Di::getAuth()->getErrorAsString($login));
31+
$template->render();
32+
}
33+
34+
public function logoutAction()
35+
{
36+
Di::getAuth()->logout();
37+
38+
$websiteRoot = Config::instance()->websiteRoot;
39+
header("Location: $websiteRoot/");
40+
}
41+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
/**
3+
* Created by PhpStorm.
4+
* User: Tom
5+
* Date: 2/28/2016
6+
* Time: 1:14 PM
7+
*/
8+
9+
namespace Controller;
10+
11+
12+
use Di\Di;
13+
use WebAppFramework\ControllerBase;
14+
use WebAppFramework\Template;
15+
16+
class HomeController extends ControllerBase
17+
{
18+
public function homeAction()
19+
{
20+
$template = new Template('home.php');
21+
$template->setVariable('name', $this->request->get('name', ''));
22+
$template->render();
23+
}
24+
}

0 commit comments

Comments
 (0)