1
0
mirror of synced 2024-12-14 07:06:04 +03:00

fixed typos

This commit is contained in:
Ralfas 2010-10-05 13:09:10 +01:00
parent 6b01986c48
commit 8ac6d29c74
6 changed files with 20 additions and 20 deletions

View File

@ -248,11 +248,11 @@ code in `Account::getBalance()` and `Account:addEntry()`:
} }
This is a very simple change, but all the tests still pass. Our account entities return This is a very simple change, but all the tests still pass. Our account entities return
the correct balance. Now calling the `Account::getBalance()` method will not occour the the correct balance. Now calling the `Account::getBalance()` method will not occur the
overhead of loading all entries anymore. Adding a new Entry to the `Account::$entities` overhead of loading all entries anymore. Adding a new Entry to the `Account::$entities`
will also not initialize the collection internally. will also not initialize the collection internally.
Adding a new entry is therefore very performant and explictly hooked into the domain model. Adding a new entry is therefore very performant and explicitly hooked into the domain model.
It will only update the account with the current balance and insert the new entry into the database. It will only update the account with the current balance and insert the new entry into the database.
## Tackling Race Conditions with Aggregate Fields ## Tackling Race Conditions with Aggregate Fields
@ -293,7 +293,7 @@ Optimistic locking is as easy as adding a version column:
The previous example would then throw an exception in the face of whatever request The previous example would then throw an exception in the face of whatever request
saves the entity last (and would create the inconsistent state). saves the entity last (and would create the inconsistent state).
Pessimmistic locking requires an additional flag set on the `EntityManager::find()` Pessimistic locking requires an additional flag set on the `EntityManager::find()`
call, enabling write locking directly in the database using a FOR UPDATE. call, enabling write locking directly in the database using a FOR UPDATE.
[php] [php]

View File

