Symfony2 细节小计1
Symfony2 细节小计1
麦拂沙 发表于3年前
Symfony2 细节小计1
  • 发表于 3年前
  • 阅读 170
  • 收藏 0
  • 点赞 0
  • 评论 0

移动开发云端新模式探索实践 >>>   

路由

   # 主路由配置app/config/routing.yml
   # 加载某模块的annotation路由,如AcmeBundle
   acme:
    resource: @XxxxBundle/Controller  #该级目录及子目录annotation都被解析
    type:     annotation    #必选
    prefix: ''  #路由前缀

    
  # annotation配置路由
  # 注解命令中引号必须用双引号
  # 注解命令必须以 /** 打头, 注释以 /* 打头。   
  /**
   * @Route(
           "/Path/{slug}",
           defaults: {},
           name="",
           requirements: {"_format": "html|rss"}
   );
   * @Method("GET");
   */
   public function indexAction($slug){}
   
   
   # annotation路由参数转换 功能
   # typehint参数为一个doctrine实体类,自动查询匹配路由参数的实体对象
   # 没有匹配对象则返回404页
   /**
    * @Route("/{id}", name="admin_post_show")
    */
    public function showAction(Post $post){}
   # 还可明确的设定参数转换细节
   use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
   * @Route("/comment/{postSlug}/new", name = "comment_new")
   * @ParamConverter("post", options={"mapping": {"postSlug": "slug"}})
   
   app/console debug:router 【routeName】//调试路由
   
   url、 参数相互转换:
   $params = $this->get('router')->match('/blog/my-blog-post'); //assoc-array, 匹配的路由参数
   $uri    = $this->get('router')->generate('blog_show', array('slug' => 'my-blog-post'), bool $生成绝对地址); //生成url


控制器

return $this->redirectToRoute('hello', array('name' => 'Fabien')); //跳转
return $this->redirect($this->generateUrl('homepage'), 301); //重定向
return $this->forward('AcmeHelloBundle:Hello:fancy', array $context); //内部action转发


模型AR查询:
//管理器插入实体
$em = $this->getDoctrine()->getManager(); 
$em->persist($product);
$em->flush();

//仓库中获取实体
$repository = $this->getDoctrine()->getRepository('AppBundle:Product');
$repository->find($id);
$repository->findOneByName('foo');

$repository->findBy(array $filters);
$repository->findOneBy(array $filters);

$repository->findByPrice(19.99);
$repository->findAll();

//更新实体
$em = $this->getDoctrine()->getManager();
$product = $em->getRepository('AppBundle:Product')->find($id);
$product->setName('New product name!');
$em->flush();

//删除实体
$em->remove($product);
$em->flush();


//调用repository类方法
$repo = $this->getDoctrine()->getRepository();
$result = $repo->仓库定义的方法();


模型DQL查询
1DQL查询构建器:
$query = $repository->createQueryBuilder('p')
        ->where('p.price > :price')
        ->setParameter('price', '19.99')
        ->orderBy('p.price', 'ASC')
        ->getQuery();
$products = $query->getResult();
$product  = $query->getSingleResult(); //没有结果会抛出异常
$product  = $query->getOneOrNullResult(); //没有结果不会抛出异常

2纯DQL查询:
$em = $this->getDoctrine()->getManager();
$query = $em->createQuery(
    'SELECT p
    FROM AppBundle:Product p
    WHERE p.price > :price
    ORDER BY p.price ASC'
)->setParameter('price', '19.99');
 
$products = $query->getResult();


Doctrine

连接配置: app/config/parameters.yml
doctrine配置: app/config/config.yml

app/console doctrine:database:create //创建库(必须先创建好具备建库权限的账号)
app/console doctrine:database:drop --force //卸载库
app/console doctrine:generate:entity 【--entity="AppBundle:Category"】 //创建实体
app/console doctrine:schema:update --force //更新映射,【可创建表】
app/console doctrine:generate:entities 【AppBundle】 //为bundle生成getter,setter, repo等

 一个bundle只可以接受一种metadata定义格式(来指定字段类型),表名是可选的,如果省略,将基于entity类的名称自动确定。
 受保护的SQL字段(如group和user)
 
