qDev stands for "Quick Development". It's an Open Source Object-Oriented Web Application Framework written in PHP.
It simplifies repetitive tasks, hoping to make developer's life easier.
The qDev Framework is distributed under the New BSD Licence.
This framework was written by Alan Reid.
It's currently in a very early stage of development, but you may contact me if you have any questions, suggestions or if want to contribute.
.
./application/ - All your application's stuff goes here
./application/config/ - Your Settings
./application/Controllers/ - Your Controllers
./application/Library/ - Your Library classes
./application/models/ - Your Models
./application/public/ - This is the only folder the world should have access to
./application/temp/ - Temporary data
./application/views/ - Your views
./qDev/ - Frameworks folder
./qDev/Library/ - qDev's Library
./qDev/Library/Smarty - Smarty Template Engine
./ReadMe.html - Wohoo this file! :)
./ToDo.html - To do stuff
Alias / "/var/www/myapp/application/public"
<Directory "/var/www/myapp/application/public">
AllowOverride All
Options FollowSymLinks MultiViews Indexes
Order allow,deny
Allow from all
</Directory>
qDev implements the Model-View-Controller pattern.
Model:
qDev's implementation of this layer is pretty simple. It's just a persistency layer between the Controller and the Database.
View:
Views are the presentation layer. Each view is a HTML template. qDev uses Smarty's Template Engine by default.
Controller:
These are in charge of doing your applications business logic. This is where you import libraries and do all your crazy stuff :)
Controllers are in charge of doing your application's business logic.
Here's where you load all the necessary libraries for your application to work.
A simple Controller looks like this:
IndexController extends qDev_Controller
{
public function indexAction()
{
$company = $this->company->get(34);
...
}
public function editAction($id)
{
$data = $this->request->post;
$company = $this->company->update($data, $id);
...
}
}
qDev has a built-in Router class that automagically loads a Controller and executes the desired method (depending on the URL).
Let's see some examples:
http://myapp.com/
IndexController->indexAction()
http://myapp.com/index
IndexController->indexAction()
http://myapp.com/index/index
IndexController->indexAction()
http://myapp.com/index/index/something
IndexController->indexAction(something)
http://myapp.com/contacts/edit/43
ContactsController->editAction(43)
http://myapp.com/contacts/group/43/55
ContactsController->groupAction(43, 55)
And so on...
If you want a Controller method to be accessible for the Router, all you have to do is declare it public and append "Action" to its name.
class IndexController extends qDev_Controller {
public function editAction($contactid) {
}
}
This is the presentation layer.
qDev works with the Smarty template engine by default. You may want to take a look at Smarty's documentation
You may disable it or use other template engine if you want (I'm working to make this easier, without hacking).
A view is basically a HTML file (or just a fragment). You can assign values to replacement variables from your Controllers and include other templates as well.
From the Controllers side, all Smarty functions are available under the view method.
IndexController extends qDev_Controller
{
public function indexAction()
{
$company = $this->company->get(34);
$this->view->assign('company', $company);
$this->view->assign('content', 'company.phtml');
}
}
And the template "company.phtml" would look like something like this:
{include file="header.phtml"}
<div class="results">
{foreach from=$company item=value key=title}
<strong>{$title}:</strong> {$value}
{/foreach}
</div>
{include file="footer.phtml"}
The Layout template is the main template, in which the content is filled.
For instance, your "company.phtml" template would be loaded inside this layout template.
qDev leaves the $_GET and $_POST global variables untouched (you can use them normally).
If you want them to be sanitized (to avoid XSS attacks), all you have to do is use the Request Library:
$username = $this->request->post['username'];
Loading classes from the Library is very easy, and it works the same way for both, qDev's Library and your own.
If you're in a Controller, there are two ways of loading a class from the Library:
$this->benchmark->start('test');
$this->load('benchmark');
$this->benchmark->start('test');
$this->load('bm1', 'benchmark');
$this->load('bm2', 'benchmark');
$this->bm1->start('test');
$this->bm2->start('test'); // Different instance
The session is created by loading the session Library. You will then have access to the stored data.
// Accessing value
$userid = $this->session->userid;
// Storing value
$this->session->username = $username;
qDev includes a small benchmarking Library to help you optimize your applications. It allows you to test multiple times before showing the results and it includes the time difference between start and stop (in seconds) and the memory usage in that period (in kb).
$this->benchmark->start('test1');
for($i = 0; $i < 10000; $i++) {
continue;
}
$this->benchmark->stop('test1');
$this->benchmark->start('test2');
for($i = 0; $i < 1000000; $i++) {
continue;
}
$this->benchmark->stop('test2');
// Get a single result
$test2 = $this->benchmark->get('test2');
// Get all results
$all = $this->benchmark->getAll();
This Library is an extension of PHPs MySQLi class. It adds some functionallity, like insert, update, delete, fetchAll.
It logs all queries made and integrates to qDev's error handling Library.
qDev's Model is a simple layer that interacts with the database.
$this->load('model');
$this->model->setTable('users')
->setPrimaryKey('userid');
->setFields(array(
'userid',
'username',
'firstname',
'lastname',
'lastlogin'
));
// Create an entry
$userid = $this->model->create(array(
'username' => 'john',
'firstname' => 'John',
'lastname' => 'Doe'
));
// Update an entry
$this->model->update(array(
'username' => 'doe',
'lastlogin' => time()
), array(
'userid' => $userid
));
// Read an entry
$this->model->get(array(
'username',
'firstname,
'lastname'
), array(
'userid' => $userid
));
// Delete an entry
$this->model->delete(array('userid' => $userid));
If we define a Primary Key, we can spare the condition array and do this (works for all methods):
$this->model->delete($userid);
Of course, if you are going to use these more often, it would be useful define models and use them.
Simply add a class to the "models" folder.
Remember:
// Customer Model
class CustomerModel extends qDev_Model
{
public function init()
{
$this->setTable('customers')
->setPrimaryKey('customerid');
->setFields(array(
'userid',
'username',
'firstname',
'lastname',
'lastlogin'
));
parent::init();
}
...
}
You can also define relationships between tables. Doing so, will allow qDev to create the necesary joins for itself.
// Invoice Model
class InvoiceModel extends qDev_Model
{
public $table = 'invoices',
$primaryKey = 'invoiceid',
$relations = array(
'customerid' => array( // Foreign key
'Customer' => 'customerid', // Parent Model class name => Parent key
)
),
$fields = array(
'invoiceid',
'description',
'customerid',
'doctype',
'docno',
'billtype',
'totalamount',
'netamount',
'tax',
'taxtype',
'billingdate',
'billduedate'
);
}
}
From your controller, you will have access to other tables data, joined by the Foreign keys you specify.
IndexController extends qDev_Controller
{
public function indexAction()
{
$invoice = $this->invoice->get(31);
print_r($invoice);
}
}
stdClass Object
(
[invoiceid] => 31
[description] => Test
[customerid] => 1
[doctype] => 80
[docno] => 20345101293
[billtype] => 1
[totalamount] => 1210.0000
[netamount] => 1000.0000
[tax] => 210.0000
[taxtype] => 2
[billingdate] => 2010-08-31 00:00:00
[billduedate] => 2010-09-30 00:00:00
[customers_customerid] => 1
[customers_company] => Test SA
[customers_cuit] => 12123456781
[customers_address] => Av. del Libertador 1123
[customers_zipcode] => 2345
[customers_city] => Capital Federal
[customers_province] => Buenos Aires
[customers_country] => Argentina
[customers_userid] => 1
)
Simply add a class to the "Library" folder.
Remember:
You can even extend other libraries to make your life easier, to enhace them or changing default behavior by overwriting them.
// Company Library
class Session exends qDev_Session
{
public function init() {
$this->session->joindate = time();
parent::init();
}
public function foo() {
return;
}
...
}
Simply create a class in qDevs "Library" folder.
In case your implementation requires more than one class, you can create a folder with the main classes name and put all other related classes together.
Remember: