Reputation: 1547
I'm building web application with symfony2. I'm using Doctrine as db engine. I will need to use some complex database queries to recive data from mysql base. What I discovered ( please correct me if I'm wrong ) is:
Upvotes: 0
Views: 65
Reputation: 3045
Even with an ORM layer in between your application and a database there may be times where you need to write raw SQL queries; for example, if you are producing a report about application usage, or you are calculating intermediate data, etc.
However, in each of those cases you should ask yourself whether or not it would be more appropriate to work with objects rather than raw data. In many cases people assume that they can't achieve their result without going directly to the database level, but they may be surprised to learn that there is really quite a lot you can do with a modern ORM like Doctrine.
In Doctrine, joins are represented by associations, and one of the key benefits of the system is the way in which you can interact with associations through objects rather than raw SQL.
Consider the following "complex" query (okay, it's really not that complex):
SELECT foo.*, bar.*
FROM foo
LEFT JOIN bar ON foo.foo_id = bar.foo_id
WHERE foo.name = "x"
In Doctrine, you can model this with entities. For example, a snippet:
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
* @ORM\Table(name="foo")
*/
class Foo
{
/**
* @ORM\Id
* @ORM\Column(name="foo_id", type="integer")
* @ORM\GeneratedValue
*/
private $id;
/**
* @ORM\Column(name="foo_name", type="string", length=32)
*/
private $name;
/**
* @ORM\OneToMany(targetEntity="Bar", mappedBy="foos")
*/
private $bars;
// more code ...
}
And another:
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
* @ORM\Table(name="bar")
*/
class Bar
{
/**
* @ORM\Id
* @ORM\Column(name="bar_id", type="integer")
* @ORM\GeneratedValue
*/
private $id;
/**
* @ORM\Column(name="bar_name", type="string", length=32)
*/
private $name;
/**
* @ORM\ManyToOne(targetEntity="Foo", inversedBy="bars")
* @ORM\JoinColumn(name="foo_id", referencedColumnName="foo_id")
*/
private $foo;
// more code ...
}
Now, in DQL, we can rewrite the original query:
SELECT f, b
FROM \Your\Namespace\Foo f
LEFT JOIN f.bars b
WHERE f.name = "x"
This query will produce a Foo object or objects, and any Bar objects associated with each, all with only that single query to the database. Using this pattern, you should be able to model the vast majority of useful SQL queries with objects in such a way that their relationships are natural and easy to understand.
One other thing worth noting is that the above DQL query is actually called a "fetch join" because it will hydrate both the Foo object(s) being requested and any Bar objects associated with them. A simpler version of the query would be:
SELECT f
FROM \Your\Namespace\Foo f
WHERE f.name = "x"
This will hydrate only Foo objects in the first query, performing no joins. However, you can still access associated Bar objects (e.g. $foo->getBars()
), and Doctrine will automatically fetch the associated data on as as-needed basis (this is known as "lazy loading"). In all cases you are free to decide whether you want to hydrate some or all of the object graph for an entity, or just retrieve top-level data and allow Doctrine to load the data as needed.
There is a lot of information about this in the Doctrine Association Mapping documentation.
Upvotes: 2