Joiner is a project mainly written in PHP, it's free.
$adapter = Joiner::setAdapter('default', 'sqlite::memory:');
$schema = Joiner::getAdapter()->getSchema();
$schema->setTable('prefix_users', 'User');
$schema->setTable('prefix_pictures', 'Picture');
$schema->setRelation('Picture.user_id', 'User.id');
$users = Joiner::getAdapter()->getTable('User')
->where('User.verified = ? AND User.id = ?', array('y', $_GET['id']))
->join('Picture p')->addSelect('p.path AS user_picture')
->groupBy('User.id');
/* Will produce:
SELECT prefix_users.*, p.path AS user_picture FROM prefix_users AS User
INNER JOIN prefix_pictures AS p ON User.id = p.user_id
WHERE User.verified = 'y' AND User.id = '1'
GROUP BY User.id */
Now $users is an instance of Joiner_Table, but can be iterated or accessed like an array to connect and fetch the data from the database.
if (count($users)) {
echo $users[0]->name;
foreach ($users as $user) {
// Relations can be helpful in a row contest too:
$user_pictures = $user->getRelated('Picture');
/* Will produce:
SELECT Picture.* FROM prefix_pictures AS Picture INNER JOIN
prefix_users AS User ON User.id = Picture.user_id
WHERE User.id = '1' */
}
}
Another thing we can do is to add some methods to the records of any table. We just need to create a class with the same name of the table alias.
class Picture extends Joiner_Model
{
function getImageTag() {
return sprintf('<img src="%s" width="%s" height="%s" alt="%s" />'
$this->path, $this->width, $this->height, $this->title);
}
}
$picture = $adapter->getTable('Picture')->limit(1);
echo $picture[0]->getImageTag();
Joiner don't provide a way to add methods to the table objects, but using static methods in the models is a nice workaround to me.
class User extends Joiner_Model
{
static function addActiveQuery($table = NULL) {
if (!$table) {
$table = Joiner::getAdapter()->getTable('User u');
}
return $table->andWhere('u.verified = ?', 'y');
}
}
// Now we can refactor the snippet above
$users = User::addActiveQuery()->andWhere('u.id = ?', $_GET['id'])
->join('Picture p')->addSelect('p.path AS user_picture')
->groupBy('u.id');
Now let's imagine that the ralation within users and photos is many to many. We can just redefine the previous schema in this way:
$schema = Joiner::getAdapter()->getSchema();
$schema->setTable('prefix_users', 'User');
$schema->setTable('prefix_pictures', 'Picture');
$schema->setTable('prefix_user_picture', 'UserPicture');
$schema->setRelation('UserPicture.user_id', 'User.id');
$schema->setRelation('UserPicture.picture_id', 'Picture.id');
$schema->setCrossReference('User', 'UserPicture', 'Picture');
That's all, we can execure all the examples above without any changes.
Joiner doesn't provide a way to paginate resultset but instead provide an inteface for the Zend Framework Paginator. Below a small introdution about how to paginate results usign Joiner and the Zend Paginator.
require_once 'Zend/Paginator.php';
require_once 'Zend/Paginator/Adapter/Interface.php';
require_once 'Joiner/ZendPaginatorAdapter.php';
$items = Joiner::getAdapter()->getTable('Item')->where('a = ?', 'b');
$paginator = new Zend_Paginator(Joiner_ZendPaginatorAdapter($items));
$paginator->setCurrentPageNumber(1);
$paginator->setItemCountPerPage(10);
$paginator->setPageRange(10);
if (count($paginator)) {
foreach ($paginator as $record) {
$record instanceOf Joiner_Model; // true
}
}
<?php
$pages = $paginator->getPages();
?>
<?php if ($pages->pageCount): ?>
<div class="paginationControl">
<!-- Previous page link -->
<?php if (isset($pages->previous)): ?>
<a href="?page=<?php echo $pages->previous); ?>">
< Previous
</a> |
<?php else: ?>
<span class="disabled">< Previous</span> |
<?php endif; ?>
<!-- Numbered page links -->
<?php foreach ($pages->pagesInRange as $page): ?>
<?php if ($page != $pages->current): ?>
<a href="?page=<?php echo $page); ?>">
<?php echo $page; ?>
</a> |
<?php else: ?>
<?php echo $page; ?> |
<?php endif; ?>
<?php endforeach; ?>
<!-- Next page link -->
<?php if (isset($pages->next)): ?>
<a href="?page=<?php echo $pages->next); ?>">
Next >
</a>
<?php else: ?>
<span class="disabled">Next ></span>
<?php endif; ?>
</div>
<?php endif; ?>
Read more about the Zend Paginator at http://framework.zend.com/manual/en/zend.paginator.html
// Get an adapter
$adapter = Joiner::getAdapter();
// Enable logging
$adapter->enableLogging(true);
// Do something to log
$adapter->query('SELECT 1');
// Dump the log in an HTML table:
echo $adapter->getLog();
// ... or get the log as array:
foreach ($adapter->getLog()->toArray() as $log) {
$function_call = $log[0];
$arguments = $log[1];
$time_spent_in_seconds = $log[2];
}