SkillAgentSearch skills...

Marcel

The PHP 5.4 MVC with Shoes On: ActiveRecord, User/Session, Generators, SCSS, (Twitter Bootstrap) Integration, Workers, Cron Management, Image Manipulation, Caching, Git Management, Mail & Mail Parsing, OCR, Scraping, Selenium, Mustache, Markdown, Phone & Text Messaging, WebSockets, BitTorrent and much more!

Install / Use

/learn @dancrew32/Marcel
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

Marcel

The MVC with Shoes On

Marcel

Contents stable

Contents unstable

Contents future

  • USPS
  • Geolocation
  • Stocks
  • Cart
    • Stripe
  • FFMPEG
  • Waveform Generation
  • Geometry
  • Vimeo/Youtube
  • Instagram
  • Facebook
  • Twitter
  • Bitcoin
  • Travis CI
  • RSS
  • Emoji
  • Color Manipulation
  • IRC/Jabber
  • Face Detection
  • AWS
  • App Engine

Requirements

  • PHP 5.4
  • MySQL 5.5
  • Apache 2.2
  • Ruby Gems

I only have PHP 5.3

C'mon! Upgrading is easy:

sudo apt-get install python-software-properties
sudo add-apt-repository ppa:ondrej/php5
sudo apt-get update
sudo apt-get upgrade
# To update APC (if you use that instead of x-cache)
# sudo pecl install apc

Install

Clone and run the db init wizard:

git clone git@github.com:dancrew32/marcel.git site
cd site
git submodule update
php script/db_init.php
chmod 777 -R tmp .git
chmod 777 marcel vendor .gitmodules
cat config/api.php.example > config/api.php 

After install, it will prompt you to seed the database with defaults and create your first user. You should also set your public/index.php and BASE_URL.

VirtualHost Setup

<VirtualHost *:80>
	ServerName site.com
	DocumentRoot /var/www/site/public
	SetEnv ENV "DEV" # or "LIVE"
</VirtualHost>

# SSL Version
<VirtualHost *:443>
	ServerName site.com
	DocumentRoot /var/www/site/public
	SSLEngine on
	SSLCertificateFile /path/to/your.crt
	SSLCertificateKeyFile /path/to/your.key
</VirtualHost>

Scripts

Marcel has a ton of scripts available to automate development.

Just run ./m <sitename> (so maybe ./m marcel for site/marcel) from the root directory to get a menu of scripts to run!

When you're comfortable with the list of scripts you have, use the search shortcut to immediately run that script ./m <site> <search> (so maybe ./m <site> dbdump to run php site/<site>/script/db_dump.php).

Every script is an easy to use interactive wizard:

Wizards & Scripts

Wizard | Script Description --- | --- php site/marcel/script/gen_controller.php | Controller php site/marcel/script/gen_model.php | Model php site/marcel/script/gen_view.php | View php site/marcel/script/gen_js_class.php | JavaScript Module php site/marcel/script/gen_script.php | Script/Cron php site/marcel/script/db_init.php | DB initialization (see Install) php site/marcel/script/db_create_mysql_user.php | Create a new MySQL user with permissions to only this DB_NAME php site/marcel/script/db_dump.php | DB dump in db/dump php site/marcel/script/db_restore.php | DB restore from db/dump php site/marcel/script/db_schema_apply.php | DB apply a schema in from db/schema php site/marcel/script/db_schema_update.php | DB update all schemas in from db/schema php site/marcel/script/create_user.php | Create Users (e.g. Create your first User with role of admin) php site/marcel/script/cron.base.php | Run each Cron_Job if Cron_Job->frequency matches time() and is active php site/marcel/script/scss_watch.php | Run compass watch as daemon to watch SCSS php site/marcel/script/worker.php | Start a Worker server php site/marcel/script/vim.php | Start an Interactive Vim eval session php site/marcel/script/fake_users.php | Create 250 fake Users with role of user

Routing

In routes.php, we send url $_SERVER['REQUEST_URI'] preg_matches to a specified method in a controller.

By default, routing is simple, but you may increase the complexity if you would like HTTP method granularity and/or auth class permissions handled at the router (instead of the controller).

You may capture parameters using regular expressions with named subpatterns e.g. '/(?P<word>\w+)/(?P<digit>\d+)' would match /blogs/2.

Take a look at class/route.php to see all of the possibilities.

Route Keys

