- XAMPP or similar server compatible with PHP
- node.js
- bower
npm install -g bower
- grunt
npm install -g grunt-cli
- PHP
- Note: PHP is included in XAMPP.
- SQLite3 extension required!
-
Clone this repository to your local computer.
-
Make a copy all files ending in
.examplein the/configfolder, and remove the.exampleextension so you have.phpconfig files. -
Make sure you point your DocumentRoot at the
/publicfolder. The app is initialized from theindex.phpfile in your/publicfolder. -
Start your server, whether it be XAMPP or Apache or nginx, whatever you please.
-
npm installThis makes sure all the node modules necessary to run Grunt are installed.
-
php composer.phar installRun this in the main project folder to update all the required package dependencies for the PHP app.
-
php composer.phar updateFrom time to time, you will need to run this to make sure your packages are up to date. Do it now.
-
bower installRun this before running the app to ensure that all your front-end dependencies are loaded.
-
Follow instructions for Using Database Migrations below.
-
Navigate to localhost in your browser and Psalted should load!
One clunky thing about using SQL-based relational databases is that they have fixed schemas. When you decide on a schema for your model and you set your columns/column types/restrictions, it is difficult to change.
Therefore, you need a way to track different versions of schemas you may have - you may have one version of the User table that only has a username and password and may want to add an email field. In order to do that, you would write a migration in the /migrations folder, then apply it by running bin/phpmig migrate. Since each migration will be tracked, all developers on different machines can keep track of their own migrations and update as they are able to.
Note: Sadly, SQLite does not allow you to change column names or remove columns as part of a migration. Just a sad fact of life.
-
Make sure you have a file migrations/.migrations.log; otherwise, migrations will not work. This file stores what migrations have been already run on your local version of the application. Run
touch migrations/.migrations.logfrom the app folder to generate it. -
If this is your first time, you want to begin with a fresh database. Set a path to a new empty file (e.g. psalted.sqlite) in
config/database.php, and take a look at theconfig/database.php.examplefor help. -
Make sure that when you pull in updates for the app, you check that all your database migrations are updated correctly. Run
bin/phpmig migrateto ensure this is done correctly. -
To revert database changes, run
bin/phpmig rollback. -
To write your own migration, take a look at the documentation. A note with that is to make sure that migrations do not corrupt pre-existing data. We want to enforce logical data independence.
The back-end uses the lightweight Slim Framework on top of PHP and the database is SQLite 3. The ORM used for the database and models is Paris/Idiorm.
The front-end implements JQuery Mobile as the primary framework.
The philosophy is that we want the app to be as minimal and functional as possible so we don't have to deal with as many technical issues and can focus more on features.
-
/bin
Contains executables needed for development, namely
phpmigwhich is used for database migrations. -
/bower_components
Is in main
.gitignoreso won't be cloned. Populated bybower install. Contains external plugins downloaded using bower. Packages in here can be referenced in Gruntfile. -
/config
Contains local server configuration files.
hybridauth.phpconfigures social login,database.phpconfigures what database file is being used, andphpmig.phpconfigures the database migration tool. -
/db
Stores the database(s) for the app. Contains a
.gitignorefile; you should probably add your database's path to that.gitignoreso that a massive file isn't pushed to the repository. -
/migrations
Contains
.migrations.log, a text file which keeps track of what migrations have been run on the local copy of the app. In addition,phpmigmigrations are written in this folder. -
/models
Contains Paris model files. When you need a new model to be used in the app, you'll need to add a file here, even if it's just an empty class.
-
/node_modules
In
.gitignore. Used to manage node_modules that would be used with Browserify, as well as modules used to help Grunt run. -
/public
-
/css
Stores JQuery Mobile CSS file and also our default
style.cssfile. DO NOT directly editstyle.css, it is compiled using Less from elsewhere. -
/hybridauth
Stores hybridauth endpoint page, probably never needs to be touched.
-
/img
Store image assets here.
-
/js
Stores Browserify files. DO NOT directly edit files in here or include files, do it using the Gruntfile and compile it into the
main.jsorlib.jsbundles. -
index.phpThis is the main app file for Slim. App level configurations can be done here.
-
-
/public_src
-
/less
Our styles are written here, compiled later into
/public/style.css. -
/libs
For either internally developed front-end libraries or external front-end libraries that cannot be downloaded and used through Bower or npm.
-
/main
Directory structure mirrors
/views. Each script will go along with a view according to the script structure.
-
-
/routes
Slim routes are written here. They are split up by first-level URLs. e.g. if the URL is
/groupsor/groups/group_name, then the route should be ingroups.php. -
/vendor
In
.gitignore. Used to manage PHP packages and libraries downloaded from Composer. -
/views
Views to be rendered in the routes are stored here. The directory is organized by the relevant model, not the route - if you are dealing with songs, put it in the
/songsfolder. If you are dealing with setlists, place it in the/setlistsfolder even though the route that is using it will begroups.phpbecause the URL is/groups/group_name/setlists.
-
Composer, Packagist, and Back-end Package Management
PHP libraries to be used for Slim and the back-end are from Composer (http://getcomposer.org). Using it is fairly straightforward,
composer.jsonstores packages we need andphp composer.phar updatemakes sure that we have the correct packages. -
CoffeeScript
CoffeeScript is just a more legible syntax for JavaScript. Read about it here. We use this for all our front-end scripts.
-
Scripts are linked to their respective views in two ways:
-
The
/public_src/mainfolder mirrors the/viewsfolder, meaning that a .coffee or .js file written in/public_src/main/songswill correspond to the view in/views/songs. -
The script uses JQuery Mobile's
pageinitevent. Since all the scripts are eventually bundled into one file, we distinguish which script runs on which page using thepageinitevent. Here's an example:$ = require('jquery') $.mobile = require('jquery-mobile') $(document).delegate "#admin-groups", "pageinit", -> # Your code goes here
The
#admin-groupsis the page id, which is formatted #directory-filename. That is, the/public_src/main/songs/view.coffeeshould have a page-id#songs-view.
-
-
Grunt, Browserify, and Gruntfile.coffee
Perhaps the most confusing part of development is going to be dealing with Browserify. What it does is that it allows us to use CommonJS-style
requirecalls to manage dependencies on the front-end, so that our code doesn't get cluttered with global variables and libraries that are included with 50 script tags on our pages.We essentially just load two scripts,
lib.js, which contains external libraries that will be frequently used (like JQuery or JQuery Mobile), andmain.js, which contains all our front-end scripts mashed into one file. The philosophy for that is in a blogpost.The Browserify configuration is located in
Gruntfile.coffee. It will automatically take care of most things - one thing that you want to do is that when you install an external front-end package, you probably want to link to it underbrowserify:mains:aliasin the config so you can have a convenient shortcut. That is, if your file is inbower_components/my_library/thiscrazyfilename.min.beta-5.19.x.js, you probably want to alias it to simply bemy_libraryso you can easily callrequire('my_library')when importing it. More details here. -
Bower, NPM and Front-end Package Management
Front-end packages can be downloaded in three ways, but there's a catch so make sure to read the notes on each:
-
If you download a package via Bower, alias the script that you need into the Browserify config in the Gruntfile. Many front-end packages, however, do not include the distributable script (meaning you'd have to manually compile it), so in that case it might be easier just to download the
.jsfile and go with option 3 of manually downloading it into/public_src/libsand then aliasing it in the Gruntfile.Even if you do have a script from something installed via Bower, make sure it is CommonJS compatible. If you open up the script and there is something like:
if (typeof exports === "object" && exports) { module.exports = factory; }
That is a good sign. If not, you can either shim it in the Gruntfile's configuration, or you may want to just manually add it in and then go with option 3 again.
-
Same deal as Bower above, pretty much. Some good package authors will make CommonJS compatible packages for both the front-end and back-end, so if that's the case you're in luck if you download your package from npm because you won't even need to alias it, you can just directly require the package name from NPM and Browserify will load it for you!
-
Manually downloaded into
/public_src/libs.You want to alias whatever manually downloaded files you have in the Gruntfile. Read the instructions under the Bower section in point 1 because the same things apply about CommonJS.
-
-
LESS is used to write simpler CSS. We write all our styles into
/public_src/lessand it will automatically compile into/public/css/style.csswhengrunt watchis running. -
grunt watchSo after the lengthy explanations above, we need to make sure this is running at all times while developing in a terminal somewhere.
This makes sure all your front-end scripts compile correctly into their respective bundles for the browser. If you don't do this, pages will load with outdated javascript because you didn't compile! For a one-time bundle or if you are updating the external libraries file, just run
grunt browserify.This will also watch changes to the LESS file and compile the CSS accordingly.
Upon setup, if PDFs saved from the website are invalid PDFs, try opening them in a text editor and viewing the raw content. If it shows an HTML document, one possible reason could be that permissions are not set up correctly for your web server to access the directories in your repository. For example, on Linux with nginx running with user www-data which belongs to user group www-data, running chgrp -R www-data <repository dir> may help.