Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

split find into find with required class name and findDocument for finding any document #863

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ Changelog
* Removed deprecated methods HierarchyInterface::getParent/setParent.
Use getParentDocument/setParentDocument instead.

* ``DocumentManager::find`` requires to specify the class name. To find any
document without restricting the class name, use the new
``DocumentManager::findDocument`` method.

* DocumentManager::flush no longer saves the PHPCR session if there are no changes
on the ODM layer.

Expand Down
2 changes: 1 addition & 1 deletion docs/en/reference/association-mapping.rst
Original file line number Diff line number Diff line change
Expand Up @@ -572,7 +572,7 @@ empty ``ArrayCollection`` in your documents constructor::
Now the following code will be working even if the Document hasn't
been associated with a DocumentManager yet::

$group = $documentManager->find(null, $groupId);
$group = $documentManager->findDocument($groupId);
$user = new User();
$user->getGroups()->add($group);

Expand Down
2 changes: 1 addition & 1 deletion docs/en/reference/basic-mapping.rst
Original file line number Diff line number Diff line change
Expand Up @@ -421,7 +421,7 @@ the assigned id if either is missing.
To create a new document, you do something like this::

$doc = new Document();
$doc->setParent($dm->find(null, '/test'));
$doc->setParent($dm->findDocument('/test'));
$doc->setNodename('mynode');
// document is persisted with id /test/mynode

Expand Down
16 changes: 8 additions & 8 deletions docs/en/reference/introduction.rst
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ We write a simple PHP script to generate some sample data::
require_once '../bootstrap.php';

// get the root node to add our data to it
$rootDocument = $documentManager->find(null, '/');
$rootDocument = $documentManager->findDocument('/');

// create a new document
$doc = new \Demo\Document();
Expand Down Expand Up @@ -297,14 +297,14 @@ This script will simply echo the data to the console::

require_once '../bootstrap.php';

$doc = $documentManager->find(null, '/doc');
$doc = $documentManager->findDocument('/doc');

echo 'Found '.$doc->getId() ."\n";
echo 'Title: '.$doc->getTitle()."\n";
echo 'Content: '.$doc->getContent()."\n";

The DocumentManager will automatically determine the document class when
you pass ``null`` as first argument to ``find()``.
you call ``findDocument()`` instead of ``find()``.

Tree traversal
--------------
Expand All @@ -319,7 +319,7 @@ we can traverse them::

use Demo\MyDocument;

$doc = $documentManager->find(null, '/doc');
$doc = $documentManager->findDocument('/doc');