Key | Description --- | --- c | Controller required m | Method required l | Layout (foo would be view/layout/foo.php) auth | Authorization Feature->slug via class/auth.php to gate access with name | Unique name for this route (see route::get($name, $params) useful when URL paths change) section | Name for grouping routes together (e.g. Portfolio) (see route::in_sections(['A', 'B'])) http| for nested [REST](https://en.wikipedia.org/wiki/Representational_state_transfer) routing (e.g.get, post, put, delete) nodb| iftrue`, skip any database connections for this execution

Example Route Implementation

<?
route::$routes = [

	# Site base url leads to controller_yours::foo
	'/' => ['c' => 'yours', 'm' => 'foo'],


	# Capture page id, name capture "id" with (?P<capturename>regexp) syntax
	'/page/(?P<id>\d+)' => ['c' => 'yours', 'm' => 'test'],


	# HTTP method-specific (Optional)
	'/http' => [
		'http' => [
			'get'    => [ 'c' => 'http_test', 'm' => 'get' ],
			'post'   => [ 'c' => 'http_test', 'm' => 'post' ],
			'put'    => [ 'c' => 'http_test', 'm' => 'put' ],
			'delete' => [ 'c' => 'http_test', 'm' => 'delete' ],
		],
	],

	
	# Skip Database (`nodb` avoids database & user session initialization)
	'/i' => [ 'c' => 'image', 'm' => 'process', 'nodb' => true, 'name' => "Image Process" ],

	
	# Auth (optional)
	'/auth-test-simple' => [ 
		'c' => 'common', 'm' => 'auth_test',
		'auth' => ['feature_name'], # only users who can do "feature_name"
	],
	'/auth-test-complex' => [ 
		'http' => [
			'get' => [
				'c' => 'common', 'm' => 'auth_test',
				'auth' => ['thing_a'], # only "thing_a" feature-allowed users may GET
			],
			'post' => [
				'c' => 'common', 'm' => 'auth_test',
				'auth' => ['thing_b'], # only "thing_b" feature-allowed users may POST
			],
		],
		'auth' => ['thing_c'], # "thing_c" may GET and POST
	],


	# Named-Routes & Sections (optional)
	'/changes-frequently' =>
		[ 'c' => 'thing' => 'm' => 'index', 'name' => 'Things Home', 'section' => 'Things' ],
		# route::get('Things Home') 
		#   returns '/changes-frequently'

	'/changes-as-well(?:/*)(?P<url_slug>\d+)' =>
		[ 'c' => 'thing' => 'm' => 'secondary', 'name' => 'Things Secondary', 'section' => 'Things' ],
		# route::get('Things Secondary', ['url_slug' => 'true-story']) 
		#   returns '/changes-as-well/true-story'
		# route::get('Things Secondary', ['url_slug' => 'true-story', 'foo' => 'bar']) 
		#   returns '/changes-as-well/true-story?foo=bar'

];

Models (M)

Uses PHPActiveRecord (see Basic CRUD to learn more). Get started with a new Model using the php script/gen_model.php Script.

Simple Model Example

<?
class Thing extends model {
	static $table_name = 'things';
}

# Create: http://www.phpactiverecord.org/projects/main/wiki/Basic_CRUD#create
$t = new Thing;
$t->stuff = "raisin";
$t->save();

# Read: http://www.phpactiverecord.org/projects/main/wiki/Finders
$b = Thing::find(1);
echo $b->stuff; # "raisin"

# Update: http://www.phpactiverecord.org/projects/main/wiki/Basic_CRUD#update
$b->stuff = "dorito";
$b->save();

# Destroy: http://www.phpactiverecord.org/projects/main/wiki/Basic_CRUD#delete
$b->delete();

Complex Model Example

<?
class Stuff extends model {
	static $table_name = 'stuff';


/*
 * RELATIONSHIPS
 * Read More: http://www.phpactiverecord.org/projects/main/wiki/Associations
 */

	# `thing_id` in `stuff_types` table: $stuff->type (Stuff_Type object)
	static $has_one = [
		[ 'type', 'class_name' => 'Stuff_Type' ], 
	];

	# `thing_id` in `owners` table: $stuff->owners (collection of Owner objects)
	static $has_many = [
		[ 'owners', 'class_name' => 'Owner' ], 
	];

	# `thing_id` in `stuff` table: $stuff->thing (Thing object)
	static $belongs_to = [
		[ 'thing', 'class_name' => 'Thing' ],
	];


/*
 * VALIDATION
 * Read More: http://www.phpactiverecord.org/projects/main/wiki/Validations
 */
	# Existence
	static $validates_presence_of = [
		['name', 
			'message' => 'must be present!'], # "Name must be present!"
	];

	# Length
	static $validates_size_of = [
		# Exact
		['field_a', 
			'is'      => 42, 
			'message' => 'must be exactly 42 chars'], # "Field_a must be exactly 42 chars"

		# Minimum
		['field_b', 
			'minimum'   => 9, 
			'too_short' => 'must be at least 9 characters long'],

		# Maximum
		['field_c', 
			'maximum'  => 20, 
			'too_long' => 'is too long!'],

		# Min/Max
		['field_d', 
			'within'    => [5, 10],
			'too_short' => 'must be longer than 5 (less than 10)',
	

Related Skills

View on GitHub
GitHub Stars5
CategoryDevelopment
Updated11y ago
Forks0

Languages

JavaScript

Security Score

55/100

Audited on Jun 30, 2014

No findings