基础查询方法:
$repo->findOneBy(Array) 
     ->findLatest()
 
 关联查询:
 查询到的关联对象都是延迟加载
 查询到的关联对象都是代理对象(代理类存储在cache目录), 除非调用getter方法才会实际进行查询
 
 join一次性全查关联对象:
 $product =  $this->getEntityManager()
                ->createQuery(
                    'SELECT p, c FROM AppBundle:Product p
                    JOIN p.category c
                    WHERE p.id = :id'
                )->setParameter('id', $id)
                ->getSingleResult();
$category = $product->getCategory();


生命周期回调lifecycle callback:
* @ORM\HasLifecycleCallbacks() //实体头部声明
 * @ORM\PrePersist //实体内部注册回调方法并在头部声明类似该执行点


TWIG

控制器访问模板路径格式:
AcmeDemoBundle:Default:index.html.twig  #模板保存在src/Bundle/Resource/views
default/index.html.twig  #模板保存在app/Resource/views, 最佳实践推荐模板保存在此处
定界符后需要跟一对空格

app/console twig:lint app/Resources/views【/article/recent_list.html.twig】 //模板语法检查

{{ article.body|raw }} //关闭输出转义
Hello <?php echo $view->escape($name【, 'js'】) ?> //php模板形式的转义, 默认html上下文, 可以指定js上下文

全局模板变量:
app.user //当前用户对象
app.request //当前Request对象
app.session //Session对象
app.environment //当前应用程序的环境(dev,prod等)
app.debug //如果是true说明是调试模式,false则不是。

<a href="{{ path('blog_show', {'slug': 'my-blog-post'}) }}"> //相对地址url, 可通过_format指定请求资源格式
<a href="{{ url('blog_show', {'slug': 'my-blog-post'}) }}"> //绝对地址url

{{ parent() }} //应用父模块内容

{{ include('article/article_details.html.twig', { 'article': article }) }} //包含模板块
{{ render(controller('AcmeArticleBundle:Article:recentArticles', { 'max': 3 })) }} //嵌入控制器

异步内容hinclude.js:
{{ render_hinclude(controller('...'), 【{'default': 'default/content.html.twig'}】) }}
{{ render_hinclude(url('...'), 【{'default': 'Loading...'})】) }}

资源链接:
<img src="{{ asset('images/logo.png'【, version='3.0'】【, absolute=true】) }}" alt="Symfony!" /> //version: null, 或未设置则默认版本号,  false则停用版本号
## 给twig拓展自己的过滤器my_filter ##

# 自定义一个拓展类,并在其中输出my_filter
# 拓展类文件推荐放在xxBundle/Tiwg下
namespace AppBundle\Twig;
class MyExtension extends \Twig_Extension{
	public function getName()
	{
	    return 'my_extension';
	}

	public function getFilters()
	{
	    return array(
	        new \Twig_SimpleFilter(
	            'my_filter',
	            array($this, 'some_operation'),
	            array('is_safe' => array('html'))
	        ),
	    );
	}
        
        public some_operation($content){...}
}

# 编辑app/config/services.yml
# 注册拓展类为服务,并tag其为twig.extension
services:
    xx.twig.my_extension:
        class:     xxBundle\Twig\MyExtension
        public:    false
        tags:
            - { name: twig.extension }

{{ content|my_filter }}  #过滤器使用


静态文件管理器Assetic

不使用assetic: <script src="{{ asset('js/script.js') }}"></script>

将bundle的静态文件默认拷贝安装到web目录下, 一般用于第三方bundle(没有用assetic的)的静态资源安装
app/console assets:install

//////////////////////////////

使用assetic:
    压缩、合并静态文件(dev环境,每个文件依然独立;prod或者调试关闭时,文件合并)
    LESS, SASS等等的编译
    图片文件优化
    随意目录存储静态文件
    
#引入一条合并的js, 来源于两个目录
    {% javascripts '@AppBundle/Resources/public/js/*' '@AcmeBarBundle/Resources/public/js/form.js' %}
        <script src="{{ asset_url }}"></script>
    {% endjavascripts %}
    
