Created
October 28, 2011 04:26
-
-
Save k-holy/1321620 to your computer and use it in GitHub Desktop.
Silex PhpTalServiceProvider + RedBean
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head metal:define-macro="head"> | |
<meta charset="UTF-8" /> | |
<link rel="stylesheet" media="screen" href="/css/base.css" /> | |
<script src="/js/jquery-1.6.2.min.js"></script> | |
<tal:block metal:define-slot="head-extra"></tal:block> | |
<title tal:content="title">Title</title> | |
</head> | |
<body metal:define-macro="body"> | |
<div id="header"> | |
<h1>Silex + RedBeanPHP + PHPTAL CRUD Examples</h1> | |
</div> | |
<div id="container"> | |
<div id="menu" metal:define-slot="menu"> | |
<ul> | |
<li><a href="/profiles/">人物一覧</a></li> | |
<li><a href="/profiles/register">人物登録</a></li> | |
</ul> | |
</div> | |
<h2 tal:content="title">画面名</h2> | |
<p class="message" tal:condition="exists:message" tal:content="message">Flashメッセージ</p> | |
<div id="main" metal:define-slot="main"> | |
メイン | |
</div> | |
</div> | |
<div id="footer"> | |
Copyright © k-holy <[email protected]> | |
</div> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* PHP versions 5 | |
* | |
* @copyright 2011 k-holy <[email protected]> | |
* @author [email protected] | |
* @license http://www.opensource.org/licenses/mit-license.php The MIT License (MIT) | |
*/ | |
namespace Keizu; | |
require_once realpath(__DIR__ . '/silex.phar'); | |
const INTERNAL_ENCODING = 'UTF-8'; | |
const CSRF_TOKEN_NAME = 'AEg9GE5#4ZyPY$fd'; | |
use Silex\Application; | |
use Silex\Provider\SessionServiceProvider; | |
use Symfony\Component\HttpFoundation\Request; | |
use Symfony\Component\HttpFoundation\Response; | |
use Holy\Silex\Provider\PhpTalServiceProvider; | |
use Holy\Silex\Provider\RedBeanServiceProvider; | |
$app = new Application(); | |
$app['debug'] = true; | |
$app['autoloader']->registerNamespace('Holy' , realpath(__DIR__ . '/vendor/k-holy/src')); | |
$app->register(new SessionServiceProvider()); | |
$app->register(new PhpTalServiceProvider(), array( | |
'phptal.class_path' => realpath(__DIR__ . '/vendor/phptal'), | |
'phptal.options' => array( | |
'templateRepository' => realpath(__DIR__ . '/views'), | |
), | |
)); | |
$app->register(new RedBeanServiceProvider(), array( | |
'db.redbean.class_path' => realpath(__DIR__ . '/vendor/redbean'), | |
'db.options' => array( | |
'dsn' => sprintf('sqlite:%s', realpath(__DIR__ . '/app/data/keizu.sqlite')), | |
), | |
)); | |
$app['db']->debug(true); | |
// Error handler | |
$app->error(function(\Exception $e, $code) use ($app) { | |
$message = 'Internal Server Error'; | |
if ($e instanceof \Symfony\Component\HttpKernel\Exception\HttpExceptionInterface) { | |
switch ($code) { | |
case 403: | |
$message = 'Forbidden'; | |
break; | |
case 404: | |
$message = 'NotFound'; | |
break; | |
case 405: | |
$message = 'Method Not Allowed'; | |
break; | |
} | |
} | |
$app['phptal']->set('message', $message); | |
$app['phptal']->set('error', ($app['debug']) ? $e->__toString() : null); | |
$app['phptal']->set('title', 'エラー'); | |
return new Response($app['phptal']->setTemplate('error.html')->execute(), | |
(isset($code)) ? $code : 500); | |
}); | |
// Before filter | |
$app->before(function(Request $request) use($app) { | |
if ($app['session']->hasFlash('message')) { | |
$app['phptal']->set('message', $app['session']->getFlash('message')); | |
$app['session']->removeFlash('message'); | |
} | |
}); | |
//---------------------------------------------------------------------------- | |
// 人物一覧 | |
//---------------------------------------------------------------------------- | |
$app->get('/profiles/', function() use ($app) { | |
$app['phptal']->set('items', $app['db']->find('profiles', ' 1 ORDER BY id')); | |
$app['phptal']->set('title', '人物一覧'); | |
return $app['phptal']->setTemplate('profiles/index.html')->execute(); | |
}); | |
//---------------------------------------------------------------------------- | |
// フィールド、バリデータ定義 | |
//---------------------------------------------------------------------------- | |
$fields = array( | |
'name' => '名前', | |
'notes' => '備考', | |
); | |
$validator = function($bean) use ($fields) { | |
$errors = array(); | |
foreach ($fields as $field => $label) { | |
switch ($field) { | |
case 'name': | |
if (!isset($bean->{$field}) || 0 === strlen($bean->{$field})) { | |
$errors[$field] = sprintf('%sを入力してください', $label); | |
} elseif (20 < mb_strlen($bean->{$field}, INTERNAL_ENCODING)) { | |
$errors[$field] = sprintf('%sを20文字以内で入力してください', $label); | |
} | |
break; | |
} | |
} | |
return (empty($errors)) ? true : $errors; | |
}; | |
//---------------------------------------------------------------------------- | |
// 人物登録 | |
//---------------------------------------------------------------------------- | |
$app->match('/profiles/register', function() use ($app, $fields, $validator) { | |
$bean = $app['db']->dispense('profiles'); | |
switch($app['request']->getMethod()) { | |
case 'POST': | |
$bean->import($app['request']->request->all(), array_keys($fields)); | |
if ($app['request']->get(CSRF_TOKEN_NAME) === $app['session']->getId()) { | |
if (true === ($errors = $validator($bean))) { | |
$app['db']->store($bean); | |
$app['session']->setFlash('message', '人物情報を登録しました。'); | |
return $app->redirect('/profiles/', 302); | |
} | |
} | |
$app['phptal']->set('errors', $errors); | |
break; | |
} | |
$app['phptal']->set('token', array( | |
'name' => CSRF_TOKEN_NAME, | |
'value' => $app['session']->getId(), | |
)); | |
$app['phptal']->set('data' , $bean); | |
$app['phptal']->set('title', '人物登録'); | |
return $app['phptal']->setTemplate('profiles/edit.html')->execute(); | |
}); | |
//---------------------------------------------------------------------------- | |
// 人物編集 | |
//---------------------------------------------------------------------------- | |
$app->match('/profiles/{id}/modify', function($id) use ($app, $fields, $validator) { | |
$bean = $app['db']->load('profiles', $id); | |
switch($app['request']->getMethod()) { | |
case 'POST': | |
$bean->import($app['request']->request->all(), array_keys($fields)); | |
if ($app['request']->get(CSRF_TOKEN_NAME) === $app['session']->getId()) { | |
if (true === ($errors = $validator($bean))) { | |
$app['db']->store($bean); | |
$app['session']->setFlash('message', '人物情報を更新しました。'); | |
return $app->redirect('/profiles/', 302); | |
} | |
} | |
$app['phptal']->set('errors', $errors); | |
break; | |
} | |
$app['phptal']->set('token', array( | |
'name' => CSRF_TOKEN_NAME, | |
'value' => $app['session']->getId(), | |
)); | |
$app['phptal']->set('data' , $bean); | |
$app['phptal']->set('title', '人物編集'); | |
return $app['phptal']->setTemplate('profiles/edit.html')->execute(); | |
})->assert('id', '\d+'); | |
//---------------------------------------------------------------------------- | |
// 人物削除 | |
//---------------------------------------------------------------------------- | |
$app->match('/profiles/{id}/delete', function($id) use ($app) { | |
$bean = $app['db']->load('profiles', $id); | |
switch($app['request']->getMethod()) { | |
case 'POST': | |
if ($app['request']->get(CSRF_TOKEN_NAME) === $app['session']->getId()) { | |
$app['db']->trash($bean); | |
$app['session']->setFlash('message', '人物情報を削除しました。'); | |
return $app->redirect('/profiles/', 302); | |
} | |
break; | |
} | |
$app['phptal']->set('token', array( | |
'name' => CSRF_TOKEN_NAME, | |
'value' => $app['session']->getId(), | |
)); | |
$app['phptal']->set('data' , $bean); | |
$app['phptal']->set('title', '人物削除'); | |
return $app['phptal']->setTemplate('profiles/delete.html')->execute(); | |
})->assert('id', '\d+'); | |
$app->run(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* PHP versions 5 | |
* | |
* @copyright 2011 k-holy <[email protected]> | |
* @author [email protected] | |
* @license http://www.opensource.org/licenses/mit-license.php The MIT License (MIT) | |
*/ | |
namespace Holy\Silex\Provider; | |
use Silex\Application; | |
use Silex\ServiceProviderInterface; | |
class PhpTalServiceProvider implements ServiceProviderInterface | |
{ | |
public function register(Application $app) | |
{ | |
$app['phptal'] = $app->share(function() use ($app) { | |
$phptal = new \PHPTAL(); | |
$app['phptal.options'] = array_replace( | |
array( | |
'outputMode' => null, | |
'encoding' => null, | |
'templateRepository' => null, | |
'phpCodeDestination' => null, | |
'phpCodeExtension' => null, | |
'cacheLifetime' => null, | |
), | |
(isset($app['phptal.options'])) ? $app['phptal.options'] : array() | |
); | |
foreach ($app['phptal.options'] as $name => $value) { | |
$method = 'set' . ucfirst($name); | |
if (!method_exists($phptal, $method)) { | |
throw new \RuntimeException( | |
sprintf('The accessor method to "%s" is not defined.', $name)); | |
} | |
if (isset($value)) { | |
switch ($name) { | |
case 'templateRepository': | |
if ('\\' === DIRECTORY_SEPARATOR) { | |
$value = (is_array($value)) | |
? array_map(function($var) { | |
return str_replace('\\', '/', $var); | |
}, $value) : str_replace('\\', '/', $value); | |
} | |
break; | |
default: | |
break; | |
} | |
$phptal->{$method}($value); | |
} | |
} | |
return $phptal; | |
}); | |
if (isset($app['phptal.class_path'])) { | |
$app['autoloader']->registerPrefix('PHPTAL', $app['phptal.class_path']); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head metal:use-macro="__layout.html/head"> | |
<meta charset="UTF-8" /> | |
<title>人物削除</title> | |
</head> | |
<body metal:use-macro="__layout.html/body"> | |
<div id="container"> | |
<div id="main" metal:fill-slot="main"> | |
<ul class="errors" tal:condition="exists:errors"> | |
<li tal:repeat="error errors" tal:content="error">エラーメッセージ</li> | |
</ul> | |
<form method="post"> | |
<input type="hidden" tal:attributes="name token/name;value token/value" /> | |
<table> | |
<tr> | |
<th>ID</th> | |
<td>${data/id}</td> | |
</tr> | |
<tr> | |
<th>名前</th> | |
<td>${data/name}</td> | |
</tr> | |
<tr> | |
<th>備考</th> | |
<td>${data/notes}</td> | |
</tr> | |
</table> | |
<p> | |
<input type="submit" name="delete" value="削除" /> | |
</p> | |
</form> | |
<p><a href="/profiles/">戻る</a></p> | |
</div> | |
</div> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head metal:use-macro="__layout.html/head"> | |
<meta charset="UTF-8" /> | |
<title>人物編集</title> | |
</head> | |
<body metal:use-macro="__layout.html/body"> | |
<div id="container"> | |
<div id="main" metal:fill-slot="main"> | |
<ul class="errors" tal:condition="exists:errors"> | |
<li tal:repeat="error errors" tal:content="error">エラーメッセージ</li> | |
</ul> | |
<form method="post"> | |
<input type="hidden" tal:attributes="name token/name;value token/value" /> | |
<table> | |
<tr> | |
<th>ID</th> | |
<td tal:content="data/id">1</td> | |
</tr> | |
<tr> | |
<th>名前</th> | |
<td><input type="text" name="name" tal:attributes="value data/name" /></td> | |
</tr> | |
<tr> | |
<th>備考</th> | |
<td><textarea name="notes" tal:content="data/notes"></textarea></td> | |
</tr> | |
</table> | |
<p> | |
<input type="submit" name="store" value="保存" /> | |
</p> | |
</form> | |
<p><a href="/profiles/">戻る</a></p> | |
</div> | |
</div> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head metal:use-macro="__layout.html/head"> | |
<meta charset="UTF-8" /> | |
<tal:block metal:fill-slot="head-extra"> | |
<link rel="stylesheet" media="screen" href="/css/list.css" /> | |
</tal:block> | |
<title>一覧</title> | |
</head> | |
<body metal:use-macro="__layout.html/body"> | |
<div id="container"> | |
<div id="main" metal:fill-slot="main"> | |
<table class="list"> | |
<thead> | |
<tr> | |
<th>ID</th> | |
<th>名前</th> | |
<th>備考</th> | |
<th></th> | |
</tr> | |
</thead> | |
<tbody> | |
<tr tal:repeat="item items" tal:attributes="class php: repeat.item.even ? 'row1' : 'row2'"> | |
<td class="number" tal:content="item/id">ID</td> | |
<td tal:content="item/name">k-holy</td> | |
<td tal:content="item/notes">眠い眠い眠い</td> | |
<td class="action"> | |
<a href="/profiles/${item/id}/modify">編集</a> | |
<a href="/profiles/${item/id}/delete">削除</a> | |
</td> | |
</tr> | |
</tbody> | |
</table> | |
</div> | |
</div> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment