我使用的是瘦弱的php,但这并不是特别简单,这在不同的php框架的路由中很常见,特别是在使用其他应用时。
好的,这是可以在博客或存档应用程序中找到的最常见的路线
$app->get('docs(/:year(/:month(/:day)))', function($y=0;$m=0;$d=0) use ($app){
if ($year !== 0 && $month !==0 && $day !== 0) {
// query database with conditions of year, month, day
} else if ($year !== 0 && $month !== 0) {
// query database with conditions of year, month
} else if ($year !== 0) {
// query database with conditions of year
} else {
// query database, return all
}
})
此外,您希望添加get
参数以缩小搜索范围,例如limit
,offset
$app->get('docs(/:year(/:month(/:day)))', function($y=0;$m=0;$d=0) use ($app){
// additionally you optionally allowed filters like: limit, offset, all
$tmpLimit = $app->request()->get('limit');
$tmpOffSet = $app->request()->get('offset');
$limit = isset($tmpLimit) ? $tmpLimit : 10;
$offset = isset($tmpOffSet) ? $tmpOffSet : 0;
... below add the code previously, and query would change according to if filters(limit,offset) has been set.
})
还有更多解决方案吗?有太多的代码告诉我,我做得不对。
答案 0 :(得分:2)
您可以使用中间件(Route-Middleware / Middleware)和/或挂钩(Hooks-Overview)来保持您的路线简单。
$mw = function($app) {
return function() use($app) {
$tmpLimit = $app->request()->get('limit');
$tmpOffSet = $app->request()->get('offset');
$app->docsLimit = isset($tmpLimit) ? $tmpLimit : 10;
$app->docsOffSet = isset($tmpOffSet) ? $tmpOffSet : 0;
};
};
路线:
$app->get('/docs(/:year(/:month(/:day)))', $mw($app),function($y=0,$m=0,$d=0) use ($app) {
echo $app->docsLimit."<br/>";
echo $app->docsOffSet."<br/>";
... your previously code
});
$app->hook('slim.before.router', function() use($app){
if (strpos($app->request()->getPath(), '/docs') === 0) {
$tmpLimit = $app->request()->get('limit');
$tmpOffSet = $app->request()->get('offset');
$app->docsLimit = isset($tmpLimit) ? $tmpLimit : 10;
$app->docsOffSet = isset($tmpOffSet) ? $tmpOffSet : 0;
}
});
路线:
$app->get('/docs(/:year(/:month(/:day)))', function($y=0,$m=0,$d=0) use ($app) {
echo $app->docsLimit."<br/>";
echo $app->docsOffSet."<br/>";
... your previously code
});
答案 1 :(得分:1)
我说你应该稍微研究一下查询构建器对象。例如Doctrine DBAL中的那个。这允许您有条件地构建查询,而无需将字符串连接在一起(这会打开各种可能的错误和安全问题的潘多拉盒子):
$queryBuilder
->select('b.id', 'b.title')
->from('blog', 'b');
if ($year) {
$queryBuilder->where('b.year = :year')
->setParameter('year', $year);
}
if ($month) {
queryBuilder->where('b.month = :month')
->setParameter('month', $month);
}
if ($day) {
$queryBuilder->where('b.day = :day')
->setParameter('year', $day)
}
除此之外,看起来您将所有功能都放在路线中,但您应该考虑将一些任务分成服务。快速扫描slimphp文档我无法找到&#34; services&#34;的任何概念,但所有这意味着你为$ app添加了一个单独的函数,以便你可以重用该功能。按理说你会想要获取博客&#34;来自多条路线。它应该像(docs here)一样简单:
$app->findBlogPosts = function($y = null, $m = null, $d = null) use ($app) {
// do the DB stuff here, return results
}
我将默认参数更改为null
,因为0
的$ year值无意义。如果你打算说'#34;这个东西可能没有价值&#34;,请使用&#34; null&#34;的语言概念。 - 每种编程语言都有这样的概念。
答案 2 :(得分:0)
感谢@deceze和@ramon指导我完成重构代码的整个过程,
首先,我被赋予了有条件地构建 SQL语句的想法,这引出了我:
if ($year !== 0) {
$where[] = 'YEAR(date_created) = :year';
$bind['where'] = $year;
}
... // if month, if year..
...
$query = sprintf('SELECT * FROM table WHERE %s', join(' AND ', $where));
Document::raw_query($query, $bind)->find_array();
根据@ ramon,他建议使用查询构建器,这将会或可能会导致问题, 这样:
我可以做类似的事情:
$queryBuilder
->select('b.id', 'b.title')
->from('blog', 'b');
查看paris提供的基本方法,如文档中所示,我无法在活动记录库的where
方法中传递本机sql函数,但是挖掘更多,我意识到它是建立在idiorm之上,我只需要查看文档,如果可以通过where子句传递函数,并且通过玩我的IDE一点,我发现where_raw
存在。
我想出了这个......
$where = array();
$bind = array();
if (!is_null($day)) {
$where[] = 'DAY(`date_created`) = ?';
$bind[] = $day;
}
if (!is_null($month)) {
$where[] = 'MONTH(`date_created`) = ?';
$bind[] = $month;
}
if (!is_null($year)) {
$where[] = 'YEAR(`date_created`) = ?';
$bind[] = $year;
$query = sprintf('%s', join(' AND ', $where));
$foo = Foo::where_raw($query, $bind)
->order_by_desc('date_created')
->offset($offset)
->limit($limit)
->find_array();
} else {
$documents = Foo::order_by_desc('date_created')
->offset($offset)
->limit($limit)
->find_array();
}
我对接受用户的输入有点自信,orm在执行之前准备了查询,我认为会做一些安全检查。