#引入一条合并的css,来源于一个目录
#css的assetic路径写法特殊,@AppBundle会报错,一个已知的框架错误
#cssrewrite过滤器用于修复文件dump后, 图片相对路径出错
    {% stylesheets 'bundles/app/css/*' filter='cssrewrite' %}
        <link rel="stylesheet" href="{{ asset_url }}" />
    {% endstylesheets %}
  
#引入图片
    {% image '@AppBundle/Resources/public/images/example.jpg' %}
        <img src="{{ asset_url }}" alt="Example" />
    {% endimage %}
    
    
配置文件预定义命名资产
# app/config/config.yml
assetic:
    assets:
        xxxx:
            inputs:
                - '@AppBundle/Resources/public/js/thirdparty/jquery.js'
模板中应用命名资产
    {% javascripts '@xxxx' %}
        <script src="{{ asset_url }}"></script>
    {% endjavascripts %}


静态资源dump合并
prod环境:
    资源路径被合并,每次文件更新时,需要手动重建一下新的合并文件
        app/console assetic:dump --env=prod --no-debug
dev环境:
    资源路径被合并,但没有生成新文件, 内部控制器动态读取文件并合并后直接输出(文件更新立即起效,但是很慢)
    # 如果静态文件加载过慢,可关闭动态生成:
    # app/config/config_dev.yml #这里是!!开发环境!!下的配置文件
    assetic:
        use_controller: false 
   然后,手动dump出合并文件(每次文件更新都得dump一下)
       app/console assetic:dump
       app/console assetic:watch #结合参数主动监测文件是否变动然后决定更新


指定dump文件的输出路径
{% javascripts '@AppBundle/Resources/public/js/*' output='js/compiled/main.js' %}
    <script src="{{ asset_url }}"></script>
{% endjavascripts %}


静态文件压缩(UglifyJS和UglifyCSS

全局安装压缩组件
cnpm install -g uglify-js
cnpm install -g uglifycss

配置压缩组件可用:
# app/config/config.yml
assetic:
    node: /usr/bin/nodejs    #可选, 手动指定node路径
    filters:
        uglifyjs2:
            bin: /usr/local/bin/uglifyjs
            
运用压缩组件:
{% javascripts '@AppBundle/Resources/public/js/*' filter='uglifyjs2' %}
    <script src="{{ asset_url }}"></script>
{% endjavascripts %}

配置压缩组件在debug时自动关闭, 在filter上加 "?"
{% javascripts '@AppBundle/Resources/public/js/*' filter='?uglifyjs2' %}
    <script src="{{ asset_url }}"></script>
{% endjavascripts %}

清理缓存, 压缩重建dump文件


指定filter作用的文件

1. filter单独某些文件:
直接在assetic标签上标示filter

2. filter特定拓展名文件
# app/config/config.yml
assetic:
    filters:
        coffee:
            bin:        /usr/bin/coffee
            apply_to:   "\.coffee$"   //filter拓展名coffee格式的文件


图片优化filter

1. Jpegoptim
# 安装开发包 并配置 app/config/config.yml
assetic:
    filters:
        jpegoptim:
            bin: path/to/jpegoptim
            strip_all: true  //可选, 用于剔除EXIF信息
            max: 70  //图片质量
            
使用
{% image '@AppBundle/Resources/public/images/example.jpg' filter='jpegoptim' output='/images/example.jpg' %}
    <img src="{{ asset_url }}" alt="Example"/>
{% endimage %}



简短语法(twig函数)实现:
# 启用配置 app/config/config.yml
assetic:
    filters:
        jpegoptim:
            bin: path/to/jpegoptim
    twig:
        functions:
            jpegoptim: ~ 或指定输出目录 { output: images/*.jpg }
            
使用   <img src="{{ jpegoptim('@AppBundle/Resources/public/images/example.jpg') }}" alt="Example"/>


  • 打赏
  • 点赞
  • 收藏
  • 分享
共有 人打赏支持
粉丝 21
博文 100
码字总数 93017
作品 1
×
麦拂沙
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: