GithubHelp home page GithubHelp logo

taniarascia / laconia Goto Github PK

View Code? Open in Web Editor NEW
358.0 21.0 63.0 13.85 MB

๐Ÿบ โ€Ž A minimalist MVC framework.

Home Page: https://laconia.dev

License: MIT License

PHP 53.45% JavaScript 5.04% CSS 19.50% Dockerfile 0.32% Makefile 0.18% SCSS 21.50%
php mvc oop authentication object-oriented-programming application webapp database mysql php-7

laconia's Introduction

๐Ÿบ Laconia

License: MIT

An MVC framework from scratch in PHP.

Installation

Install a local copy with the instructions below, or follow the Docker instructions.

Install Apache, MySQL, and PHP

It is assumed you already know how to install a LAMP stack. For macOS and Windows local development, I would recommend downloading MAMP for a sandboxed environment. You can set up virtual hosts as well.

If using MAMP, add MAMP to the PHP command line by adding this line to .bash_profile.

export PATH=/Applications/MAMP/bin/php/php7.2.1/bin:$PATH

Install Composer

Composer is the standard in PHP for dependency management, class autoloading, and much more.

curl -sS https://getcomposer.org/installer | php
sudo mv composer.phar /usr/local/bin/composer

Set up server

Create a virtual host called laconia.server. The server should point to the /public directory. Your httpd-vhosts.conf will look like this:

<VirtualHost *:80>
    DocumentRoot "/Users/tania/hosts/laconia/public"
    ServerName laconia.server
</VirtualHost>

Run install script

  • Run php bin/install.php in the root directory to initialize the database.
  • Run composer install to autoload classes and configuration.
  • Run npm i to install depencencies to use Sass.
  • Run npm run sass to run sass.

Copy credentials example file to credentials.

cp credentials.example.php credentials.php

Laconia is all set up and ready to use!

Docker Instructions

  • Run make init to build all containers.
  • Run make install to run the install script.

npm and sass are not integrated in Docker at the moment.

  • Run npm i to install depencencies to use Sass.
  • Run npm run sass to run sass.

Autoload classes

If you change or add a class at anytime, you'll need to re-run the autoload script to re-load the new classes.

composer dump-autoload

Project Structure

The entire program flows through /public/index.php, and the rest of the project is a directory above public.

laconia/
  .git               # Git source directory
  assets/            # Uncompiled raw SCSS
  bin/               # Command line scripts
      install.php    # Database installation script
  config/            # Database credentials, utility helpers, and other configuration
  data/              # SQL database files
  node_modules/      # Node.js front end dependencies
  docker/            # Contains Docker environment variables
  public/            # Publicly accessible files
      css/           # Compiled, ready-to-use styles
      js/            # Compiled, ready-to-use scripts
      index.php      # Main entry point for the entire application
  src/               # PHP source code
      app            # Router code
      controllers/   # Controller classes
      models/        # Model classes
      views/         # Views
  tests/             # Unit tests
  vendor/            # Composer files and 3rd party packages
  .gitignore         # Files to be ignored in the repository
  composer.json      # Composer dependency file
  composer.lock      # Composer lockfile
  docker-compose.yml # Docker configuration
  Dockerfile         # Docker configuration
  LICENSE            # MIT License file
  Makefile           # Docker instructions
  package.json       # npm dependency file
  package-lock.json  # Dependency lockfile
  README.md          # Brief documentation

Usage

Laconia is a simple list-making website. You can register an account, log in, log out, reset your password, create and edit lists, and view public profiles.

  • / - Landing page
  • /register - Register a new user
  • /login - Log in to user account
  • /dashboard - Logged in dashboard screen
  • /logout - Log out of user session
  • /forgot-password - Get a password reset link
  • /create-password - Create a new password
  • /users - View all users
  • /settings - Edit user settings
  • /lists - View lists
  • /create - Create a new list
  • /edit/:list_id - Edit an existing list
  • /:username - View public profile
  • /404 - Any not found redirects to 404.

Testing

Laconia uses PHPUnit for unit testing. Tests will go in the /tests directory. For now, here is how to run a Hello, World! script.

./vendor/bin/phpunit ./tests/HelloWorldTest

Motivation