foreach($doc->getChildren() as $child) {
if ($child instanceof MyDocument) {
Expand Down Expand Up @@ -394,7 +394,7 @@ Lets look at an example of document ``A`` referencing ``B``::

We can now create a reference with the following code::

$parent = $dm->find(null, '/');
$parent = $dm->findDocument('/');
$a = new A();
$a->setParent($parent);
$a->setNodename('a');
Expand All @@ -408,7 +408,7 @@ We can now create a reference with the following code::
$dm->flush();
$dm->clear();

$b = $dm->find(null, '/b');
$b = $dm->findDocument('/b');

// output Demo\A
var_dump(get_class($b->getReferrers()));
Expand All @@ -429,7 +429,7 @@ To delete a document, call the ``remove`` method on the ``DocumentManager``::
require_once '../bootstrap.php';

// remove a document
$doc = $documentManager->find(null, '/doc');
$doc = $documentManager->findDocument('/doc');
$documentManager->remove($doc);

// persist all operations
Expand All @@ -448,7 +448,7 @@ by assignment. The latter is for example handy with Symfony forms::
require_once '../bootstrap.php';

// we move a node
$child = $documentManager->find(null, '/doc/child');
$child = $documentManager->findDocument('/doc/child');
$documentManager->move($child, '/newpath');

// persist all operations
Expand Down
4 changes: 2 additions & 2 deletions docs/en/reference/multilang.rst
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ have a translator strategy and a Locale field.
Interacting with translations
-----------------------------

When reading, ``DocumentManager::find()`` uses the default locale (see below how to set that). This means
When reading, the ``DocumentManager::find*`` methods use the default locale (see below how to set that). This means
your reading code does not need to be aware of content translations happening.

If you need to access a document with an explicit locale that might be different from the default locale,
Expand Down Expand Up @@ -271,7 +271,7 @@ Full Example

// Get the document in default language
// (English if you bootstrapped as in the example)
$doc = $dm->find(null, '/my_test_node');
$doc = $dm->findDocument('/my_test_node');

// Get the document in French
$doc = $dm->findTranslation(null, '/my_test_node', 'fr');
Expand Down
4 changes: 2 additions & 2 deletions docs/en/reference/versioning.rst
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ See the Phpdoc for full details on those methods.

**Reading**:

- ``DocumentManager::find()`` works as normal, always gives you the current latest version.
- ``DocumentManager::find*`` methods work as normal, always giving you the current latest version.
- ``DocumentManager::getAllLinearVersions($document)`` returns an array with all version names for this document,
ordered from most recent to oldest version. You can specify an optional limit to only get that many most recent versions.
- ``DocumentManager::findVersionByName($id, $versionName)`` get a detached read-only document for a specific version.
Expand Down Expand Up @@ -184,7 +184,7 @@ Full Example
echo $oldVersion->topic; // "Test"

// find the head version
$article = $dm->find('/test');
$article = $dm->findDocument('/test');
echo $article->topic; // "Newvalue"

// restore the head to the old version
Expand Down
35 changes: 20 additions & 15 deletions docs/en/reference/working-with-objects.rst
Original file line number Diff line number Diff line change
Expand Up @@ -37,20 +37,22 @@ Every document has an identifier, which is its PHPCR path. The path is unique
inside the workspace. Take the following example, where you find an article
with the headline "Hello World" with the ID ``/cms/article/hello-world``::

$article = $documentManager->find(null, '/cms/article/hello-world');
$article = $documentManager->findDocument('/cms/article/hello-world');
$article->setHeadline('Hello World dude!');

$article2 = $documentManager->find(null, '/cms/article/hello-world');
$article2 = $documentManager->findDocument('/cms/article/hello-world');
echo $article2->getHeadline(); // Hello World dude!

.. note::

The first argument to ``find()`` is the document class name. While the ORM
has a table per class and thus always needs the document class name,
PHPCR-ODM has one tree for all documents. The above call will find you
whatever document is at that path. Note that you may optionally specify
the class name to have PHPCR-ODM detect if the document is not of the
expected type.
The first argument to ``find()`` is the document class name. Since PHPCR-ODM
2.0, the class name is required. But while the ORM has a table per class and
thus always needs the document class name, PHPCR-ODM uses one tree for all
documents. ``findDocument()`` finds you whatever document is at the specified
path. If you want to only get the document if it is of your expected type,
e.g. for type safety, use the ``find()`` method with its class name argument.
When using ``find``, PHPCR-ODM will return null if the path exists but the
document is not of the requested class.

In this case, the article is retrieved from the document manager twice,
but modified in between. Doctrine 2 realizes that it is the same ID and will
Expand Down Expand Up @@ -131,7 +133,7 @@ from newly opened DocumentManager::
}
}

$article = $em->find(null, '/cms/article/hello-world');
$article = $em->findDocument('/cms/article/hello-world');

This code retrieves an ``Article`` instance with ID
``/cms/article/hello-world``, executing a single ``getNode()`` operation
Expand All @@ -154,7 +156,7 @@ access these proxies for the first time they will go through the
This lazy-loading process happens behind the scenes, hidden from
your code. Have a look at the following example::

$article = $em->find(null, '/cms/article/hello-world');
$article = $em->findDocument('/cms/article/hello-world');

// accessing a method of the user instance triggers the lazy-load
echo "Author: " . $article->getAuthor()->getName() . "\n";
Expand Down Expand Up @@ -612,23 +614,26 @@ By Primary Key

The most basic way to query for a persisted document is by its
identifier (PHPCR path) using the
``DocumentManager::find(null, $id)`` method. Here is an
``DocumentManager::find($className, $id)`` method. Here is an
example::

/** @var $em DocumentManager */
$user = $em->find(User::class, $id);

The return value is either the found document instance or null if no
instance could be found with the given identifier.
instance of the specified class can be found with the given identifier.

If you do not want to specify the class, you can use the ``findDocument($id)``
method instead.

If you need several documents and know their paths, you can have a considerable
performance gain by using ``DocumentManager::findMany(null, $ids)`` as then
all those documents are loaded from the repository in one request.

You can also specify the class name instead of null to filter to only find
instances of that class. If you go through the repository for a document class
this is equivalent to calling find on the ``DocumentManager`` with that document
class.
instances of that class. If you call ``find`` on the repository of a document
class, this is equivalent to calling ``find`` on the ``DocumentManager`` with
that document class.


By Simple Conditions
Expand Down
5 changes: 5 additions & 0 deletions lib/Doctrine/ODM/PHPCR/Decorator/DocumentManagerDecorator.php
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,11 @@ public function isOpen(): bool
return $this->wrapped->isOpen();
}

public function findDocument(string $id): ?object
{
return $this->wrapped->findDocument($id);
}

public function findMany(?string $className, array $ids): Collection
{
return $this->wrapped->findMany($className, $ids);
Expand Down
31 changes: 23 additions & 8 deletions lib/Doctrine/ODM/PHPCR/DocumentManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -180,26 +180,41 @@ public function getClassMetadata($className): ClassMetadata
*
* Will return null if the document was not found. A document is considered
* not found if the data at $id is not instance of of the specified
* $className. To get the document regardless of its class, pass null.
* $className.
*
* To get a document regardless of its class, use the ``findDocument`` method.
*
* If the document is translatable, then the language chooser strategy is
* used to load the best suited language for the translatable fields.
*
* @param string|null $className optional object class name to use
* @param string $id the path or uuid of the document to find
* @param string $id the path or uuid of the document to find
*
* @return object|null the document if found, otherwise null
*/
public function find($className, $id): ?object
public function find(string $className, mixed $id): ?object
{
if (!is_string($id)) {
throw new \InvalidArgumentException('PHPCR-ODM ids must be of type string (either uuid or path), you passed '.gettype($id));
}

return $this->doFind($className, $id);
}

public function findDocument(string $id): ?object
{
return $this->doFind(null, $id);
}

private function doFind(?string $className, mixed $id): ?object
{
try {
if (UUIDHelper::isUUID($id)) {
try {
$id = $this->session->getNodeByIdentifier($id)->getPath();
} catch (ItemNotFoundException $e) {
} catch (ItemNotFoundException) {
return null;
}
} elseif (0 !== strpos($id, '/')) {
} elseif (!str_starts_with($id, '/')) {
$id = '/'.$id;
}

Expand All @@ -209,7 +224,7 @@ public function find($className, $id): ?object
$this->unitOfWork->validateClassName($document, $className);

return $document;
} catch (ClassMismatchException $e) {
} catch (ClassMismatchException) {
return null;
}
}
Expand All @@ -222,7 +237,7 @@ public function find($className, $id): ?object

try {
return $this->unitOfWork->getOrCreateDocument($className, $node, $hints);
} catch (ClassMismatchException $e) {
} catch (ClassMismatchException) {
return null;
}
}
Expand Down
12 changes: 12 additions & 0 deletions lib/Doctrine/ODM/PHPCR/DocumentManagerInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,18 @@ public function getConfiguration(): Configuration;
*/
public function isOpen(): bool;

/**
* Finds an object by its identifier.
*
* This is an alternative to ``find`` that does not require you to specify the class name.
* If the PHPCR node at $id does not have the PHPCR-ODM metadata, this method returns null.
*
* Apart from the class name, it has the same semantics as `find`.
*
* @param string $id the identity of the object to find
*/
public function findDocument(string $id): ?object;

/**
* Finds many documents by id.
*
Expand Down
2 changes: 1 addition & 1 deletion lib/Doctrine/ODM/PHPCR/UnitOfWork.php
Original file line number Diff line number Diff line change
Expand Up @@ -2822,7 +2822,7 @@ public function restoreVersion(object $documentVersion, bool $removeExisting): v
$oid = \spl_object_hash($documentVersion);
$history = $this->documentHistory[$oid];
$version = $this->documentVersion[$oid];
$document = $this->dm->find(null, $history->getVersionableIdentifier());
$document = $this->dm->findDocument($history->getVersionableIdentifier());
$vm = $this->session->getWorkspace()->getVersionManager();

$vm->restore($removeExisting, $version);
Expand Down
2 changes: 1 addition & 1 deletion tests/Doctrine/Tests/ODM/PHPCR/DocumentManagerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public function testFind(): void

$dm = DocumentManager::create($session, $config);

$nonExistent = $dm->find(null, $fakeUuid);
$nonExistent = $dm->findDocument($fakeUuid);

$this->assertNull($nonExistent);
}
Expand Down
Loading
Loading