@ -1,13 +1,13 @@
# Extending DQL in Doctrine 2: Custom AST Walkers # Extending DQL in Doctrine 2: Custom AST Walkers
The Doctrine Query Language (DQL) is a propriotary sql-dialect that substitutes The Doctrine Query Language (DQL) is a proprietary sql-dialect that substitutes
tables and columns for Entity names and their fields. Using DQL you write a query tables and columns for Entity names and their fields. Using DQL you write a query
against the database using your entities. With the help of the metadata you against the database using your entities. With the help of the metadata you
can write very concise, compact and powerful queries that are then translated can write very concise, compact and powerful queries that are then translated
into SQL by the Doctrine ORM. into SQL by the Doctrine ORM.
In Doctrine 1 the DQL language was not implemented using a real parser. This In Doctrine 1 the DQL language was not implemented using a real parser. This
made modifications of the DQL by the user impossible. Doctrine 2 in constrast made modifications of the DQL by the user impossible. Doctrine 2 in contrast
has a real parser for the DQL language, which transforms the DQL statement has a real parser for the DQL language, which transforms the DQL statement
into an [Abstract Syntax Tree](http://en.wikipedia.org/wiki/Abstract_syntax_tree) into an [Abstract Syntax Tree](http://en.wikipedia.org/wiki/Abstract_syntax_tree)
and generates the appropriate SQL statement for it. Since this process is and generates the appropriate SQL statement for it. Since this process is
@ -130,7 +130,7 @@ execution plans. You can write your own output walker to introduce certain
keywords using the Query Hint API. A query hint can be set via `Query::setHint($name, $value)` keywords using the Query Hint API. A query hint can be set via `Query::setHint($name, $value)`
as shown in the previous example with the `HINT_CUSTOM_TREE_WALKERS` query hint. as shown in the previous example with the `HINT_CUSTOM_TREE_WALKERS` query hint.
We will implement a custom Output Walker that allows to specifiy the SQL_NO_CACHE We will implement a custom Output Walker that allows to specify the SQL_NO_CACHE
query hint. query hint.
[php] [php]

View File

@ -48,7 +48,7 @@ takes two dates as argument and calculates the difference in days with `date1-da
The DQL parser is a top-down recursive descent parser to generate the The DQL parser is a top-down recursive descent parser to generate the
Abstract-Syntax Tree (AST) and uses a TreeWalker approach to generate the appropriate Abstract-Syntax Tree (AST) and uses a TreeWalker approach to generate the appropriate
SQL from the AST. This makes reading the Parser/TreeWalker code managable SQL from the AST. This makes reading the Parser/TreeWalker code manageable
in a finite amount of time. in a finite amount of time.
The `FunctionNode` class I referred to earlier requires you to implement The `FunctionNode` class I referred to earlier requires you to implement
@ -98,13 +98,13 @@ to the generation of a DateDiff FunctionNode somewhere in the AST of the
dql statement. dql statement.
The `ArithmeticPrimary` method call is the most common denominator of valid The `ArithmeticPrimary` method call is the most common denominator of valid
EBNF tokens taken from the [DQL EBNF grammer](http://www.doctrine-project.org/documentation/manual/2_0/en/dql-doctrine-query-language#ebnf) EBNF tokens taken from the [DQL EBNF grammar](http://www.doctrine-project.org/documentation/manual/2_0/en/dql-doctrine-query-language#ebnf)
that matches our requirements for valid input into the DateDiff Dql function. that matches our requirements for valid input into the DateDiff Dql function.
Picking the right tokens for your methods is a tricky business, but the EBNF Picking the right tokens for your methods is a tricky business, but the EBNF
grammer is pretty helpful finding it, as is looking at the Parser source code. grammar is pretty helpful finding it, as is looking at the Parser source code.
Now in the TreeWalker process we have to pick up this node and generate SQL Now in the TreeWalker process we have to pick up this node and generate SQL
from it, which apprently is quite easy looking at the code in (7). Since from it, which apparently is quite easy looking at the code in (7). Since
we don't know which type of AST Node the first and second Date expression we don't know which type of AST Node the first and second Date expression
are we are just dispatching them back to the SQL Walker to generate SQL from are we are just dispatching them back to the SQL Walker to generate SQL from
and then wrap our DATEDIFF function call around this output. and then wrap our DATEDIFF function call around this output.
@ -125,7 +125,7 @@ We can do fancy stuff like:
Often useful it the ability to do some simple date calculations in your DQL query Often useful it the ability to do some simple date calculations in your DQL query
using [MySql's DATE_ADD function](http://dev.mysql.com/doc/refman/5.1/en/date-and-time-functions.html#function_date-add). using [MySql's DATE_ADD function](http://dev.mysql.com/doc/refman/5.1/en/date-and-time-functions.html#function_date-add).
I'll skip the bla and show the code for this function: I'll skip the blah and show the code for this function:
[php] [php]
/** /**
@ -176,7 +176,7 @@ the value of the `T_IDENTIFIER` token for the Date Interval unit, for example th
The above method now only supports the specification using `INTERVAL`, to also The above method now only supports the specification using `INTERVAL`, to also
allow a real date in DATE_ADD we need to add some decision logic to the parsing allow a real date in DATE_ADD we need to add some decision logic to the parsing
process (makes up for a nice excercise). process (makes up for a nice exercise).
Now as you see, the Parsing process doesn't catch all the possible SQL errors, Now as you see, the Parsing process doesn't catch all the possible SQL errors,
here we don't match for all the valid inputs for the interval unit. here we don't match for all the valid inputs for the interval unit.

View File

@ -1,5 +1,5 @@
The NOTIFY changetracking policy is the most effective changetracking policy provided by Doctrine but it requires some boilerplate code. This recipe will show you how this boilerplate code should look like. We will implement it on a [Layer Supertype](http://martinfowler.com/eaaCatalog/layerSupertype.html) for all our domain objects. The NOTIFY change-tracking policy is the most effective change-tracking policy provided by Doctrine but it requires some boilerplate code. This recipe will show you how this boilerplate code should look like. We will implement it on a [Layer Supertype](http://martinfowler.com/eaaCatalog/layerSupertype.html) for all our domain objects.
++ Implementing NotifyPropertyChanged ++ Implementing NotifyPropertyChanged

View File

@ -13,15 +13,15 @@ Given a Content-Management-System, we probably want to add / edit some so-called
So, in this scenario, when building your CMS, you will surely add lots of blocks and panels to your pages and you will find yourself highly uncomfortable because of the following: So, in this scenario, when building your CMS, you will surely add lots of blocks and panels to your pages and you will find yourself highly uncomfortable because of the following:
* Every existing page needs to know about the panels it contains - therefore, you'll have an association to your panels. But if you've got several types of panels - what do you do? Add an association to * Every existing page needs to know about the panels it contains - therefore, you'll have an association to your panels. But if you've got several types of panels - what do you do? Add an association to
every paneltype? This wouldn't be flexible. You might be tempted to add an AbstractPanelEntity and an AbstractBlockEntity that use class inheritance. Your page could then only confer to the AbstractPanelType and Doctrine 2 would do the rest for you, i.e. load the right entites. But - you'll for sure have lots of panels and blocks, and even worse, you'd have to edit the discriminator map *manually* every time you or another developer implements a new block / entity. This would tear down any effort of modular programming. every panel-type? This wouldn't be flexible. You might be tempted to add an AbstractPanelEntity and an AbstractBlockEntity that use class inheritance. Your page could then only confer to the AbstractPanelType and Doctrine 2 would do the rest for you, i.e. load the right entities. But - you'll for sure have lots of panels and blocks, and even worse, you'd have to edit the discriminator map *manually* every time you or another developer implements a new block / entity. This would tear down any effort of modular programming.
Therefore, we need something thats far more flexible. Therefore, we need something thats far more flexible.
++ Solution ++ Solution
The solution itself is pretty easy. We will have one base class that will be loaded via the page and that has specific behaviour - a Block class might render the frontend and even the backend, for example. Now, every block that you'll write might look different or need different data - therefore, we'll offer an API to these methods but internally, we use a strategy that exactly knows what to do. The solution itself is pretty easy. We will have one base class that will be loaded via the page and that has specific behaviour - a Block class might render the front-end and even the backend, for example. Now, every block that you'll write might look different or need different data - therefore, we'll offer an API to these methods but internally, we use a strategy that exactly knows what to do.
First of all, we need to make sure that we have an interface that contains every needed action. Such actions would be rendering the frontend or the backend, solving dependencies (blocks that are supposed to be placed in the sidebar could refuse to be placed in the middle of your page, for example). First of all, we need to make sure that we have an interface that contains every needed action. Such actions would be rendering the front-end or the backend, solving dependencies (blocks that are supposed to be placed in the sidebar could refuse to be placed in the middle of your page, for example).
Such an interface could look like this: Such an interface could look like this:

View File

@ -1,5 +1,5 @@
Doctrine 2 does not ship with any internal validators, the reason being that Doctrine 2 does not ship with any internal validators, the reason being that
we think all the frameworks out there already ship with quite decents ones that can be integrated we think all the frameworks out there already ship with quite decent ones that can be integrated
into your Domain easily. What we offer are hooks to execute any kind of validation. into your Domain easily. What we offer are hooks to execute any kind of validation.
> **Note** > **Note**
@ -7,7 +7,7 @@ into your Domain easily. What we offer are hooks to execute any kind of validati
> one of many options. Of course you can also perform validations in value setters > one of many options. Of course you can also perform validations in value setters
> or any other method of your entities that are used in your code. > or any other method of your entities that are used in your code.
Entities can register lifecycle evnt methods with Doctrine that are called on Entities can register lifecycle event methods with Doctrine that are called on
different occasions. For validation we would need to hook into the different occasions. For validation we would need to hook into the
events called before persisting and updating. Even though we don't support events called before persisting and updating. Even though we don't support
validation out of the box, the implementation is even simpler than in Doctrine 1 validation out of the box, the implementation is even simpler than in Doctrine 1
@ -71,7 +71,7 @@ this will happen before Beta 1 though.
Now validation is performed whenever you call `EntityManager#persist($order)` Now validation is performed whenever you call `EntityManager#persist($order)`
or when you call `EntityManager#flush()` and an order is about to be updated. or when you call `EntityManager#flush()` and an order is about to be updated.
Any Exception that happens in the lifecycle callbacks will be catched by the Any Exception that happens in the lifecycle callbacks will be cached by the
EntityManager and the current transaction is rolled back. EntityManager and the current transaction is rolled back.
Of course you can do any type of primitive checks, not null, email-validation, string size, Of course you can do any type of primitive checks, not null, email-validation, string size,