Laconia is a personal project created by Tania Rascia to learn the fundamentals of programming and modern web development from scratch. The main goals of the project are to learn MVC (Model View Controller) architecture, the OOP (Object-Oriented Programming) paradigm, routing, authentication, security, modern development practices, and how to tie it all together to make a functional web app.

Laconia runs on PHP 7.2 and MySQL. It uses Composer to autoload classes, configuration and utility files, as well as future tests through PHPUnit. Node.js is used to compile Sass to CSS via npm scripts. The CSS framework Primitive was used for the design.

Here are some of the concepts I learned while writing this program:

  • Authentication โ€“ logging in, logging out, resetting a password, having private content/dashboard hidden from anonymous users
  • Security and validation โ€“ encrypted passwords and hashing, parameter binding with SQL, making sure users cannot be overridden, making sure no spam or empty content can go through, making sure passwords and usernames have the proper characters
  • Routing โ€“ Redirecting to URLs based on incoming request method and URI path, creating public user profiles in the root directory, creating dynamic pages based on GET requests
  • Object-oriented programming โ€“ I had never used a class in a working application before writing this app, so I learned a lot about constructors, inheritance, and abstract classes
  • Composer โ€“ I had no prior experience using Composer, so I wanted to find out why it was the standard in modern PHP development. I used it for autoloading classes and configuration.
  • Database schema โ€“ how to structure a database to relate information easily between the tables, i.e. linking lists and list items, users and user comments, etc. Sessions and Users โ€“ how to easily deal with sessions, users, and authentication.

Acknowledgements

I've used a combination of many tutorials and StackOverflow posts to create this project. These have been the most important.

Contributing

Please feel free to fork, comment, critique, or submit a pull request.

Author

License

This project is open source and available under the MIT License.

laconia's People

Contributors

kevin-mycos avatar kevin-schmitt avatar taniarascia 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  avatar  avatar

laconia's Issues

Broken link

The link to "Project Directory" is broken or may be no longer existe.

Create a basic templating system

Hi!
I can see that you have a partials dit in your views. I suggest that we refactor the viens in a way that it can support a basic templating system as you can see here.

Integrate docker compose

I think is will be interesting to integrate docker compose file, for easy install and upgrade environment.

Separate server response from controllers

Continuing on my theme of testability, another item to think about and possibly implement. Your controllers will do one of two things:

  • Echo HTML to standard output
  • Use header() to perform a redirect and exit

I would suggest that instead you:

  • Return a Laconia\WebResponse object

You can call this whatever you like, but to wire it in, I'd do this in your controller:

public function setWebResponse(Laconia\WebResponse $webResponse) {
    $this->webResponse = $webResponse;
}

I'd then modify view to inject the HTML it generates into the WebResponse (to capture HTML in a variable rather than printing it immediately, use output buffering).

The web response could look a bit like this:

namespace Laconia;

class WebResponse {
    protected $isOutput = false;
    protected $isRedirect = false;
    protected $output;
    protected $redirect;

    public function setOutput($output) {
        $this->isOutput = true;
        $this->output = $output;
    }

    public function setRedirect($redirect) {
        $this->isRedirect = true;
        $this->redirect = $redirect;
    }

    public function execute() {
        if ($this->isOutput) {
            echo $this->output;
        } elseif ($this->isRedirect) {
            header($this->redirect);
        }
    }
}

Woop! That is much better for testing. It is, specifically, better for mocking, so we can pass a fake object during testing, to see what things get called on it.

Separate SESSION array from controllers

This is similar to #2, but may need a bit of experimentation to get right.

I would start off with adding something similar to GET/POST:

protected $sessionValues = [];

public function setSessionValues(array $sessionValues) {
   $this->sessionValues = $sessionValues;
}

protected function getSessionValue($key) {
    return isset($this->getSessionValue[$key]) ? $this->getSessionValue[$key] : null;
}

You will also want to modify keys separately:

public function setSessionValue($key, $value) {
   $this->sessionValues[$key] = $value;
}

However, this array is unusual in that when you reset it, you want it to modify the $SESSION PHP var. To do that, I believe you can use "pass by reference" on the original setter, like so:

// The ampersand indicates pass by ref
// See https://stackoverflow.com/a/885
public function setSessionValues(array &$sessionValues) {

This will allow you to disconnect your controllers $SESSION too, again helping future testing. Of course, check your web app still works after making any sweeping changes.

Regex in controller.php causes an error with PHP 7.4

This really isn't an "issue" since laconia was developed for PHP 7.2, but this might help anyone considering a PHP update.

In controller.php, function validateUsername, the preg_match fails with error โ€œCompilation failed: invalid range in character class at offset 10โ€ after upgrading to PHP 7.4. This appears to be caused by the update made in PHPโ€™s implementation of PRCE2 (introduced in 7.3) that assumes the use of a dash in a character class defines a range. For the regex in controller.php, the 3rd dash isnโ€™t a range, itโ€™s a literal, so I believe the simple, backwards compatible solution is to simply escape it. I.e., instead of

if (!preg_match("/^[a-zA-Z\d-_]+$/i", $username)) {

change it to:

if (!preg_match("/^[a-zA-Z\d\-_]+$/i", $username)) {

Write some unit tests using PHPUnit

I can expand on this once the existing tickets are done - it's a "level up" target for now! ๐Ÿ˜ธ

I tend to install PHPUnit and Mockery together for this purpose. Mockery has a fluent interface to create different kinds of class mocks i.e. fake secondary classes that we can rely upon when testing a class in isolation. I believe PHPUnit has its own mocking system, but I've learned Mockery instead, and this route seems to be popular with other PHP devs.

how to run laconia in ubuntu

Hi Tania! only i what to ask you how to install Laconia in ubunutu. Im staring with php and your project it seems very interesting and i would like to look inside it. Please if you could guide me I would appreciate it.

Hi Tania

I am new for the PHP if you have any sample code for Pos system or I need to know how to write a code adding a item in php with checking existing product and items and sell the items please help me

Thank you,
Vijay

[Bug] Routing issues with nginx on Docker compose

There's an .htaccess file that does some interesting routing. In order to get laconia.dev/user to work, I made a rule that looks for username-router in the URL and redirects to the profile if it exists. I couldn't find any way to get nginx working with this setup, so maybe someone knows a better way to handle those URLs.

RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME}%  !-d
RewriteCond %{REQUEST_FILENAME}%  !-f

# Do not route static files in the public directory
RewriteRule \.(js|css|svg|gif|jpg|jpeg|png)$ -                 [L]

# Route /edit/$ to /edit?list_id=$ 
RewriteRule ^/?edit/(.*?)/?$                 /edit?list_id=$1  [L]

# Route everything else to index.php in the public directory
# Note: username-router get variable used for public user profiles
RewriteRule ^(.*)$                index.php?username-router=$1 [QSA,L]

URL not found with Apache?

I tried install Laconia using Apache, I set up the server and others (composer, npm, node.js, etc). When I type the root url (http://laconia.local) it works fine but when try to enter to register the server send: "404 - The requested URL was not found on this server."

However, when I run Laconia from php -S localhost:8888 Laconia's all pages works fine!

Debian 10, PHP 7.3, Apache/2.4.38

Password Reset is not working!

The password reset link does not seem to be working. I don't receive any e-mail when I click on the forgot password link.

Separate GET/POST array from controllers

OK, what you have so far is great work. I'm adding suggestions here as they're more editable than Reddit PMs. Feel free to do, or not do, any of these as you wish - all just food for thought.

Your controllers rely on $_GET and $_POST, which don't work in test environments, and they're global variables, so they are not very clean to work with. I would suggest something like this in your Controller:

protected $getValues = [];
protected $postValues = [];

public function setGetValues(array $getValues) {
    $this->getValues = $getValues;
}

public function setPostValues(array $postValues) {
   $this->postValues = $postValues;
}

protected function getGetValue($key) {
    return isset($this->getValues[$key]) ? $this->getValues[$key] : null;
}

protected function getPostValue($key) {
    // TODO
}

Then before you execute the controller in the index.php, you can do:

$controller->setGetValues($_GET);
$controller->setGetValues($_POST);

Of course you'll need to scan your controllers for the old global arrays and swap them for the new getters. Feel free to rename things as you wish.

When you come to unit testing, your controllers will now have nice entry points for you to inject test values.

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.