Symfony

【Symfony2.3/Doctrine2】で生SQLを実行する。

DQLではMySQLのDATE_FORMATが使えないので生クエリを発行してみた。

例えばブログなどの投稿記事を男女別、日別でカウントを取りたいとすると
雰囲気下記のような感じになる。

// ファイルの先頭で宣言
use Hoge\FugaBundle\Entity\Post;
use Doctrine\ORM\Query\ResultSetMapping;

...
// 関数内
$em = $this->getDoctrine()->getManager();
// 何日前の投稿分まで集計するか
$pastRange = date('Y-m-d', strtotime('-16 days'));

$sql = "select date_format(p.createdAt, '%Y-%m-%d') as date, p.sex as sex, count(p.id) as cnt from posts as p where p.deletedAt is null and p.status in (1, 2) and p.createdAt >= ? 

group by date, sex";

$rsm = new ResultSetMapping();
$rsm->addEntityResult('HogeFugaBundle:Post', 'p');
$rsm->addScalarResult('date', 'date');
$rsm->addScalarResult('sex', 'sex');
$rsm->addScalarResult('cnt', 'cnt');

$query = $em->createNativeQuery($sql, $rsm);
$query->setParameter(1, $pastRange);

// FOSRestBundleを用いてjsonでレスポンスを返却する。
$view = $this->view($query->getResult(), 200)->setFormat('json');
return $this->handleView($view);

これでDQLに無い関数も利用出来るようになった。

おまけ。曜日、時間帯、男女別ごとにカウントを取るSQL。

$sql = "select date_format(p.createdAt, '%w') as day, date_format(p.createdAt, '%H') as hour, p.sex as sex, count(p.id) as cnt from posts as p where p.deletedAt is null and p.status 

in (1, 2) and p.createdAt >= ? group by day, hour, sex";

$rsm = new ResultSetMapping();
$rsm->addEntityResult('HogeFugaBundle:Post', 'p');
$rsm->addScalarResult('day', 'day');
$rsm->addScalarResult('hour', 'hour');
$rsm->addScalarResult('sex', 'sex');
$rsm->addScalarResult('cnt', 'cnt');

うん。楽しい。

createNativeQuery()の詳細は下記公式を参照されたし。

http://doctrine-orm.readthedocs.org/en/latest/reference/native-sql.html

 

【Symfony2.3】asseticでディレクトリ内のJS、CSSを再帰的に検知する方法。

は無いらしいのでどうやら下記のように記述してやる必要がある模様。

■CSS

{% block stylesheets %}
{% stylesheets
'/*.css'
'/*/*.css'
'/*/*/*.css'
'/*/*/*/*.css'
'/*/*/*/*/*.css'
output='css/dump/main.css'
%}
<link rel="stylesheet" href="{{ asset_url | replace({'/app_dev.php': ''}) }}" />
{% endstylesheets %}
{% endblock %}

■Javascript

{% block javascripts %}
{% javascripts 
'/*.js'
'/*/*.js'
'/*/*/*.js'
'/*/*/*/*.js'
'/*/*/*/*/*.js'
output='js/dump/main.js'
%}
<script src="{{ asset_url | replace({'/app_dev.php': ''}) }}"></script>
{% endjavascripts %}
{% endblock  %}

的な感じ。

 

【Symfony2.3】doctrine2のfindBy()でlimit、offsetを指定する。

メモ。

findBy()は第3引数が$maxResults、第4引数が$firstResultになっているので下記のように指定すればOK。
※ちなみに第2引数はオーダー。

$em->getRepository('HogeFugaBundle:Piyo')->findBy([
    'status' => 2
], [
    'createdAt' => 'asc'
], 20, 0);

こんな感じ。

 

【Symfony2.3】doctrine2で一つのリザルトを取得する。

getSingleResult()を用いる。

$em->createQuery($dql)->getSingleResult();

のような感じ。

 

【Symfony2.3】Google用のサイトマップを生成するBundle。

「presta/sitemap-bundle」がマジ便利。

packagistは下記。

https://packagist.org/packages/presta/sitemap-bundle

gitは下記。

https://github.com/prestaconcept/PrestaSitemapBundle

これで速攻サイトマップ完成したは。

 

【Symfony2.3】アクセスしているホスト名によって開発と本番環境を分ける。

.htaccessで分岐させる。

デフォルトで入っているhtaccessファイルの42行目付近を下記のように変更。

開発環境のホストが.lcl、本番環境が.comの場合。

    # Rewrite all other queries to the front controller.
    RewriteCond %{HTTP_HOST} \.com$
    RewriteRule .? %{ENV:BASE}/app.php [L]
    
    RewriteCond %{HTTP_HOST} \.lcl$
    RewriteRule .? %{ENV:BASE}/app_dev.php [L]

こんな感じでOK。

 

【Symfony2.3】現在の実行環境を取得する。

メモ。

$this->get('kernel')->getEnvironment();

これで環境を取得できるので、開発、テスト、及び本番環境で処理を分岐したい場合は下記のように記述すればOK。

if(in_array($this->get('kernel')->getEnvironment(), ['test', 'dev'])) {
    // テスト環境用の処理
}

 

【Symfony2.3】@Routerで特定文字列を含むURI以外を全て一つのアクションで拾う。

シングルページアプリケーションを構築していて、どのURI出来ても特定のアクションを返したい場合。

※下記はURIにapiを含まない場合の全てのルーティングを拾う例。

    /**
     * @Route("/{_all}", name="_all", requirements={"_all" = "^(?!.*api).*$"})
     */
    public function indexAction()
    {
    }

こんな感じでOK。