
部品ナビゲーション
Githubプロジェクト
必要なマニュアルの一部をインストールする方法については、 リンクでリポジトリの説明を参照してください 。 (たとえば、前のレッスンを経ずにこのレッスンから始めたい場合)
ホームページ 投稿とコメント。
メインページに最近のエントリのリストが表示されるようになりましたが、これらのエントリのコメントに関する情報はありません。 エッセンスコメントがあります。この情報を提供するためにメインページに戻ることができます。 BlogエンティティとCommentエンティティの間に関係を確立したので、Doctrine 2は投稿に対するコメントを受信できることを知っています( $ commentsオブジェクトをBlogエンティティに追加したことを思い出してください)。 ホームページテンプレートを更新しましょう
src / Blogger / BlogBundle / Resources / views / Page / index.html.twig
{# src/Blogger/BlogBundle/Resources/views/Page/index.html.twig #}
{# .. #}
<footer class="meta">
<p>Comments: {{ blog.comments|length }}</p>
<p>Posted by <span class="highlight">{{ blog.author }}</span> at {{ blog.created|date('h:iA') }}</p>
<p>Tags: <span class="highlight">{{ blog.tags }}</span></p>
</footer>
{# .. #}
comments getter , Twig length . , http://localhost:8000/ .
, Doctrine 2 $comments Blog Comment. Blog.
src/Blogger/BlogBundle/Entity/Blog.php
// src/Blogger/BlogBundle/Entity/Blog.php
/**
* @ORM\OneToMany(targetEntity="Comment", mappedBy="blog")
*/
protected $comments;
, , Doctrine 2 , $comments Comment? BlogRepository, ( ) , Comment .
src/Blogger/BlogBundle/Repository/BlogRepository.php
// src/Blogger/BlogBundle/Repository/BlogRepository.php
public function getLatestBlogs($limit = null)
{
$qb = $this->createQueryBuilder('b')
->select('b')
->addOrderBy('b.created', 'DESC');
if (false === is_null($limit))
$qb->setMaxResults($limit);
return $qb->getQuery()
->getResult();
}
, Doctrine 2 , , Comment , , {{blog.comments | length}}. , . , , Doctrine 2 . Doctrine 2 , … , HTTP-.

Doctrine 2 , Doctrine 2 HTTP.

, . , getLatestBlogs() BlogRepository. , , . WHERE t0.blog_id = ? , ? (id ). {{blog.comments}} . , , Doctrine 2 (lazily) Comment, Blog.
, . Doctrine2 , . , Blog Comment . QueryBuilder BlogRepository.
src/Blogger/BlogBundle/Repository/BlogRepository.php
// src/Blogger/BlogBundle/Repository/BlogRepository.php
public function getLatestBlogs($limit = null)
{
$qb = $this->createQueryBuilder('b')
->select('b, c')
->leftJoin('b.comments', 'c')
->addOrderBy('b.created', 'DESC');
if (false === is_null($limit))
$qb->setMaxResults($limit);
return $qb->getQuery()
->getResult();
}
, Doctrine 2 , . , comment blog.
, . 2 , , . , . , , Doctrine 2. , .
, , .
src/Blogger/BlogBundle/Resources/views/Page/index.html.twig
{# src/Blogger/BlogBundle/Resources/views/Page/index.html.twig #}
{# .. #}
<footer class="meta">
<p>Comments: <a href="{{ path('BloggerBlogBundle_blog_show', { 'id': blog.id }) }}#comments">{{ blog.comments|length }}</a></p>
<p>Posted by <span class="highlight">{{ blog.author }}</span> at {{ blog.created|date('h:iA') }}</p>
<p>Tags: <span class="highlight">{{ blog.tags }}</span></p>
</footer>
{# .. #}
.
(sidebar)
symblog . .
, . . BlogRepository . BlogRepository
src/Blogger/BlogBundle/Repository/BlogRepository.php
// src/Blogger/BlogBundle/Repository/BlogRepository.php
public function getTags()
{
$blogTags = $this->createQueryBuilder('b')
->select('b.tags')
->getQuery()
->getResult();
$tags = array();
foreach ($blogTags as $blogTag)
{
$tags = array_merge(explode(",", $blogTag['tags']), $tags);
}
foreach ($tags as &$tag)
{
$tag = trim($tag);
}
return $tags;
}
public function getTagWeights($tags)
{
$tagWeights = array();
if (empty($tags))
return $tagWeights;
foreach ($tags as $tag)
{
$tagWeights[$tag] = (isset($tagWeights[$tag])) ? $tagWeights[$tag] + 1 : 1;
}
// Shuffle the tags
uksort($tagWeights, function() {
return rand() > rand();
});
$max = max($tagWeights);
// Max of 5 weights
$multiplier = ($max > 5) ? 5 / $max : 1;
foreach ($tagWeights as &$tag)
{
$tag = ceil($tag * $multiplier);
}
return $tagWeights;
}
, (CSV) , . getTags(). getTagWeights() , «» , . , .
, .
src/Blogger/BlogBundle/Controller/PageController.php
// src/Blogger/BlogBundle/Controller/PageController.php
public function sidebarAction()
{
$em = $this->getDoctrine()
->getManager();
$tags = $em->getRepository('BloggerBlogBundle:Blog')
->getTags();
$tagWeights = $em->getRepository('BloggerBlogBundle:Blog')
->getTagWeights($tags);
return $this->render('BloggerBlogBundle:Page:sidebar.html.twig', array(
'tags' => $tagWeights
));
}
, 2 BlogRepository , .
src/Blogger/BlogBundle/Resources/views/Page/sidebar.html.twig
{# src/Blogger/BlogBundle/Resources/views/Page/sidebar.html.twig #}
<section class="section">
<header>
<h3>Tag Cloud</h3>
</header>
<p class="tags">
{% for tag, weight in tags %}
<span class="weight-{{ weight }}">{{ tag }}</span>
{% else %}
<p>There are no tags</p>
{% endfor %}
</p>
</section>
. «» . for , , tag , weight . for, Twig.
BloggerBlogBundle, src/Blogger/BlogBundle/Resources/views/layout.html.twig , (placeholder) . . , Twig render , sidebar Page.
{# src/Blogger/BlogBundle/Resources/views/layout.html.twig #}
{# .. #}
{% block sidebar %}
{{ render(controller('BloggerBlogBundle:Page:sidebar' ))}}
{% endblock %}
.
src/Blogger/BlogBundle/Resources/public/css/sidebar.css
.sidebar .section { margin-bottom: 20px; }
.sidebar h3 { line-height: 1.2em; font-size: 20px; margin-bottom: 10px; font-weight: normal; background: #eee; padding: 5px; }
.sidebar p { line-height: 1.5em; margin-bottom: 20px; }
.sidebar ul { list-style: none }
.sidebar ul li { line-height: 1.5em }
.sidebar .small { font-size: 12px; }
.sidebar .comment p { margin-bottom: 5px; }
.sidebar .comment { margin-bottom: 10px; padding-bottom: 10px; }
.sidebar .tags { font-weight: bold; }
.sidebar .tags span { color: #000; font-size: 12px; }
.sidebar .tags .weight-1 { font-size: 12px; }
.sidebar .tags .weight-2 { font-size: 15px; }
.sidebar .tags .weight-3 { font-size: 18px; }
.sidebar .tags .weight-4 { font-size: 21px; }
.sidebar .tags .weight-5 { font-size: 24px; }
, . BloggerBlogBundle main
src/Blogger/BlogBundle/Resources/views/layout.html.twig
{# src/Blogger/BlogBundle/Resources/views/layout.html.twig #}
{# .. #}
{% block stylesheets %}
{{ parent() }}
<link href="{{ asset('bundles/bloggerblog/css/blog.css') }}" type="text/css" rel="stylesheet" />
<link href="{{ asset('bundles/bloggerblog/css/sidebar.css') }}" type="text/css" rel="stylesheet" />
{% endblock %}
{# .. #}
assets web, assets.
$ php app/console assets:install web
. , «» (), .
, .
-, . CommentRepository
src/Blogger/BlogBundle/Repository/CommentRepository.php
<?php
// src/Blogger/BlogBundle/Repository/CommentRepository.php
public function getLatestComments($limit = 10)
{
$qb = $this->createQueryBuilder('c')
->select('c')
->addOrderBy('c.id', 'DESC');
if (false === is_null($limit))
$qb->setMaxResults($limit);
return $qb->getQuery()
->getResult();
}
sidebar
src/Blogger/BlogBundle/Controller/PageController.php
// src/Blogger/BlogBundle/Controller/PageController.php
public function sidebarAction()
{
// ..
$commentLimit = $this->container
->getParameter('blogger_blog.comments.latest_comment_limit');
$latestComments = $em->getRepository('BloggerBlogBundle:Comment')
->getLatestComments($commentLimit);
return $this->render('BloggerBlogBundle:Page:sidebar.html.twig', array(
'latestComments' => $latestComments,
'tags' => $tagWeights
));
}
blogger_blog.comments.latest_comment_limit . ,
src/Blogger/BlogBundle/Resources/config/config.yml
# src/Blogger/BlogBundle/Resources/config/config.yml
parameters:
# ..
# Blogger max latest comments
blogger_blog.comments.latest_comment_limit: 10
, .
src/Blogger/BlogBundle/Resources/views/Page/sidebar.html.twig
{# src/Blogger/BlogBundle/Resources/views/Page/sidebar.html.twig #}
{# .. #}
<section class="section">
<header>
<h3>Latest Comments</h3>
</header>
{% for comment in latestComments %}
<article class="comment">
<header>
<p class="small"><span class="highlight">{{ comment.user }}</span> commented on
<a href="{{ path('BloggerBlogBundle_blog_show', { 'id': comment.blog.id }) }}#comment-{{ comment.id }}">
{{ comment.blog.title }}
</a>
[<em><time datetime="{{ comment.created|date('c') }}">{{ comment.created|date('Y-m-d h:iA') }}</time></em>]
</p>
</header>
<p>{{ comment.comment }}</p>
</p>
</article>
{% else %}
<p>There are no recent comments</p>
{% endfor %}
</section>
, .

Twig
, , 2011-04-21. , , , , , 3 . Comment , {{comment.created|date (' h:iA Y-m-d')}}.
, Comment. , Twig. Twig , Extension.
extension Twig , . Twig , .
{{ comment.created|created_ago }}. , 2 .
Twig
src/Blogger/BlogBundle/Twig/Extensions/BloggerBlogExtension.php
<?php
// src/Blogger/BlogBundle/Twig/Extensions/BloggerBlogExtension.php
namespace Blogger\BlogBundle\Twig\Extensions;
class BloggerBlogExtension extends \Twig_Extension
{
public function getFilters()
{
return array(
new \Twig_SimpleFilter('created_ago', array($this, 'createdAgo')),
);
}
public function createdAgo(\DateTime $dateTime)
{
$delta = time() - $dateTime->getTimestamp();
if ($delta < 0)
throw new \InvalidArgumentException("createdAgo is unable to handle dates in the future");
$duration = "";
if ($delta < 60)
{
// Seconds
$time = $delta;
$duration = $time . " second" . (($time > 1) ? "s" : "") . " ago";
}
else if ($delta <= 3600)
{
// Mins
$time = floor($delta / 60);
$duration = $time . " minute" . (($time > 1) ? "s" : "") . " ago";
}
else if ($delta <= 86400)
{
// Hours
$time = floor($delta / 3600);
$duration = $time . " hour" . (($time > 1) ? "s" : "") . " ago";
}
else
{
// Days
$time = floor($delta / 86400);
$duration = $time . " day" . (($time > 1) ? "s" : "") . " ago";
}
return $duration;
}
public function getName()
{
return 'blogger_blog_extension';
}
}
. getFilters() , . created_ago. createdAgo, DateTime , DateTime.
, Twig ,
src/Blogger/BlogBundle/Resources/config/services.yml
services:
blogger_blog.twig.extension:
class: Blogger\BlogBundle\Twig\Extensions\BloggerBlogExtension
tags:
- { name: twig.extension }
BloggerBlogExtension Twig .
Twig . created_at .
src/Blogger/BlogBundle/Resources/views/Page/sidebar.html.twig
{# src/Blogger/BlogBundle/Resources/views/Page/sidebar.html.twig #}
{# .. #}
<section class="section">
<header>
<h3>Latest Comments</h3>
</header>
{% for comment in latestComments %}
{# .. #}
<em><time datetime="{{ comment.created|date('c') }}">{{ comment.created|created_ago }}</time></em>
{# .. #}
{% endfor %}
</section>
http://localhost:8000/ , Twig.
.
src/Blogger/BlogBundle/Resources/views/Comment/index.html.twig
{# src/Blogger/BlogBundle/Resources/views/Comment/index.html.twig #}
{% for comment in comments %}
<article class="comment {{ cycle(['odd', 'even'], loop.index0) }}" id="comment-{{ comment.id }}">
<header>
<p><span class="highlight">{{ comment.user }}</span> commented <time datetime="{{ comment.created|date('c') }}">{{ comment.created|created_ago }}</time></p>
</header>
<p>{{ comment.comment }}</p>
</article>
{% else %}
<p>There are no comments for this post. Be the first to comment...</p>
{% endfor %}
Twig, Twig-Extensions GitHub. pull request , , .
Url
URL id . , SEO. , URL http://localhost:8000/1 , - http://localhost:8000/1/a-day-with-symfony2 . slug URL. slug , ASCII — .
slug.
src/Blogger/BlogBundle/Resources/config/routing.yml
# src/Blogger/BlogBundle/Resources/config/routing.yml
BloggerBlogBundle_blog_show:
path: /{id}/{slug}
defaults: { _controller: "BloggerBlogBundle:Blog:show" }
requirements:
methods: GET
id: \d+
id, slug ,
src/Blogger/BlogBundle/Controller/BlogController.php
// src/Blogger/BlogBundle/Controller/BlogController.php
public function showAction($id, $slug)
{
// ..
}
.
, , . Symfony2 . , . defaults.
BloggerBlogBundle_blog_show: path: /{id}/{slug} defaults: { _controller: "BloggerBlogBundle:Blog:show", comments: true } requirements: methods: GET id: \d+
public function showAction($id, $slug, $comments) { // .. }
, http://localhost:8000/1/symfony2-blog $comments true showAction
Slug
, slug , slug. , slug Blog .
Blog
Blog slug.
src/Blogger/BlogBundle/Entity/Blog.php
// src/Blogger/BlogBundle/Entity/Blog.php
class Blog
{
// ..
/**
* @ORM\Column(type="string")
*/
protected $slug;
// ..
}
$slug. .
$ php app/console doctrine:generate:entities Blogger
.
$ php app/console doctrine:migrations:diff $ php app/console doctrine:migrations:migrate
slug slugify symfony1 Jobeet . slugify Blog
src/Blogger/BlogBundle/Entity/Blog.php
// src/Blogger/BlogBundle/Entity/Blog.php
public function slugify($text)
{
// replace non letter or digits by -
$text = preg_replace('#[^\\pL\d]+#u', '-', $text);
// trim
$text = trim($text, '-');
// transliterate
if (function_exists('iconv'))
{
$text = iconv('utf-8', 'us-ascii//TRANSLIT', $text);
}
// lowercase
$text = strtolower($text);
// remove unwanted characters
$text = preg_replace('#[^-\w]+#', '', $text);
if (empty($text))
{
return 'n-a';
}
return $text;
}
, slug slug, . setTitle slug. Blog
src/Blogger/BlogBundle/Entity/Blog.php
// src/Blogger/BlogBundle/Entity/Blog.php
public function setTitle($title)
{
$this->title = $title;
$this->setSlug($this->title);
}
setSlug.
src/Blogger/BlogBundle/Entity/Blog.php
// src/Blogger/BlogBundle/Entity/Blog.php
public function setSlug($slug)
{
$this->slug = $this->slugify($slug);
}
slug.
$ php app/console doctrine:fixtures:load
, . .
src/Blogger/BlogBundle/Resources/views/Page/index.html.twig
{# src/Blogger/BlogBundle/Resources/views/Page/index.html.twig #}
{% extends 'BloggerBlogBundle::layout.html.twig' %}
{% block body %}
{% for blog in blogs %}
<article class="blog">
<div class="date"><time datetime="{{ blog.created|date('c') }}">{{ blog.created|date('l, F j, Y') }}</time></div>
<header>
<h2><a href="{{ path('BloggerBlogBundle_blog_show', { 'id': blog.id, 'slug': blog.slug }) }}">{{ blog.title }}</a></h2>
</header>
<img src="{{ asset(['images/', blog.image]|join) }}" />
<div class="snippet">
<p>{{ blog.blog(500) }}</p>
<p class="continue"><a href="{{ path('BloggerBlogBundle_blog_show', { 'id': blog.id, 'slug': blog.slug }) }}">Continue reading...</a></p>
</div>
<footer class="meta">
<p>Comments: <a href="{{ path('BloggerBlogBundle_blog_show', { 'id': blog.id, 'slug': blog.slug }) }}#comments">{{ blog.comments|length }}</a></p>
<p>Posted by <span class="highlight">{{ blog.author }}</span> at {{ blog.created|date('h:iA') }}</p>
<p>Tags: <span class="highlight">{{ blog.tags }}</span></p>
</footer>
</article>
{% else %}
<p>There are no blog entries for symblog</p>
{% endfor %}
{% endblock %}
,
src/Blogger/BlogBundle/Resources/views/Page/sidebar.html.twig
{# src/Blogger/BlogBundle/Resources/views/Page/sidebar.html.twig #}
{# .. #}
<a href="{{ path('BloggerBlogBundle_blog_show', { 'id': comment.blog.id, 'slug': comment.blog.slug }) }}#comment-{{ comment.id }}">
{{ comment.blog.title }}
</a>
{# .. #}
createAction Comment . Comment
src/Blogger/BlogBundle/Controller/CommentController.php
// src/Blogger/BlogBundle/Controller/CommentController.php
public function createAction($blog_id)
{
// ..
if ($form->isValid()) {
// ..
return $this->redirect($this->generateUrl('BloggerBlogBundle_blog_show', array(
'id' => $comment->getBlog()->getId(),
'slug' => $comment->getBlog()->getSlug())) .
'#comment-' . $comment->getId()
);
}
// ..
}
, http://localhost:8000/ , slug URL.
Symfony2. Symfony2 - . Symfony2 3- :
dev —
test —
prod —
, , - . , . , . , . , . — , ..
test . , unit . , …
Front
. - web/app_dev.php :
$kernel = new AppKernel('dev', true);
, - , web/app.php :
$kernel = new AppKernel('prod', false);
, AppKernel .
- app_test.php.
, - , . , . app/config config.yml. , config.yml 3 ; config_dev.yml, config_test.yml config_prod.yml. . config_dev.yml .
imports: - { resource: config.yml }
imports config.yml, imports 2 , config_test.yml config_prod.yml. , config.yml . development, app/config/config_dev.yml , .
# app/config/config_dev.yml
web_profiler:
toolbar: true
, .
, .
-, Symfony2.
$ php app/console cache:clear --env=prod
http://localhost:8000/app.php.
, , . , http://localhost:8000/app.php/999.

, . .
, app/logs/prod.log . , , .
http://localhost:8000/app.php app.php? , , index.html index.php, , app.php ? RewriteRule web/.htaccess
RewriteRule ^(.*)$ app.php [QSA,L]
, , , ^(.*)$ app.php.
Apache, mod_rewrite.c, app.php URL, http://localhost:8000/app.php/.
Symfony2 , , , , . , .
, . cookbook Symfony2, .
Assetic
Symfony2.8 Asseti , assetic. composer.json
"require": {
//...
"symfony/assetic-bundle": "dev-master"
},
composer update
.
app/AppKernel.php
//app/AppKernel.php
public function registerBundles()
{
$bundles = array(
// ...
new Symfony\Bundle\AsseticBundle\AsseticBundle(),
);
// ...
}
app/config/config.yml
# app/config/config.yml
assetic:
debug: '%kernel.debug%'
use_controller: '%kernel.debug%'
filters:
cssrewrite: ~
# ...
Kris Wallsmith Python webassets.
Assetic 2- assets, assets , , JavaScript , . , CSS JavaScript, CoffeeScript CoffeeScript assets , HTTP .
Twig asset assets .
<link href="{{ asset('bundles/bloggerblog/css/blog.css') }}" type="text/css" rel="stylesheet" />
Assets
Assetic asset :
Assetic asset - , . Asset , .
, assets , , .
Assetic BloggerBlogBundle
app/config/config.yml
# ..
assetic:
bundles: [BloggerBlogBundle]
# ..
Assetic BloggerBlogBundle , Assetic. bundles .
asset BloggerBlogBundle.
src/Blogger/BlogBundle/Resources/views/layout.html.twig
{# src/Blogger/BlogBundle/Resources/views/layout.html.twig #}
{# .. #}
{% block stylesheets %}
{{ parent () }}
{% stylesheets
'@BloggerBlogBundle/Resources/public/css/*'
%}
<link href="{{ asset_url }}" rel="stylesheet" media="screen" />
{% endstylesheets %}
{% endblock %}
{# .. #}
2 CSS-, Assetic . Assetic , CSS src/Blogger/BlogBundle/Resources/public/css 1 , . , . HTTP- . * css .
{# src/Blogger/BlogBundle/Resources/views/layout.html.twig #}
{# .. #}
{% block stylesheets %}
{{ parent () }}
{% stylesheets
'@BloggerBlogBundle/Resources/public/css/blog.css'
'@BloggerBlogBundle/Resources/public/css/sidebar.css'
%}
<link href="{{ asset_url }}" rel="stylesheet" media="screen" />
{% endstylesheets %}
{% endblock %}
{# .. #}
. * , , CSS , CSS Assetic. , .
HTML http://localhost:8000/ , CSS (, ).
<link href="/css/d8f44a4_part_1_blog_1.css" rel="stylesheet" media="screen" />
<link href="/css/d8f44a4_part_1_sidebar_2.css" rel="stylesheet" media="screen" />
, 2 . , Assetic 1 CSS . , symblog . Assetic , false
{# src/Blogger/BlogBundle/Resources/views/layout.html.twig #}
{# .. #}
{% stylesheets
'@BloggerBlogBundle/Resources/public/css/*'
debug=false
%}
<link href="{{ asset_url }}" rel="stylesheet" media="screen" />
{% endstylesheets %}
{# .. #}
, HTML - .
<link href="/css/3c7da45.css" rel="stylesheet" media="screen" />
, 2 CSS , blog.css sidebar.css 1 . CSS . , output
{% stylesheets
'@BloggerBlogBundle/Resources/public/css/*'
output='css/blogger.css'
%}
<link href="{{ asset_url }}" rel="stylesheet" media="screen" />
{% endstylesheets %}
, , , assets.
app/Resources/views/base.html.twig
{# app/Resources/views/base.html.twig #}
{# .. #}
{% block stylesheets %}
<link href='http://fonts.googleapis.com/css?family=Irish+Grover' rel='stylesheet' type='text/css'>
<link href='http://fonts.googleapis.com/css?family=La+Belle+Aurore' rel='stylesheet' type='text/css'>
{% stylesheets
'css/*'
%}
<link href="{{ asset_url }}" rel="stylesheet" media="screen" />
{% endstylesheets %}
{% endblock %}
{# .. #}
JavaScripts
- JavaScript , Assetic ,
{% javascripts
'@BloggerBlogBundle/Resources/public/js/*'
%}
<script type="text/javascript" src="{{ asset_url }}"></script>
{% endjavascripts %}
Assetic — . assets assets. , , :
CssMinFilter: CSS
JpegoptimFilter: JPEG
Yui\CssCompressorFilter: CSS YUI
Yui\JsCompressorFilter: JavaScript YUI
CoffeeScriptFilter: CoffeeScript JavaScript
Assetic Readme.
, YUI , , , / , .
YUI 2.4.7 ( , , 2.4.8 ), yuicompressor-2.4.7.jar build app/Resources/java/.
Java
Assetic CSS YUI .
app/config/config.yml
# app/config/config.yml
# ..
assetic:
filters:
cssrewrite: ~
yui_css:
jar: "%kernel.root_dir%/Resources/java/yuicompressor-2.4.7.jar"
# ..
yui_css, YUI Compressor Java . assets , . yui_css
src/Blogger/BlogBundle/Resources/views/layout.html.twig
{# src/Blogger/BlogBundle/Resources/views/layout.html.twig #}
{# .. #}
{% stylesheets
'@BloggerBlogBundle/Resources/public/css/*'
output='css/blogger.css'
filter='yui_css'
%}
<link href="{{ asset_url }}" rel="stylesheet" media="screen" />
{% endstylesheets %}
{# .. #}
, Assetic , . , , JavaScript. , ?
{% stylesheets
'@BloggerBlogBundle/Resources/public/css/*'
output='css/blogger.css'
filter='?yui_css'
%}
<link href="{{ asset_url }}" rel="stylesheet" media="screen" />
{% endstylesheets %}
assets
, Assetic css javascript . , , Symfony ( ).
assets , , assets . , . , .
, Assetic assets , .
asset.
$ php app/console assetic:dump
, CSS- web/css blogger.css. , - symblog http://localhost:8000/app.php .
asset , asset web/, Assetic .
Symfony2, Symfony2 Assetic asset . .
. unit . , Symfony2 , , -, , , .
:
https://symfony.com/
http://tutorial.symblog.co.uk/
http://twig.sensiolabs.org/
How to Use Assetic for Asset Management
How to Minify JavaScripts and Stylesheets with YUI Compressor
How to Use Assetic For Image Optimization with Twig Functions
How to Apply an Assetic Filter to a Specific File Extension
Post Scriptum
, , , .
1 — Symfony2
2 — : ,
3 — Doctrine 2
4 — , Doctrine 2
6 —
, . .