先进的原则使用
乔纳森·h·工资
写一个原则的行为
在本节中,我们将展示如何编写一个行为使用原则1.2。我们将创建一个示例,使您可以轻松地保持缓存数的关系,这样你不需要每一次查询计数。
的功能非常简单。对于所有你想维护一个有价值的关系,这种行为将列添加到模型来存储当前的计数。
的模式
这是开始我们将使用的模式。以后我们将修改和添加找
定义的行为我们要写:
#配置/理论/模式。yml线程:列:标题:类型:字符串(255)notnull:真正的帖子:列:thread_id:类型:整数notnull:真正的身体:类型:clob notnull:真正的关系:线程:onDelete:级联foreignAlias:职位
现在我们可以构建一切的模式:
php syob娱乐下载mfony学说:美元构建——所有
模板
首先我们需要编写的基本Doctrine_Template
儿童类,它负责将列添加到模型,该模型将存储数量。
您可以简单地把这个地方的一个项目lib /
目录和symfony将能够为您自ob娱乐下载动装载:
/ / lib / count_cache / CountCache.class.php类CountCache扩展Doctrine_Template{公共函数setTableDefinition(){}公共函数设置(){}}
现在让我们修改帖子
模型找
的CountCache
行为:
#配置/理论/模式。yml:找:CountCache: ~ #…
现在,我们有帖子
模型使用CountCache
行为让我解释一下发生了什么。
当模型实例化的映射信息,任何的附加行为setTableDefinition ()
和设置()
方法调用。就像你的一样BasePost
类lib /模型/理论/基地/ BasePost.class.php
。这允许您添加到任何模型塞n '玩的方式。这可以列、关系、事件监听器等。
现在你了解一点关于正在发生的事情,让我们做的CountCache
行为实际上做某事:
类CountCache扩展Doctrine_Template{受保护的_options美元=数组(“关系”= >数组());公共函数setTableDefinition(){foreach(这个美元- > _options(“关系”]作为美元的关系= >选择美元){/ /构建列名如果没有如果(!收取(选择美元(“columnName”])){这个美元- > _options(“关系”](美元的关系](“columnName”]=“num_”.Doctrine_Inflector::tableize(美元的关系);}/ /将列添加到相关模型columnName美元=这个美元- > _options(“关系”](美元的关系](“columnName”];relatedTable美元=这个美元- > _table - >getRelation(美元的关系)- >可以获得的();这个美元- > _options(“关系”](美元的关系](“名称”]=relatedTable美元- >getOption(“名字”);relatedTable美元- >setColumn(columnName美元,“整数”,零,数组(“默认”= >0));}}}
上面的代码将列添加到维护依靠相关模型。在我们的例子中,我们将行为添加到帖子
模型线程
的关系。我们要保持文章任何给定的数量线程
在一列命名实例num_posts
。现在修改YAML模式定义的额外选项行为:
#……职位:找:CountCache:关系:线程:columnName: num_posts foreignAlias:文章#……
现在,线程
模型有一个num_posts
列,我们将保持更新帖子,每个线程的数量。
事件监听器
下一步建设行为是编写一个记录事件监听器负责保持数日期,当我们插入新记录,删除记录或批DQL删除记录:
类CountCache扩展Doctrine_Template{/ /……公共函数setTableDefinition(){/ /……这个美元- >addListener(新CountCacheListener(这个美元- > _options));}}
在我们继续下去之前,我们需要定义CountCacheListener
类,它扩展了Doctrine_Record_Listener
。它接受一个数组的选项仅仅是转发到侦听器的模板:
/ / lib /模型/ count_cache / CountCacheListener.class.php类CountCacheListener扩展Doctrine_Record_Listener{受保护的_options美元;公共函数__construct(数组选择美元){这个美元- > _options =选择美元;}}
现在我们必须利用以下事件为了保持我们的计算日期:
postInsert ():增量计数时插入一个新对象;
postDelete ():计数,当一个对象被删除的精神性;
preDqlDelete ():衰减计算时通过DQL删除记录被删除。
首先,让我们定义postInsert ()
方法:
类CountCacheListener扩展Doctrine_Record_Listener{/ /……公共函数postInsert(Doctrine_Event美元的事件){美元调用程序=美元的事件- >getInvoker();foreach(这个美元- > _options(“关系”]作为美元的关系= >选择美元){美元的表=学说::可以获得的(选择美元(“名称”]);美元的关系=美元的表- >getRelation(选择美元(“foreignAlias”]);美元的表- >createQuery()- >更新()- >集(选择美元(“columnName”],选择美元(“columnName”]。“+ 1”)- >在哪里(美元的关系(“本地”]。“= ?”,美元调用程序- >美元的关系(“外国”])- >执行();}}}
上面的代码将增加数量,一个用于所有配置的关系通过发行DQL更新查询时插入一个新对象像下面:
美元的帖子=新帖子();美元的帖子- >thread_id=1;美元的帖子- >身体=“身体的”;美元的帖子- >保存();
的线程
与一个id
的1
会得到num_posts
列增加了1
。
现在数量正在增加在插入新对象时,我们需要处理当对象被删除和递减计数。我们将通过实施postDelete ()
方法:
类CountCacheListener扩展Doctrine_Record_Listener{/ /……公共函数postDelete(Doctrine_Event美元的事件){美元调用程序=美元的事件- >getInvoker();foreach(这个美元- > _options(“关系”]作为美元的关系= >选择美元){美元的表=学说::可以获得的(选择美元(“名称”]);美元的关系=美元的表- >getRelation(选择美元(“foreignAlias”]);美元的表- >createQuery()- >更新()- >集(选择美元(“columnName”],选择美元(“columnName”]。“- 1”)- >在哪里(美元的关系(“本地”]。“= ?”,美元调用程序- >美元的关系(“外国”])- >执行();}}}
上面的postDelete ()
方法是几乎相同的postInsert ()
唯一的区别是我们减量num_posts
列的1
而不是增加。它处理以下代码如果我们删除美元的帖子
记录我们之前保存:
美元的帖子- >删除();
最后一块拼图是处理时使用DQL更新记录被删除。我们可以解决这个问题用preDqlDelete ()
方法:
类CountCacheListener扩展Doctrine_Record_Listener{/ /……公共函数preDqlDelete(Doctrine_Event美元的事件){foreach(这个美元- > _options(“关系”]作为美元的关系= >选择美元){美元的表=学说::可以获得的(选择美元(“名称”]);美元的关系=美元的表- >getRelation(选择美元(“foreignAlias”]);美元的问=克隆美元的事件- >getQuery();美元的问- >选择(美元的关系(“外国”]);$ id=美元的问- >执行(数组(),原则::HYDRATE_NONE);foreach($ id作为$ id){$ id=$ id(0];美元的表- >createQuery()- >更新()- >集(选择美元(“columnName”],选择美元(“columnName”]。“- 1”)- >在哪里(美元的关系(“本地”]。“= ?”,$ id)- >执行();}}}}
上面的代码克隆DQL删除
查询和转换它选择
它允许我们检索吗ID
年代,将被删除,这样我们可以更新项删除这些记录。
现在我们有下面的场景照顾和计数将递减如果我们要做到以下几点:
原则::可以获得的(“职位”)- >createQuery()- >删除()- >在哪里(“id = ?”,1)- >执行();
甚至如果我们正确删除多条记录数仍将递减:
原则::可以获得的(“职位”)- >createQuery()- >删除()- >在哪里(“身体?”,“%酷%”)- >执行();
请注意
为了使preDqlDelete ()
方法调用您必须启用一个属性。DQL回调是默认情况下由于他们花费一点额外的。所以,如果你想使用它们,你必须让他们。
美元的经理- >setAttribute(Doctrine_Core::ATTR_USE_DQL_CALLBACKS,真正的);
就是这样!完成的行为。我们要做的最后一件事就是对其进行测试。
测试
现在我们已经实现的代码,让我们给它一个测试运行一些示例数据装置:
#数据/夹具/数据。yml线程:thread1:标题:测试线程的帖子:post1:身体:这是我的身体测试线程post2:身体:这是很酷的post3:身体:丫很酷
现在,构建一切又和负载数据设备:
php syob娱乐下载mfony学说:美元构建——所有和负载
现在一切都是构建和数据加载装置;让我们运行一个测试,看看数量一直保持日期:
php syob娱乐下载mfony学说:美元dql”从线程t, t。帖子s p" doctrine - executing: "FROM Thread t, t.Posts p" () doctrine - id: '1' doctrine - title: 'Test Thread' doctrine - num_posts: '3' doctrine - Posts: doctrine - - doctrine - id: '1' doctrine - thread_id: '1' doctrine - body: 'This is the body of my test thread' doctrine - - doctrine - id: '2' doctrine - thread_id: '1' doctrine - body: 'This is really cool' doctrine - - doctrine - id: '3' doctrine - thread_id: '1' doctrine - body: 'Ya it is pretty cool'
你会看到的线程
模型有一个num_posts
列的值是3。如果我们要删除的一个帖子下面的代码将为您递减计数:
美元的帖子= Doctrine_Core::可以获得的(“职位”)- >找到(1);美元的帖子- >删除();
你会发现记录被删除和更新计数:
php syob娱乐下载mfony学说:美元dql”从线程t, t。帖子s p" doctrine - executing: "FROM Thread t, t.Posts p" () doctrine - id: '1' doctrine - title: 'Test Thread' doctrine - num_posts: '2' doctrine - Posts: doctrine - - doctrine - id: '2' doctrine - thread_id: '1' doctrine - body: 'This is really cool' doctrine - - doctrine - id: '3' doctrine - thread_id: '1' doctrine - body: 'Ya it is pretty cool'
这甚至适用如果我们DQL进行批量删除剩下的两个记录删除查询:
Doctrine_Core::可以获得的(“职位”)- >createQuery()- >删除()- >在哪里(“身体?”,“%酷%”)- >执行();
现在我们已经和删除所有相关的帖子num_posts
应该是零:
php syob娱乐下载mfony学说:美元dql”从线程t, t。帖子s p" doctrine - executing: "FROM Thread t, t.Posts p" () doctrine - id: '1' doctrine - title: 'Test Thread' doctrine - num_posts: '0' doctrine - Posts: { }
这就是它!我希望这篇文章既有用,您了解了一些关于行为和行为本身也对你有用!
使用原则结果缓存
在繁忙的web应用程序,它是一种常见的需要缓存信息保存您的CPU资源。最新的教义1.2我们已经做了很多改进结果集缓存,给你更多的控制从缓存中删除缓存项的司机。之前是不可能指定缓存键用于存储缓存条目,所以你不能真的确定缓存条目以删除它。
在本节中,我们将向您展示一个简单的例子,如何利用结果集缓存来缓存相关的所有用户查询和使用事件,确保他们正确清除一些数据时发生了变化。
我们的模式
对于本例,我们使用以下模式:
#配置/理论/模式。yml用户:列:用户名:类型:字符串(255)notnull:真正的独特:真正的密码:类型:字符串(255)notnull:真的
现在让我们构建从模式使用下面的命令:
php syob娱乐下载mfony学说:美元构建——所有
一旦你这样做,你应该有以下用户
类为您生成:
/ / lib /模型/理论/ User.class.php/ * * *用户* *这个类已经被教义ORM框架自动生成的* * @package # #包# # * @subpackage # #分包# # * @author # #名# # < # #邮件# # > * @version SVN: $ Id:构建器。php 6508 2009-10-14 06:28:49Z jwage $ * /类用户扩展BaseUser{}
在本文的后面您将需要添加一些代码来这门课所以要注意的。
配置结果缓存
为了使用结果缓存,我们需要配置缓存司机查询使用。这可以通过设置完成ATTR_RESULT_CACHE
属性。我们将使用APC缓存驱动程序,因为它是生产的最佳选择。如果你没有APC可用,您可以使用Doctrine_Cache_Db
或Doctrine_Cache_Array
司机出于测试目的。
我们可以设置这个属性ProjectConfiguration
类。定义一个configureDoctrine ()
方法:
/ /配置/ ProjectConfiguration.class.php/ /……类ProjectConfiguration扩展sfProjectConfiguration{/ /……公共函数configureDoctrine(Doctrine_Manager美元的经理){美元的经理- >setAttribute(Doctrine_Core::ATTR_RESULT_CACHE,新Doctrine_Cache_Apc());}}
现在我们有了结果缓存配置驱动程序,我们可以开始实际使用这个驱动程序缓存查询的结果集。
示例查询
现在想象一下,在您的应用程序有很多用户相关的查询和你想清楚他们当一些用户数据发生了变化。
这是一个简单的查询,我们可能使用呈现用户按照字母顺序排列的列表:
美元的问= Doctrine_Core::可以获得的(“用户”)- >createQuery(“u”)- >orderBy(“u。用户名ASC的);
现在,我们可以打开缓存查询使用useResultCache ()
方法:
美元的问- >useResultCache(真正的,3600年,“users_index”);
请注意
注意第三个参数。这是关键,将用于在缓存中存储的缓存条目结果司机。这让我们很容易识别出查询和删除它从缓存中司机。
当我们执行结果的查询,将查询数据库并将它们存储在缓存中司机在命名的关键users_index
和任何后续请求将从缓存中获取信息驱动程序,而不是问数据库:
美元的用户=美元的问- >执行();
请注意
这不仅节省您的数据库服务器上的处理,也绕过整个水化过程学说存储水分数据。这意味着它将缓解处理您的web服务器上。
如果我们检查缓存中的司机,你会发现有一个条目users_index
:
如果(cacheDriver美元- >包含(“users_index”)){回声“缓存的存在”;}其他的{回声缓存中不存在的;}
删除缓存
现在查询缓存,我们需要学习一下如何删除缓存。我们可以使用缓存API或司机手动删除它我们可以利用一些事件时自动清除缓存条目用户插入或修改。
缓存司机API
首先,我们将展示原始API的缓存司机在我们在一个事件中实现它。
提示
获得结果缓存可以从驱动程序实例Doctrine_Manager
类实例。
cacheDriver美元=美元的经理- >getAttribute(Doctrine_Core::ATTR_RESULT_CACHE);
如果你不已经有访问美元的经理
变量已经可以用下面的代码检索实例。
美元的经理= Doctrine_Manager::getInstance();
现在我们可以开始使用API来删除缓存条目:
cacheDriver美元- >删除(“users_index”);
你可能有一个以上的查询前缀用户宏观
并删除会有意义结果的缓存。在这种情况下,delete ()
方法本身不会工作。我们有一个方法deleteByPrefix ()
,它允许我们删除任何包含给定前缀缓存条目。这是一个例子:
cacheDriver美元- >deleteByPrefix(“用户宏观”);
我们有一些其他方便的方法,如果我们可以使用删除缓存条目deleteByPrefix ()
对你是不够的:
deleteBySuffix(后缀)
:删除缓存项,通过后缀;deleteByRegexp(正则表达式)
:删除缓存条目通过正则表达式匹配的;deleteAll ()
:删除所有缓存条目。
删除与事件
理想的方法清除缓存会自动清除一些用户数据修改。我们可以通过实现一个postSave ()
事件在我们的用户
模型类的定义。
还记得用户
类我们之前讲过吗?现在我们需要添加一些代码来所以你最喜欢的编辑器中打开类并添加以下postSave ()
方法:
/ / lib /模型/理论/ User.class.php类用户扩展BaseUser{/ /……公共函数postSave(美元的事件){cacheDriver美元=这个美元- >可以获得的()- >getAttribute(Doctrine_Core::ATTR_RESULT_CACHE);cacheDriver美元- >deleteByPrefix(“用户宏观”);}}
现在如果我们更新用户或插入一个新用户将清除缓存相关的所有用户查询:
$ user=新用户();$ user- >用户名=“jwage”;$ user- >密码=“changeme”;$ user- >保存();
下次调用查询缓存中不存在,将新鲜的从数据库中获取数据和缓存再后续请求。
虽然这个例子很简单,它应该很演示如何使用这些功能来实现细粒度的教义查询缓存。
写一个教义保湿液
学说的一个重要的特性是转换的能力Doctrine_Query
对象的各种结果集的结构。这是教义加湿器的工作,直到1.2学说,加湿器都硬编码,而不是开放开发人员编写自定义的。现在已经改变可以编写一个定制的水合器并创建的任何数据从数据库的数据结构,需要给你执行的时候Doctrine_Query
实例。
在这个例子中,我们将构建一个保湿液,将是非常简单和容易理解的,但非常有用。它将允许您选择两列和水合物数据平面数组第一个选择的列是关键,第二选择列的值。
模式和夹具
开始我们首先需要一个简单的模式来运行我们的测试。我们将只使用一个简单的用户
模型:
#配置/理论/模式。yml用户:列:用户名:字符串(255)is_active:字符串(255)
我们还需要一些数据测试夹具,所以复制装置从下面:
#数据/夹具/数据。jwage yml用户:user1:用户名:密码:changeme is_active: 1 user2:用户名:密码:jonwage changeme is_active: 0
现在构建一切使用下面的命令:
php syob娱乐下载mfony学说:美元构建——所有和负载
编写保湿液
写一个水化器所有我们需要做的是编写一个扩展的新类Doctrine_Hydrator_Abstract
而且必须实现一个hydrateResultSet(支撑美元)
方法。它接收PDOStatement
实例用于执行查询。我们可以使用这句话来自PDO的原始查询的结果然后变换自己的结构。
让我们创建一个新类命名KeyValuePairHydrator
并将其放入lib /
目录,以便symfony可以自动装载ob娱乐下载它:
/ / lib / KeyValuePairHydrator.class.php类KeyValuePairHydrator扩展Doctrine_Hydrator_Abstract{公共函数hydrateResultSet(支撑美元){返回支撑美元- >fetchAll(Doctrine_Core::FETCH_NUM);}}
上面的代码像现在这样只会返回数据完全是PDO。这并不是我们想要的。我们想改变我们自己的关键数据= >值对结构。让我们修改hydrateResultSet ()
方法有点做我们想做的事:
/ / lib / KeyValuePairHydrator.class.php类KeyValuePairHydrator扩展Doctrine_Hydrator_Abstract{公共函数hydrateResultSet(支撑美元){美元的结果=支撑美元- >fetchAll(Doctrine_Core::FETCH_NUM);美元的数组=数组();foreach(美元的结果作为美元的结果){美元的数组(美元的结果(0]]=美元的结果(1];}返回美元的数组;}}
这很容易!水合器代码完成后,这正是我们想要测试一下!
使用保湿液
使用和测试保湿液我们首先需要注册到学说,这样当我们执行一些查询,水合器类的教义意识到我们所写的。
要做到这一点,在注册它Doctrine_Manager
实例的ProjectConfiguration
:
/ /配置/ ProjectConfiguration.class.php/ /……类ProjectConfiguration扩展sfProjectConfiguration{/ /……公共函数configureDoctrine(Doctrine_Manager美元的经理){美元的经理- >registerHydrator(“key_value_pair”,“KeyValuePairHydrator”);}}
现在我们有水合器注册,我们可以使用它Doctrine_Query
实例。这是一个例子:
美元的问= Doctrine_Core::可以获得的(“用户”)- >createQuery(“u”)- >选择(“u。用户名、u.is_active”);美元的结果=美元的问- >执行(数组(),“key_value_pair”);print_r(美元的结果);
执行上面的查询与数据设备我们上面定义会导致以下:
数组([jwage] = > 1 [jonwage] = > 0)
这是它!很简单不是吗?我希望这对你会有用的,因此社区得到了一些很棒的新加湿器的贡献。欧宝体育平台怎么样
这项工作在Creative Commons许可Attribution-Share都3.0 Unported许可执照。