[DDC-497][DDC-500][DDC-342] Fixed. Persister polishing and refactoring. More to come for that, but after beta1.
This commit is contained in:
parent
4b71afe7c2
commit
760ea34a0c
@ -1,7 +1,5 @@
|
||||
<?php
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
@ -29,10 +27,7 @@ use \ReflectionClass,
|
||||
/**
|
||||
* A reader for docblock annotations.
|
||||
*
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
* @link www.doctrine-project.org
|
||||
* @since 2.0
|
||||
* @version $Revision: 3938 $
|
||||
* @author Benjamin Eberlei <kontakt@beberlei.de>
|
||||
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
|
||||
* @author Jonathan Wage <jonwage@gmail.com>
|
||||
|
@ -22,10 +22,7 @@ namespace Doctrine\Common\Annotations;
|
||||
/**
|
||||
* A simple parser for docblock annotations.
|
||||
*
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
* @link www.doctrine-project.org
|
||||
* @since 2.0
|
||||
* @version $Revision: 3938 $
|
||||
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
|
||||
* @author Jonathan Wage <jonwage@gmail.com>
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
@ -234,7 +231,7 @@ class Parser
|
||||
$nameParts[] = $this->_lexer->token['value'];
|
||||
}
|
||||
|
||||
// Effectively pick the name of class (append default NS if none, grab from NS alias, etc)
|
||||
// Effectively pick the name of the class (append default NS if none, grab from NS alias, etc)
|
||||
if (count($nameParts) == 1) {
|
||||
if (strpos($nameParts[0], ':')) {
|
||||
list ($alias, $simpleName) = explode(':', $nameParts[0]);
|
||||
|
@ -1,7 +1,5 @@
|
||||
<?php
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
@ -24,10 +22,7 @@ namespace Doctrine\Common\Cache;
|
||||
/**
|
||||
* Base class for cache driver implementations.
|
||||
*
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
* @link www.doctrine-project.org
|
||||
* @since 2.0
|
||||
* @version $Revision: 3938 $
|
||||
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
|
||||
* @author Jonathan Wage <jonwage@gmail.com>
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
|
@ -1,7 +1,5 @@
|
||||
<?php
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
|
@ -1,7 +1,5 @@
|
||||
<?php
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
@ -21,16 +19,12 @@
|
||||
|
||||
namespace Doctrine\Common\Collections;
|
||||
|
||||
use \Closure, \ArrayIterator;
|
||||
use Closure, ArrayIterator;
|
||||
|
||||
/**
|
||||
* An ArrayCollection is a Collection implementation that uses a regular PHP array
|
||||
* internally.
|
||||
* An ArrayCollection is a Collection implementation that wraps a regular PHP array.
|
||||
*
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
* @link www.doctrine-project.org
|
||||
* @since 2.0
|
||||
* @version $Revision: 3938 $
|
||||
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
|
||||
* @author Jonathan Wage <jonwage@gmail.com>
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
@ -39,7 +33,6 @@ class ArrayCollection implements Collection
|
||||
{
|
||||
/**
|
||||
* An array containing the entries of this collection.
|
||||
* This is the internal php array.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
@ -54,7 +47,7 @@ class ArrayCollection implements Collection
|
||||
{
|
||||
$this->_elements = $elements;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the PHP array representation of this collection.
|
||||
*
|
||||
@ -121,7 +114,7 @@ class ArrayCollection implements Collection
|
||||
* Removes an element with a specific key/index from the collection.
|
||||
*
|
||||
* @param mixed $key
|
||||
* @return mixed
|
||||
* @return mixed The removed element or NULL, if no element exists for the given key.
|
||||
*/
|
||||
public function remove($key)
|
||||
{
|
||||
@ -131,7 +124,7 @@ class ArrayCollection implements Collection
|
||||
|
||||
return $removed;
|
||||
}
|
||||
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -413,6 +406,7 @@ class ArrayCollection implements Collection
|
||||
/**
|
||||
* Returns a string representation of this object.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
@ -421,7 +415,6 @@ class ArrayCollection implements Collection
|
||||
|
||||
/**
|
||||
* Clears the collection.
|
||||
*
|
||||
*/
|
||||
public function clear()
|
||||
{
|
||||
|
@ -1,7 +1,5 @@
|
||||
<?php
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
@ -40,10 +38,7 @@ use Closure, Countable, IteratorAggregate, ArrayAccess;
|
||||
* position unless you explicitly positioned it before. Prefer iteration with
|
||||
* external iterators.
|
||||
*
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
* @link www.doctrine-project.org
|
||||
* @since 2.0
|
||||
* @version $Revision: 3938 $
|
||||
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
|
||||
* @author Jonathan Wage <jonwage@gmail.com>
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
|
@ -1,7 +1,5 @@
|
||||
<?php
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
@ -22,15 +20,13 @@
|
||||
namespace Doctrine\Common;
|
||||
|
||||
/**
|
||||
* Simple generic lexical scanner.
|
||||
* Base class for writing simple lexers, i.e. for creating small DSLs.
|
||||
*
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
* @link www.doctrine-project.org
|
||||
* @since 2.0
|
||||
* @version $Revision: 3938 $
|
||||
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
|
||||
* @author Jonathan Wage <jonwage@gmail.com>
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
* @todo Rename: AbstractLexer
|
||||
*/
|
||||
abstract class Lexer
|
||||
{
|
||||
@ -50,7 +46,7 @@ abstract class Lexer
|
||||
private $_peek = 0;
|
||||
|
||||
/**
|
||||
* @var array The next token in the query string.
|
||||
* @var array The next token in the input.
|
||||
*/
|
||||
public $lookahead;
|
||||
|
||||
@ -60,9 +56,12 @@ abstract class Lexer
|
||||
public $token;
|
||||
|
||||
/**
|
||||
* Inputs data to be tokenized
|
||||
* Sets the input data to be tokenized.
|
||||
*
|
||||
* @param string $input input to be tokenized
|
||||
* The Lexer is immediately reset and the new input tokenized.
|
||||
* Any unprocessed tokens from any previous input are lost.
|
||||
*
|
||||
* @param string $input The input to be tokenized.
|
||||
*/
|
||||
public function setInput($input)
|
||||
{
|
||||
@ -72,20 +71,18 @@ abstract class Lexer
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the scanner
|
||||
*
|
||||
* Resets the lexer.
|
||||
*/
|
||||
public function reset()
|
||||
{
|
||||
$this->lookahead = null;
|
||||
$this->token = null;
|
||||
$this->_peek = 0;
|
||||
$this->token = null;
|
||||
$this->_peek = 0;
|
||||
$this->_position = 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Resets the peek pointer to 0
|
||||
*
|
||||
* Resets the peek pointer to 0.
|
||||
*/
|
||||
public function resetPeek()
|
||||
{
|
||||
@ -93,7 +90,7 @@ abstract class Lexer
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the lexer position on the input to the given position
|
||||
* Resets the lexer position on the input to the given position.
|
||||
*
|
||||
* @param integer $position Position to place the lexical scanner
|
||||
*/
|
||||
@ -235,14 +232,14 @@ abstract class Lexer
|
||||
}
|
||||
|
||||
/**
|
||||
* Lexical catchable patterns
|
||||
* Lexical catchable patterns.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
abstract protected function getCatchablePatterns();
|
||||
|
||||
/**
|
||||
* Lexical non-catchable patterns
|
||||
* Lexical non-catchable patterns.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
|
@ -1,7 +1,5 @@
|
||||
<?php
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
|
@ -1,7 +1,5 @@
|
||||
<?php
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
|
@ -1,4 +1,21 @@
|
||||
<?php
|
||||
/*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* This software consists of voluntary contributions made by many individuals
|
||||
* and is licensed under the LGPL. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM;
|
||||
|
||||
@ -12,6 +29,6 @@ class EntityNotFoundException extends ORMException
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct('Entity was found although one item was expected.');
|
||||
parent::__construct('Entity was not found.');
|
||||
}
|
||||
}
|
@ -1,7 +1,5 @@
|
||||
<?php
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
@ -28,10 +26,7 @@ namespace Doctrine\ORM;
|
||||
* This class is designed for inheritance and users can subclass this class to
|
||||
* write their own repositories with business-specific methods to locate entities.
|
||||
*
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
* @link www.doctrine-project.org
|
||||
* @since 2.0
|
||||
* @version $Revision$
|
||||
* @author Benjamin Eberlei <kontakt@beberlei.de>
|
||||
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
|
||||
* @author Jonathan Wage <jonwage@gmail.com>
|
||||
|
@ -1,7 +1,5 @@
|
||||
<?php
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
@ -25,12 +23,9 @@ namespace Doctrine\ORM\Event;
|
||||
* Lifecycle Events are triggered by the UnitOfWork during lifecycle transitions
|
||||
* of entities.
|
||||
*
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
* @link www.doctrine-project.com
|
||||
* @since 1.0
|
||||
* @version $Revision$
|
||||
* @author Roman Borschel <roman@code-factory.de>
|
||||
* @author Benjamin Eberlei <kontakt@beberlei.de>
|
||||
* @since 2.0
|
||||
* @author Roman Borschel <roman@code-factory.de>
|
||||
* @author Benjamin Eberlei <kontakt@beberlei.de>
|
||||
*/
|
||||
class LifecycleEventArgs extends \Doctrine\Common\EventArgs
|
||||
{
|
||||
|
@ -1,4 +1,21 @@
|
||||
<?php
|
||||
/*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* This software consists of voluntary contributions made by many individuals
|
||||
* and is licensed under the LGPL. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Id;
|
||||
|
||||
|
@ -1,7 +1,5 @@
|
||||
<?php
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
@ -27,10 +25,7 @@ use Doctrine\ORM\ORMException;
|
||||
/**
|
||||
* Special generator for application-assigned identifiers (doesnt really generate anything).
|
||||
*
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
* @link www.doctrine-project.org
|
||||
* @since 2.0
|
||||
* @version $Revision$
|
||||
* @author Benjamin Eberlei <kontakt@beberlei.de>
|
||||
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
|
||||
* @author Jonathan Wage <jonwage@gmail.com>
|
||||
|
@ -1,4 +1,21 @@
|
||||
<?php
|
||||
/*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* This software consists of voluntary contributions made by many individuals
|
||||
* and is licensed under the LGPL. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Id;
|
||||
|
||||
|
@ -1,7 +1,5 @@
|
||||
<?php
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
@ -21,7 +19,7 @@
|
||||
|
||||
namespace Doctrine\ORM\Id;
|
||||
|
||||
use Doctrine\ORM\EntityManager;
|
||||
use Serializable, Doctrine\ORM\EntityManager;
|
||||
|
||||
/**
|
||||
* Represents an ID generator that uses a database sequence.
|
||||
@ -29,7 +27,7 @@ use Doctrine\ORM\EntityManager;
|
||||
* @since 2.0
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
*/
|
||||
class SequenceGenerator extends AbstractIdGenerator implements \Serializable
|
||||
class SequenceGenerator extends AbstractIdGenerator implements Serializable
|
||||
{
|
||||
private $_allocationSize;
|
||||
private $_sequenceName;
|
||||
|
@ -1,4 +1,21 @@
|
||||
<?php
|
||||
/*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* This software consists of voluntary contributions made by many individuals
|
||||
* and is licensed under the LGPL. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Id;
|
||||
|
||||
|
@ -1,4 +1,21 @@
|
||||
<?php
|
||||
/*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* This software consists of voluntary contributions made by many individuals
|
||||
* and is licensed under the LGPL. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Id;
|
||||
|
||||
@ -7,10 +24,7 @@ use Doctrine\ORM\EntityManager;
|
||||
/**
|
||||
* Id generator that uses a single-row database table and a hi/lo algorithm.
|
||||
*
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
* @link www.doctrine-project.org
|
||||
* @since 2.0
|
||||
* @version $Revision$
|
||||
* @author Benjamin Eberlei <kontakt@beberlei.de>
|
||||
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
|
||||
* @author Jonathan Wage <jonwage@gmail.com>
|
||||
|
@ -1,7 +1,5 @@
|
||||
<?php
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
|
@ -1,7 +1,5 @@
|
||||
<?php
|
||||
/*
|
||||
* $Id: Hydrate.php 3192 2007-11-19 17:55:23Z romanb $
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
@ -30,10 +28,7 @@ use PDO,
|
||||
* Base class for all hydrators. A hydrator is a class that provides some form
|
||||
* of transformation of an SQL result set into another structure.
|
||||
*
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
* @link www.doctrine-project.org
|
||||
* @since 2.0
|
||||
* @version $Revision: 3192 $
|
||||
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
*/
|
||||
|
@ -1,7 +1,5 @@
|
||||
<?php
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
|
@ -1,7 +1,5 @@
|
||||
<?php
|
||||
/*
|
||||
* $Id: UnitOfWork.php 4947 2008-09-12 13:16:05Z romanb $
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
|
@ -1,7 +1,5 @@
|
||||
<?php
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
@ -242,8 +240,8 @@ class ObjectHydrator extends AbstractHydrator
|
||||
* specified by the FROM clause in a DQL query.
|
||||
*
|
||||
* @param array $data The data of the row to process.
|
||||
* @param array $cache
|
||||
* @param array $result
|
||||
* @param array $cache The cache to use.
|
||||
* @param array $result The result array to fill.
|
||||
*/
|
||||
protected function _hydrateRow(array $data, array &$cache, array &$result)
|
||||
{
|
||||
|
@ -1,7 +1,5 @@
|
||||
<?php
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
|
@ -1,7 +1,5 @@
|
||||
<?php
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
|
@ -32,6 +32,7 @@ namespace Doctrine\ORM\Mapping;
|
||||
*
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
* @since 2.0
|
||||
* @todo Potentially remove if assoc mapping objects get replaced by simple arrays.
|
||||
*/
|
||||
abstract class AssociationMapping
|
||||
{
|
||||
@ -58,7 +59,7 @@ abstract class AssociationMapping
|
||||
public $isCascadeRemove;
|
||||
|
||||
/**
|
||||
* READ-ONLY: Whether the association cascades save() operations from the source entity
|
||||
* READ-ONLY: Whether the association cascades persist() operations from the source entity
|
||||
* to the target entity/entities.
|
||||
*
|
||||
* @var boolean
|
||||
|
@ -26,12 +26,9 @@ use Doctrine\ORM\Mapping\ClassMetadataInfo;
|
||||
/**
|
||||
* Contract for metadata drivers.
|
||||
*
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
* @link www.doctrine-project.com
|
||||
* @since 2.0
|
||||
* @version $Revision: 1393 $
|
||||
* @author Jonathan H. Wage <jonwage@gmail.com>
|
||||
* @todo Rename: MetadataDriver
|
||||
* @since 2.0
|
||||
* @author Jonathan H. Wage <jonwage@gmail.com>
|
||||
* @todo Rename: MetadataDriver or MappingDriver
|
||||
*/
|
||||
interface Driver
|
||||
{
|
||||
|
@ -1,7 +1,5 @@
|
||||
<?php
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
@ -29,14 +27,12 @@ use Doctrine\ORM\Mapping\Driver\Driver,
|
||||
* The DriverChain allows you to add multiple other mapping drivers for
|
||||
* certain namespaces
|
||||
*
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
* @link www.doctrine-project.org
|
||||
* @since 2.0
|
||||
* @version $Revision$
|
||||
* @author Benjamin Eberlei <kontakt@beberlei.de>
|
||||
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
|
||||
* @author Jonathan H. Wage <jonwage@gmail.com>
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
* @since 2.0
|
||||
* @author Benjamin Eberlei <kontakt@beberlei.de>
|
||||
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
|
||||
* @author Jonathan H. Wage <jonwage@gmail.com>
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
* @todo Rename: MappingDriverChain or MetadataDriverChain
|
||||
*/
|
||||
class DriverChain implements Driver
|
||||
{
|
||||
|
@ -37,6 +37,7 @@ namespace Doctrine\ORM\Mapping;
|
||||
* @since 2.0
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
* @author Giorgio Sironi <piccoloprincipeazzurro@gmail.com>
|
||||
* @todo Potentially remove if assoc mapping objects get replaced by simple arrays.
|
||||
*/
|
||||
class ManyToManyMapping extends AssociationMapping
|
||||
{
|
||||
@ -140,39 +141,11 @@ class ManyToManyMapping extends AssociationMapping
|
||||
* @param object The owner of the collection.
|
||||
* @param object The collection to populate.
|
||||
* @param array
|
||||
* @todo Remove
|
||||
*/
|
||||
public function load($sourceEntity, $targetCollection, $em, array $joinColumnValues = array())
|
||||
{
|
||||
$sourceClass = $em->getClassMetadata($this->sourceEntityName);
|
||||
$joinTableConditions = array();
|
||||
if ($this->isOwningSide) {
|
||||
foreach ($this->relationToSourceKeyColumns as $relationKeyColumn => $sourceKeyColumn) {
|
||||
// getting id
|
||||
if (isset($sourceClass->fieldNames[$sourceKeyColumn])) {
|
||||
$joinTableConditions[$relationKeyColumn] = $sourceClass->reflFields[$sourceClass->fieldNames[$sourceKeyColumn]]->getValue($sourceEntity);
|
||||
} else {
|
||||
throw MappingException::joinColumnMustPointToMappedField(
|
||||
$sourceClass->name, $sourceKeyColumn
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$owningAssoc = $em->getClassMetadata($this->targetEntityName)->associationMappings[$this->mappedBy];
|
||||
// TRICKY: since the association is inverted source and target are flipped
|
||||
foreach ($owningAssoc->relationToTargetKeyColumns as $relationKeyColumn => $sourceKeyColumn) {
|
||||
// getting id
|
||||
if (isset($sourceClass->fieldNames[$sourceKeyColumn])) {
|
||||
$joinTableConditions[$relationKeyColumn] = $sourceClass->reflFields[$sourceClass->fieldNames[$sourceKeyColumn]]->getValue($sourceEntity);
|
||||
} else {
|
||||
throw MappingException::joinColumnMustPointToMappedField(
|
||||
$sourceClass->name, $sourceKeyColumn
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$persister = $em->getUnitOfWork()->getEntityPersister($this->targetEntityName);
|
||||
$persister->loadManyToManyCollection($this, $joinTableConditions, $targetCollection);
|
||||
$em->getUnitOfWork()->getEntityPersister($this->targetEntityName)->loadManyToManyCollection($this, $sourceEntity, $targetCollection);
|
||||
}
|
||||
|
||||
/** {@inheritdoc} */
|
||||
|
@ -1,7 +1,5 @@
|
||||
<?php
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
|
@ -41,6 +41,7 @@ namespace Doctrine\ORM\Mapping;
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
* @author Giorgio Sironi <piccoloprincipeazzurro@gmail.com>
|
||||
* @since 2.0
|
||||
* @todo Potentially remove if assoc mapping objects get replaced by simple arrays.
|
||||
*/
|
||||
class OneToManyMapping extends AssociationMapping
|
||||
{
|
||||
@ -99,8 +100,6 @@ class OneToManyMapping extends AssociationMapping
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @override
|
||||
*/
|
||||
public function isOneToMany()
|
||||
{
|
||||
@ -115,24 +114,11 @@ class OneToManyMapping extends AssociationMapping
|
||||
* @param $em The EntityManager to use.
|
||||
* @param $joinColumnValues
|
||||
* @return void
|
||||
* @todo Remove
|
||||
*/
|
||||
public function load($sourceEntity, $targetCollection, $em, array $joinColumnValues = array())
|
||||
{
|
||||
$persister = $em->getUnitOfWork()->getEntityPersister($this->targetEntityName);
|
||||
// a one-to-many is always inverse (does not have foreign key)
|
||||
$sourceClass = $em->getClassMetadata($this->sourceEntityName);
|
||||
$owningAssoc = $em->getClassMetadata($this->targetEntityName)->associationMappings[$this->mappedBy];
|
||||
// TRICKY: since the association is specular source and target are flipped
|
||||
foreach ($owningAssoc->targetToSourceKeyColumns as $sourceKeyColumn => $targetKeyColumn) {
|
||||
// getting id
|
||||
if (isset($sourceClass->fieldNames[$sourceKeyColumn])) {
|
||||
$conditions[$targetKeyColumn] = $sourceClass->reflFields[$sourceClass->fieldNames[$sourceKeyColumn]]->getValue($sourceEntity);
|
||||
} else {
|
||||
$conditions[$targetKeyColumn] = $joinColumnValues[$sourceKeyColumn];
|
||||
}
|
||||
}
|
||||
|
||||
$persister->loadOneToManyCollection($this, $conditions, $targetCollection);
|
||||
$em->getUnitOfWork()->getEntityPersister($this->targetEntityName)->loadOneToManyCollection($this, $sourceEntity, $targetCollection);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -37,6 +37,7 @@ namespace Doctrine\ORM\Mapping;
|
||||
* @since 2.0
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
* @author Giorgio Sironi <piccoloprincipeazzurro@gmail.com>
|
||||
* @todo Potentially remove if assoc mapping objects get replaced by simple arrays.
|
||||
*/
|
||||
class OneToOneMapping extends AssociationMapping
|
||||
{
|
||||
@ -133,57 +134,11 @@ class OneToOneMapping extends AssociationMapping
|
||||
* @param object $targetEntity the entity to load data in
|
||||
* @param EntityManager $em
|
||||
* @param array $joinColumnValues Values of the join columns of $sourceEntity.
|
||||
* @todo Remove
|
||||
*/
|
||||
public function load($sourceEntity, $targetEntity, $em, array $joinColumnValues = array())
|
||||
{
|
||||
$targetClass = $em->getClassMetadata($this->targetEntityName);
|
||||
|
||||
if ($this->isOwningSide) {
|
||||
// Mark inverse side as fetched in the hints, otherwise the UoW would
|
||||
// try to load it in a separate query (remember: to-one inverse sides can not be lazy).
|
||||
$hints = array();
|
||||
if ($this->inversedBy) {
|
||||
$hints['fetched'][$targetClass->name][$this->inversedBy] = true;
|
||||
if ($targetClass->subClasses) {
|
||||
foreach ($targetClass->subClasses as $targetSubclassName) {
|
||||
$hints['fetched'][$targetSubclassName][$this->inversedBy] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* cascade read-only status
|
||||
if ($em->getUnitOfWork()->isReadOnly($sourceEntity)) {
|
||||
$hints[Query::HINT_READ_ONLY] = true;
|
||||
}
|
||||
*/
|
||||
|
||||
$targetEntity = $em->getUnitOfWork()->getEntityPersister($this->targetEntityName)->load($joinColumnValues, $targetEntity, $this, $hints);
|
||||
|
||||
if ($targetEntity !== null && $this->inversedBy && ! $targetClass->isCollectionValuedAssociation($this->inversedBy)) {
|
||||
$targetClass->reflFields[$this->inversedBy]->setValue($targetEntity, $sourceEntity);
|
||||
}
|
||||
} else {
|
||||
$conditions = array();
|
||||
$sourceClass = $em->getClassMetadata($this->sourceEntityName);
|
||||
$owningAssoc = $targetClass->getAssociationMapping($this->mappedBy);
|
||||
// TRICKY: since the association is specular source and target are flipped
|
||||
foreach ($owningAssoc->targetToSourceKeyColumns as $sourceKeyColumn => $targetKeyColumn) {
|
||||
if (isset($sourceClass->fieldNames[$sourceKeyColumn])) {
|
||||
$conditions[$targetKeyColumn] = $sourceClass->reflFields[$sourceClass->fieldNames[$sourceKeyColumn]]->getValue($sourceEntity);
|
||||
} else {
|
||||
throw MappingException::joinColumnMustPointToMappedField(
|
||||
$sourceClass->name, $sourceKeyColumn
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$targetEntity = $em->getUnitOfWork()->getEntityPersister($this->targetEntityName)->load($conditions, $targetEntity, $this);
|
||||
|
||||
if ($targetEntity !== null) {
|
||||
$targetClass->setFieldValue($targetEntity, $this->mappedBy, $sourceEntity);
|
||||
}
|
||||
}
|
||||
|
||||
return $targetEntity;
|
||||
return $em->getUnitOfWork()->getEntityPersister($this->targetEntityName)->loadOneToOneEntity($this, $sourceEntity, $targetEntity, $joinColumnValues);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,4 +1,21 @@
|
||||
<?php
|
||||
/*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* This software consists of voluntary contributions made by many individuals
|
||||
* and is licensed under the LGPL. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM;
|
||||
|
||||
|
@ -1,4 +1,21 @@
|
||||
<?php
|
||||
/*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* This software consists of voluntary contributions made by many individuals
|
||||
* and is licensed under the LGPL. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM;
|
||||
|
||||
|
@ -1,4 +1,21 @@
|
||||
<?php
|
||||
/*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* This software consists of voluntary contributions made by many individuals
|
||||
* and is licensed under the LGPL. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM;
|
||||
|
||||
|
@ -1,7 +1,5 @@
|
||||
<?php
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
|
@ -1,7 +1,5 @@
|
||||
<?php
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
|
@ -37,7 +37,7 @@ abstract class AbstractEntityInheritancePersister extends StandardEntityPersiste
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $_declaringClassMap = array();
|
||||
/*private*/protected $_declaringClassMap = array();
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
@ -91,7 +91,7 @@ abstract class AbstractEntityInheritancePersister extends StandardEntityPersiste
|
||||
protected function _getSelectColumnSQL($field, ClassMetadata $class)
|
||||
{
|
||||
$columnName = $class->columnNames[$field];
|
||||
$sql = $this->_getSQLTableAlias($class) . '.' . $class->getQuotedColumnName($field, $this->_platform);
|
||||
$sql = $this->_getSQLTableAlias($class->name) . '.' . $class->getQuotedColumnName($field, $this->_platform);
|
||||
$columnAlias = $this->_platform->getSQLResultCasing($columnName . $this->_sqlAliasCounter++);
|
||||
if ( ! isset($this->_resultColumnNames[$columnAlias])) {
|
||||
$this->_resultColumnNames[$columnAlias] = $columnName;
|
||||
|
@ -1,7 +1,5 @@
|
||||
<?php
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
@ -21,15 +19,14 @@
|
||||
|
||||
namespace Doctrine\ORM\Persisters;
|
||||
|
||||
use Doctrine\ORM\ORMException;
|
||||
use Doctrine\ORM\ORMException,
|
||||
Doctrine\ORM\Mapping\ManyToManyMapping;
|
||||
|
||||
/**
|
||||
* The joined subclass persister maps a single entity instance to several tables in the
|
||||
* database as it is defined by the <tt>Class Table Inheritance</tt> strategy.
|
||||
*
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
* @link www.doctrine-project.org
|
||||
* @since 2.0
|
||||
* @see http://martinfowler.com/eaaCatalog/classTableInheritance.html
|
||||
*/
|
||||
@ -116,19 +113,19 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
|
||||
$this->_class : $this->_em->getClassMetadata($this->_class->rootEntityName);
|
||||
$rootPersister = $this->_em->getUnitOfWork()->getEntityPersister($rootClass->name);
|
||||
$rootTableName = $rootClass->table['name'];
|
||||
$rootTableStmt = $this->_conn->prepare($rootPersister->getInsertSQL());
|
||||
$rootTableStmt = $this->_conn->prepare($rootPersister->_getInsertSQL());
|
||||
|
||||
// Prepare statements for sub tables.
|
||||
$subTableStmts = array();
|
||||
if ($rootClass !== $this->_class) {
|
||||
$subTableStmts[$this->_class->table['name']] = $this->_conn->prepare($this->getInsertSQL());
|
||||
$subTableStmts[$this->_class->table['name']] = $this->_conn->prepare($this->_getInsertSQL());
|
||||
}
|
||||
foreach ($this->_class->parentClasses as $parentClassName) {
|
||||
$parentClass = $this->_em->getClassMetadata($parentClassName);
|
||||
$parentTableName = $parentClass->table['name'];
|
||||
if ($parentClass !== $rootClass) {
|
||||
$parentPersister = $this->_em->getUnitOfWork()->getEntityPersister($parentClassName);
|
||||
$subTableStmts[$parentTableName] = $this->_conn->prepare($parentPersister->getInsertSQL());
|
||||
$subTableStmts[$parentTableName] = $this->_conn->prepare($parentPersister->_getInsertSQL());
|
||||
}
|
||||
}
|
||||
|
||||
@ -231,27 +228,30 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function _getSelectEntitiesSQL(array &$criteria, $assoc = null, $orderBy = null)
|
||||
protected function _getSelectEntitiesSQL(array $criteria, $assoc = null)
|
||||
{
|
||||
$idColumns = $this->_class->getIdentifierColumnNames();
|
||||
$baseTableAlias = $this->_getSQLTableAlias($this->_class);
|
||||
$baseTableAlias = $this->_getSQLTableAlias($this->_class->name);
|
||||
|
||||
// Create the column list fragment only once
|
||||
if ($this->_selectColumnListSql === null) {
|
||||
// Add regular columns
|
||||
$columnList = '';
|
||||
foreach ($this->_class->fieldMappings as $fieldName => $mapping) {
|
||||
if ($columnList != '') $columnList .= ', ';
|
||||
$columnList .= $this->_getSelectColumnSQL($fieldName,
|
||||
isset($mapping['inherited']) ? $this->_em->getClassMetadata($mapping['inherited']) : $this->_class);
|
||||
isset($mapping['inherited']) ?
|
||||
$this->_em->getClassMetadata($mapping['inherited']) :
|
||||
$this->_class);
|
||||
}
|
||||
|
||||
// Add foreign key columns
|
||||
foreach ($this->_class->associationMappings as $assoc) {
|
||||
if ($assoc->isOwningSide && $assoc->isOneToOne()) {
|
||||
$tableAlias = $assoc->inherited ?
|
||||
$this->_getSQLTableAlias($this->_em->getClassMetadata($assoc->inherited))
|
||||
foreach ($this->_class->associationMappings as $assoc2) {
|
||||
if ($assoc2->isOwningSide && $assoc2->isOneToOne()) {
|
||||
$tableAlias = $assoc2->inherited ?
|
||||
$this->_getSQLTableAlias($assoc2->inherited)
|
||||
: $baseTableAlias;
|
||||
foreach ($assoc->targetToSourceKeyColumns as $srcColumn) {
|
||||
foreach ($assoc2->targetToSourceKeyColumns as $srcColumn) {
|
||||
$columnAlias = $srcColumn . $this->_sqlAliasCounter++;
|
||||
$columnList .= ", $tableAlias.$srcColumn AS $columnAlias";
|
||||
$resultColumnName = $this->_platform->getSQLResultCasing($columnAlias);
|
||||
@ -262,12 +262,12 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
|
||||
}
|
||||
}
|
||||
|
||||
// Add discriminator column (DO NOT ALIAS THIS COLUMN, see StandardEntityPersister#_processSQLResultInheritanceAware).
|
||||
// Add discriminator column (DO NOT ALIAS, see AbstractEntityInheritancePersister#_processSQLResult).
|
||||
$discrColumn = $this->_class->discriminatorColumn['name'];
|
||||
if ($this->_class->rootEntityName == $this->_class->name) {
|
||||
$columnList .= ", $baseTableAlias.$discrColumn";
|
||||
} else {
|
||||
$columnList .= ', ' . $this->_getSQLTableAlias($this->_em->getClassMetadata($this->_class->rootEntityName))
|
||||
$columnList .= ', ' . $this->_getSQLTableAlias($this->_class->rootEntityName)
|
||||
. ".$discrColumn";
|
||||
}
|
||||
|
||||
@ -279,7 +279,7 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
|
||||
$joinSql = '';
|
||||
foreach ($this->_class->parentClasses as $parentClassName) {
|
||||
$parentClass = $this->_em->getClassMetadata($parentClassName);
|
||||
$tableAlias = $this->_getSQLTableAlias($parentClass);
|
||||
$tableAlias = $this->_getSQLTableAlias($parentClassName);
|
||||
$joinSql .= ' INNER JOIN ' . $parentClass->getQuotedTableName($this->_platform) . ' ' . $tableAlias . ' ON ';
|
||||
$first = true;
|
||||
foreach ($idColumns as $idColumn) {
|
||||
@ -291,7 +291,7 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
|
||||
// OUTER JOIN sub tables
|
||||
foreach ($this->_class->subClasses as $subClassName) {
|
||||
$subClass = $this->_em->getClassMetadata($subClassName);
|
||||
$tableAlias = $this->_getSQLTableAlias($subClass);
|
||||
$tableAlias = $this->_getSQLTableAlias($subClassName);
|
||||
|
||||
if ($this->_selectColumnListSql === null) {
|
||||
// Add subclass columns
|
||||
@ -326,27 +326,14 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
|
||||
}
|
||||
}
|
||||
|
||||
$conditionSql = '';
|
||||
foreach ($criteria as $field => $value) {
|
||||
if ($conditionSql != '') $conditionSql .= ' AND ';
|
||||
if (isset($this->_class->fieldMappings[$field]['inherited'])) {
|
||||
$conditionSql .= $this->_getSQLTableAlias($this->_em->getClassMetadata($this->_class->fieldMappings[$field]['inherited'])) . '.';
|
||||
} else {
|
||||
$conditionSql .= $baseTableAlias . '.';
|
||||
}
|
||||
if (isset($this->_class->columnNames[$field])) {
|
||||
$conditionSql .= $this->_class->getQuotedColumnName($field, $this->_platform);
|
||||
} else if ($assoc !== null) {
|
||||
$conditionSql .= $field;
|
||||
} else {
|
||||
throw ORMException::unrecognizedField($field);
|
||||
}
|
||||
$conditionSql .= ' = ?';
|
||||
}
|
||||
$joinSql .= $assoc != null && $assoc->isManyToMany() ?
|
||||
$this->_getSelectManyToManyJoinSQL($assoc) : '';
|
||||
|
||||
$conditionSql = $this->_getSelectConditionSQL($criteria, $assoc);
|
||||
|
||||
$orderBySql = '';
|
||||
if ($orderBy !== null) {
|
||||
$orderBySql = $this->_getCollectionOrderBySQL($orderBy, $baseTableAlias);
|
||||
if ($assoc != null && isset($assoc->orderBy)) {
|
||||
$orderBySql = $this->_getCollectionOrderBySQL($assoc->orderBy, $baseTableAlias);
|
||||
}
|
||||
|
||||
if ($this->_selectColumnListSql === null) {
|
||||
@ -359,10 +346,10 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
|
||||
. ($conditionSql != '' ? ' WHERE ' . $conditionSql : '') . $orderBySql;
|
||||
}
|
||||
|
||||
/** Ensure this method is never called. This persister overrides _getSelectEntitiesSQL directly. */
|
||||
/* Ensure this method is never called. This persister overrides _getSelectEntitiesSQL directly. */
|
||||
protected function _getSelectColumnListSQL()
|
||||
{
|
||||
throw new \BadMethodCallException("Illegal invocation of ".__METHOD__." on JoinedSubclassPersister.");
|
||||
throw new \BadMethodCallException("Illegal invocation of ".__METHOD__.".");
|
||||
}
|
||||
|
||||
/** {@inheritdoc} */
|
||||
@ -398,17 +385,4 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
|
||||
|
||||
return $columns;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the SQL to select a collection of entities in a many-many association.
|
||||
*
|
||||
* @param ManyToManyMapping $manyToMany
|
||||
* @param array $criteria
|
||||
* @return string
|
||||
*/
|
||||
protected function _getSelectManyToManyEntityCollectionSQL($manyToMany, array &$criteria)
|
||||
{
|
||||
// @todo
|
||||
throw new \BadMethodCallException("Not yet implemented, see http://www.doctrine-project.org/jira/browse/DDC-342");
|
||||
}
|
||||
}
|
||||
|
@ -41,24 +41,25 @@ class SingleTablePersister extends AbstractEntityInheritancePersister
|
||||
protected function _getSelectColumnListSQL()
|
||||
{
|
||||
$columnList = parent::_getSelectColumnListSQL();
|
||||
|
||||
// Append discriminator column
|
||||
$discrColumn = $this->_class->discriminatorColumn['name'];
|
||||
$columnList .= ", $discrColumn";
|
||||
$rootClass = $this->_em->getClassMetadata($this->_class->rootEntityName);
|
||||
$tableAlias = $this->_getSQLTableAlias($rootClass);
|
||||
$tableAlias = $this->_getSQLTableAlias($rootClass->name);
|
||||
$resultColumnName = $this->_platform->getSQLResultCasing($discrColumn);
|
||||
$this->_resultColumnNames[$resultColumnName] = $discrColumn;
|
||||
|
||||
// Append subclass columns
|
||||
foreach ($this->_class->subClasses as $subClassName) {
|
||||
$subClass = $this->_em->getClassMetadata($subClassName);
|
||||
// Append subclass columns
|
||||
// Regular columns
|
||||
foreach ($subClass->fieldMappings as $fieldName => $mapping) {
|
||||
if ( ! isset($mapping['inherited'])) {
|
||||
$columnList .= ', ' . $this->_getSelectColumnSQL($fieldName, $subClass);
|
||||
}
|
||||
}
|
||||
|
||||
// Append subclass foreign keys
|
||||
// Foreign key columns
|
||||
foreach ($subClass->associationMappings as $assoc) {
|
||||
if ($assoc->isOwningSide && $assoc->isOneToOne() && ! $assoc->inherited) {
|
||||
foreach ($assoc->targetToSourceKeyColumns as $srcColumn) {
|
||||
@ -87,14 +88,27 @@ class SingleTablePersister extends AbstractEntityInheritancePersister
|
||||
}
|
||||
|
||||
/** {@inheritdoc} */
|
||||
protected function _getSQLTableAlias(ClassMetadata $class)
|
||||
protected function _getSQLTableAlias($className)
|
||||
{
|
||||
if (isset($this->_sqlTableAliases[$class->rootEntityName])) {
|
||||
return $this->_sqlTableAliases[$class->rootEntityName];
|
||||
}
|
||||
$tableAlias = $this->_em->getClassMetadata($class->rootEntityName)->table['name'][0] . $this->_sqlAliasCounter++;
|
||||
$this->_sqlTableAliases[$class->rootEntityName] = $tableAlias;
|
||||
return parent::_getSQLTableAlias($this->_class->rootEntityName);
|
||||
}
|
||||
|
||||
return $tableAlias;
|
||||
/** {@inheritdoc} */
|
||||
protected function _getSelectConditionSQL(array $criteria, $assoc = null)
|
||||
{
|
||||
$conditionSql = parent::_getSelectConditionSQL($criteria, $assoc);
|
||||
|
||||
// Append discriminator condition
|
||||
if ($conditionSql) $conditionSql .= ' AND ';
|
||||
$values = array($this->_conn->quote($this->_class->discriminatorValue));
|
||||
$discrValues = array_flip($this->_class->discriminatorMap);
|
||||
foreach ($this->_class->subClasses as $subclassName) {
|
||||
$values[] = $this->_conn->quote($discrValues[$subclassName]);
|
||||
}
|
||||
$conditionSql .= $this->_getSQLTableAlias($this->_class->name) . '.'
|
||||
. $this->_class->discriminatorColumn['name']
|
||||
. ' IN (' . implode(', ', $values) . ')';
|
||||
|
||||
return $conditionSql;
|
||||
}
|
||||
}
|
@ -1,7 +1,5 @@
|
||||
<?php
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
@ -28,16 +26,50 @@ use PDO,
|
||||
Doctrine\ORM\EntityManager,
|
||||
Doctrine\ORM\Query,
|
||||
Doctrine\ORM\PersistentCollection,
|
||||
Doctrine\ORM\Mapping\ClassMetadata;
|
||||
Doctrine\ORM\Mapping\MappingException,
|
||||
Doctrine\ORM\Mapping\ClassMetadata,
|
||||
Doctrine\ORM\Mapping\OneToOneMapping,
|
||||
Doctrine\ORM\Mapping\OneToManyMapping,
|
||||
Doctrine\ORM\Mapping\ManyToManyMapping;
|
||||
|
||||
/**
|
||||
* A basic entity persister that maps an entity with no (mapped) inheritance to a single table
|
||||
* in the relational database.
|
||||
* A BasicEntityPersiter maps an entity to a single table in a relational database.
|
||||
*
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
* @author Giorgio Sironi <piccoloprincipeazzurro@gmail.com>
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
* @since 2.0
|
||||
* A persister is always responsible for a single entity type.
|
||||
*
|
||||
* EntityPersisters are used during a UnitOfWork to apply any changes to the persistent
|
||||
* state of entities onto a relational database when the UnitOfWork is committed,
|
||||
* as well as for basic querying of entities and their associations (not DQL).
|
||||
*
|
||||
* The persisting operations that are invoked during a commit of a UnitOfWork to
|
||||
* persist the persistent entity state are:
|
||||
*
|
||||
* - {@link addInsert} : To schedule an entity for insertion.
|
||||
* - {@link executeInserts} : To execute all scheduled insertions.
|
||||
* - {@link update} : To update the persistent state of an entity.
|
||||
* - {@link delete} : To delete the persistent state of an entity.
|
||||
*
|
||||
* As can be seen from the above list, insertions are batched and executed all at once
|
||||
* for increased efficiency.
|
||||
*
|
||||
* The querying operations invoked during a UnitOfWork, either through direct find
|
||||
* requests or lazy-loading, are the following:
|
||||
*
|
||||
* - {@link load} : Loads (the state of) a single, managed entity.
|
||||
* - {@link loadAll} : Loads multiple, managed entities.
|
||||
* - {@link loadOneToOneEntity} : Loads a one/many-to-one association (lazy-loading).
|
||||
* - {@link loadOneToManyCollection} : Loads a one-to-many association (lazy-loading).
|
||||
* - {@link loadManyToManyCollection} : Loads a many-to-many association (lazy-loading).
|
||||
*
|
||||
* The BasicEntityPersister implementation provides the default behavior for
|
||||
* persisting and querying entities that are mapped to a single database table.
|
||||
*
|
||||
* Subclasses can be created to provide custom persisting and querying strategies,
|
||||
* i.e. spanning multiple tables.
|
||||
*
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
* @author Giorgio Sironi <piccoloprincipeazzurro@gmail.com>
|
||||
* @since 2.0
|
||||
* @todo Rename: BasicEntityPersister
|
||||
*/
|
||||
class StandardEntityPersister
|
||||
@ -50,16 +82,16 @@ class StandardEntityPersister
|
||||
protected $_class;
|
||||
|
||||
/**
|
||||
* The underlying Connection of the used EntityManager.
|
||||
* The underlying DBAL Connection of the used EntityManager.
|
||||
*
|
||||
* @var Doctrine\DBAL\Connection $conn
|
||||
*/
|
||||
protected $_conn;
|
||||
|
||||
|
||||
/**
|
||||
* The database platform.
|
||||
*
|
||||
* @var AbstractPlatform
|
||||
* @var Doctrine\DBAL\Platforms\AbstractPlatform
|
||||
*/
|
||||
protected $_platform;
|
||||
|
||||
@ -87,8 +119,8 @@ class StandardEntityPersister
|
||||
protected $_resultColumnNames = array();
|
||||
|
||||
/**
|
||||
* The map of column names to DBAL mapping types of all prepared columns used when INSERTing
|
||||
* or UPDATEing an entity.
|
||||
* The map of column names to DBAL mapping types of all prepared columns used
|
||||
* when INSERTing or UPDATEing an entity.
|
||||
*
|
||||
* @var array
|
||||
* @see _prepareInsertData($entity)
|
||||
@ -143,9 +175,9 @@ class StandardEntityPersister
|
||||
|
||||
/**
|
||||
* Adds an entity to the queued insertions.
|
||||
* The entity remains queued until {@link executeInserts()} is invoked.
|
||||
* The entity remains queued until {@link executeInserts} is invoked.
|
||||
*
|
||||
* @param object $entity The entitiy to queue for insertion.
|
||||
* @param object $entity The entity to queue for insertion.
|
||||
*/
|
||||
public function addInsert($entity)
|
||||
{
|
||||
@ -171,7 +203,7 @@ class StandardEntityPersister
|
||||
$idGen = $this->_class->idGenerator;
|
||||
$isPostInsertId = $idGen->isPostInsertGenerator();
|
||||
|
||||
$stmt = $this->_conn->prepare($this->getInsertSQL());
|
||||
$stmt = $this->_conn->prepare($this->_getInsertSQL());
|
||||
$tableName = $this->_class->table['name'];
|
||||
|
||||
foreach ($this->_queuedInserts as $entity) {
|
||||
@ -209,9 +241,9 @@ class StandardEntityPersister
|
||||
* by the preceding INSERT statement and assigns it back in to the
|
||||
* entities version field.
|
||||
*
|
||||
* @param $class
|
||||
* @param $entity
|
||||
* @param $id
|
||||
* @param Doctrine\ORM\Mapping\ClassMetadata $class
|
||||
* @param object $entity
|
||||
* @param mixed $id
|
||||
*/
|
||||
protected function _assignDefaultVersionValue($class, $entity, $id)
|
||||
{
|
||||
@ -226,7 +258,16 @@ class StandardEntityPersister
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates an entity.
|
||||
* Updates a managed entity. The entity is updated according to its current changeset
|
||||
* in the running UnitOfWork. If there is no changeset, nothing is updated.
|
||||
*
|
||||
* The data to update is retrieved through {@link _prepareUpdateData}.
|
||||
* Subclasses that override this method are supposed to obtain the update data
|
||||
* in the same way, through {@link _prepareUpdateData}.
|
||||
*
|
||||
* Subclasses are also supposed to take care of versioning when overriding this method,
|
||||
* if necessary. The {@link _updateTable} method can be used to apply the data retrieved
|
||||
* from {@_prepareUpdateData} on the target tables, thereby optionally applying versioning.
|
||||
*
|
||||
* @param object $entity The entity to update.
|
||||
*/
|
||||
@ -241,14 +282,14 @@ class StandardEntityPersister
|
||||
|
||||
/**
|
||||
* Performs an UPDATE statement for an entity on a specific table.
|
||||
* The UPDATE can be optionally versioned, which requires the entity to have a version field.
|
||||
* The UPDATE can optionally be versioned, which requires the entity to have a version field.
|
||||
*
|
||||
* @param object $entity The entity object being updated.
|
||||
* @param string $tableName The name of the table to apply the UPDATE on.
|
||||
* @param array $updateData The map of columns to update (column => value).
|
||||
* @param boolean $versioned Whether the UPDATE should be versioned.
|
||||
*/
|
||||
protected function _updateTable($entity, $tableName, $updateData, $versioned = false)
|
||||
protected final function _updateTable($entity, $tableName, array $updateData, $versioned = false)
|
||||
{
|
||||
$set = $params = $types = array();
|
||||
|
||||
@ -261,7 +302,7 @@ class StandardEntityPersister
|
||||
$params[] = $value;
|
||||
$types[] = $this->_columnTypes[$columnName];
|
||||
}
|
||||
|
||||
|
||||
$where = array();
|
||||
$id = $this->_em->getUnitOfWork()->getEntityIdentifier($entity);
|
||||
foreach ($this->_class->identifier as $idField) {
|
||||
@ -284,7 +325,7 @@ class StandardEntityPersister
|
||||
$types[] = $this->_class->fieldMappings[$versionField]['type'];
|
||||
}
|
||||
|
||||
$sql = 'UPDATE ' . $tableName . ' SET ' . implode(', ', $set)
|
||||
$sql = "UPDATE $tableName SET " . implode(', ', $set)
|
||||
. ' WHERE ' . implode(' = ? AND ', $where) . ' = ?';
|
||||
|
||||
$result = $this->_conn->executeUpdate($sql, $params, $types);
|
||||
@ -295,7 +336,12 @@ class StandardEntityPersister
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes an entity.
|
||||
* Deletes a managed entity.
|
||||
*
|
||||
* The entity to delete must be managed and have a persistent identifier.
|
||||
* The deletion happens instantaneously.
|
||||
*
|
||||
* Subclasses may override this method to customize the semantics of entity deletion.
|
||||
*
|
||||
* @param object $entity The entity to delete.
|
||||
*/
|
||||
@ -319,7 +365,9 @@ class StandardEntityPersister
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares the data changeset of an entity for database insertion.
|
||||
* Prepares the changeset of an entity for database insertion (UPDATE).
|
||||
*
|
||||
* The changeset is obtained from the currently running UnitOfWork.
|
||||
*
|
||||
* During this preparation the array that is passed as the second parameter is filled with
|
||||
* <columnName> => <value> pairs, grouped by table name.
|
||||
@ -333,8 +381,6 @@ class StandardEntityPersister
|
||||
* )
|
||||
* </code>
|
||||
*
|
||||
* Notes to inheritors: Be sure to call <code>parent::_prepareData($entity, $result, $isInsert);</code>
|
||||
*
|
||||
* @param object $entity The entity for which to prepare the data.
|
||||
* @return array The prepared data.
|
||||
*/
|
||||
@ -348,7 +394,7 @@ class StandardEntityPersister
|
||||
}
|
||||
|
||||
foreach ($uow->getEntityChangeSet($entity) as $field => $change) {
|
||||
if ($versioned && $versionField == $field) {
|
||||
if ($versioned && $versionField == $field) { //TODO: Needed?
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -356,9 +402,9 @@ class StandardEntityPersister
|
||||
$newVal = $change[1];
|
||||
|
||||
if (isset($this->_class->associationMappings[$field])) {
|
||||
$assocMapping = $this->_class->associationMappings[$field];
|
||||
$assoc = $this->_class->associationMappings[$field];
|
||||
// Only owning side of x-1 associations can have a FK column.
|
||||
if ( ! $assocMapping->isOwningSide || ! $assocMapping->isOneToOne()) {
|
||||
if ( ! $assoc->isOwningSide || ! $assoc->isOneToOne()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -379,10 +425,10 @@ class StandardEntityPersister
|
||||
$newValId = $uow->getEntityIdentifier($newVal);
|
||||
}
|
||||
|
||||
$targetClass = $this->_em->getClassMetadata($assocMapping->targetEntityName);
|
||||
$targetClass = $this->_em->getClassMetadata($assoc->targetEntityName);
|
||||
$owningTable = $this->getOwningTable($field);
|
||||
|
||||
foreach ($assocMapping->sourceToTargetKeyColumns as $sourceColumn => $targetColumn) {
|
||||
foreach ($assoc->sourceToTargetKeyColumns as $sourceColumn => $targetColumn) {
|
||||
if ($newVal === null) {
|
||||
$result[$owningTable][$sourceColumn] = null;
|
||||
} else {
|
||||
@ -399,6 +445,16 @@ class StandardEntityPersister
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares the data changeset of a managed entity for database insertion (initial INSERT).
|
||||
* The changeset of the entity is obtained from the currently running UnitOfWork.
|
||||
*
|
||||
* The default insert data preparation is the same as for updates.
|
||||
*
|
||||
* @param object $entity The entity for which to prepare the data.
|
||||
* @return array The prepared data for the tables to update.
|
||||
* @see _prepareUpdateData
|
||||
*/
|
||||
protected function _prepareInsertData($entity)
|
||||
{
|
||||
return $this->_prepareUpdateData($entity);
|
||||
@ -407,8 +463,12 @@ class StandardEntityPersister
|
||||
/**
|
||||
* Gets the name of the table that owns the column the given field is mapped to.
|
||||
*
|
||||
* @param string $fieldName
|
||||
* @return string
|
||||
* The default implementation in BasicEntityPersister always returns the name
|
||||
* of the table the entity type of this persister is mapped to, since an entity
|
||||
* is always persisted to a single table with a BasicEntityPersister.
|
||||
*
|
||||
* @param string $fieldName The field name.
|
||||
* @return string The table name.
|
||||
*/
|
||||
public function getOwningTable($fieldName)
|
||||
{
|
||||
@ -423,13 +483,13 @@ class StandardEntityPersister
|
||||
* a new entity is created.
|
||||
* @param $assoc The association that connects the entity to load to another entity, if any.
|
||||
* @param array $hints Hints for entity creation.
|
||||
* @return The loaded entity instance or NULL if the entity/the data can not be found.
|
||||
* @return object The loaded and managed entity instance or NULL if the entity can not be found.
|
||||
* @todo Check identity map? loadById method? Try to guess whether $criteria is the id?
|
||||
*/
|
||||
public function load(array $criteria, $entity = null, $assoc = null, array $hints = array())
|
||||
{
|
||||
$sql = $this->_getSelectEntitiesSQL($criteria, $assoc);
|
||||
$params = array_values($criteria);
|
||||
$stmt = $this->_conn->executeQuery($sql, $params);
|
||||
$stmt = $this->_conn->executeQuery($sql, array_values($criteria));
|
||||
$result = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
$stmt->closeCursor();
|
||||
|
||||
@ -437,17 +497,80 @@ class StandardEntityPersister
|
||||
}
|
||||
|
||||
/**
|
||||
* Refreshes an entity.
|
||||
* Loads an entity of this persister's mapped class as part of a single-valued
|
||||
* association from another entity.
|
||||
*
|
||||
* @param OneToOneMapping $assoc The association to load.
|
||||
* @param object $sourceEntity The entity that owns the association (not necessarily the "owning side").
|
||||
* @param object $targetEntity The existing ghost entity (proxy) to load, if any.
|
||||
* @param array $identifier The identifier of the entity to load. Must be provided if
|
||||
* the association to load represents the owning side, otherwise
|
||||
* the identifier is derived from the $sourceEntity.
|
||||
* @return object The loaded and managed entity instance or NULL if the entity can not be found.
|
||||
*/
|
||||
public function loadOneToOneEntity(OneToOneMapping $assoc, $sourceEntity, $targetEntity, array $identifier = array())
|
||||
{
|
||||
$targetClass = $this->_em->getClassMetadata($assoc->targetEntityName);
|
||||
|
||||
if ($assoc->isOwningSide) {
|
||||
// Mark inverse side as fetched in the hints, otherwise the UoW would
|
||||
// try to load it in a separate query (remember: to-one inverse sides can not be lazy).
|
||||
$hints = array();
|
||||
if ($assoc->inversedBy) {
|
||||
$hints['fetched'][$targetClass->name][$assoc->inversedBy] = true;
|
||||
if ($targetClass->subClasses) {
|
||||
foreach ($targetClass->subClasses as $targetSubclassName) {
|
||||
$hints['fetched'][$targetSubclassName][$assoc->inversedBy] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* cascade read-only status
|
||||
if ($this->_em->getUnitOfWork()->isReadOnly($sourceEntity)) {
|
||||
$hints[Query::HINT_READ_ONLY] = true;
|
||||
}
|
||||
*/
|
||||
|
||||
$targetEntity = $this->load($identifier, $targetEntity, $assoc, $hints);
|
||||
|
||||
// Complete bidirectional association, if necessary
|
||||
if ($targetEntity !== null && $assoc->inversedBy && ! $targetClass->isCollectionValuedAssociation($assoc->inversedBy)) {
|
||||
$targetClass->reflFields[$assoc->inversedBy]->setValue($targetEntity, $sourceEntity);
|
||||
}
|
||||
} else {
|
||||
$sourceClass = $this->_em->getClassMetadata($assoc->sourceEntityName);
|
||||
$owningAssoc = $targetClass->getAssociationMapping($assoc->mappedBy);
|
||||
// TRICKY: since the association is specular source and target are flipped
|
||||
foreach ($owningAssoc->targetToSourceKeyColumns as $sourceKeyColumn => $targetKeyColumn) {
|
||||
if (isset($sourceClass->fieldNames[$sourceKeyColumn])) {
|
||||
$identifier[$targetKeyColumn] = $sourceClass->reflFields[$sourceClass->fieldNames[$sourceKeyColumn]]->getValue($sourceEntity);
|
||||
} else {
|
||||
throw MappingException::joinColumnMustPointToMappedField(
|
||||
$sourceClass->name, $sourceKeyColumn
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$targetEntity = $this->load($identifier, $targetEntity, $assoc);
|
||||
|
||||
if ($targetEntity !== null) {
|
||||
$targetClass->setFieldValue($targetEntity, $assoc->mappedBy, $sourceEntity);
|
||||
}
|
||||
}
|
||||
|
||||
return $targetEntity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Refreshes a managed entity.
|
||||
*
|
||||
* @param array $id The identifier of the entity as an associative array from column names to values.
|
||||
* @param array $id The identifier of the entity as an associative array from
|
||||
* column or field names to values.
|
||||
* @param object $entity The entity to refresh.
|
||||
*/
|
||||
public function refresh(array $id, $entity)
|
||||
{
|
||||
$sql = $this->_getSelectEntitiesSQL($id);
|
||||
$params = array_values($id);
|
||||
|
||||
$stmt = $this->_conn->executeQuery($sql, $params);
|
||||
$stmt = $this->_conn->executeQuery($sql, array_values($id));
|
||||
$result = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
$stmt->closeCursor();
|
||||
|
||||
@ -527,10 +650,8 @@ class StandardEntityPersister
|
||||
public function loadAll(array $criteria = array())
|
||||
{
|
||||
$entities = array();
|
||||
|
||||
$sql = $this->_getSelectEntitiesSQL($criteria);
|
||||
$params = array_values($criteria);
|
||||
$stmt = $this->_conn->executeQuery($sql, $params);
|
||||
$stmt = $this->_conn->executeQuery($sql, array_values($criteria));
|
||||
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
$stmt->closeCursor();
|
||||
|
||||
@ -541,37 +662,44 @@ class StandardEntityPersister
|
||||
return $entities;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a collection of entities in a one-to-many association.
|
||||
*
|
||||
* @param OneToManyMapping $assoc
|
||||
* @param array $criteria The criteria by which to select the entities.
|
||||
* @param PersistentCollection The collection to fill.
|
||||
*/
|
||||
public function loadOneToManyCollection($assoc, array $criteria, PersistentCollection $coll)
|
||||
{
|
||||
$owningAssoc = $this->_class->associationMappings[$coll->getMapping()->mappedBy];
|
||||
$sql = $this->_getSelectEntitiesSQL($criteria, $owningAssoc, $assoc->orderBy);
|
||||
$params = array_values($criteria);
|
||||
$stmt = $this->_conn->executeQuery($sql, $params);
|
||||
while ($result = $stmt->fetch(PDO::FETCH_ASSOC)) {
|
||||
$coll->hydrateAdd($this->_createEntity($result));
|
||||
}
|
||||
$stmt->closeCursor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a collection of entities of a many-to-many association.
|
||||
*
|
||||
* @param ManyToManyMapping $assoc
|
||||
* @param array $criteria
|
||||
* @param ManyToManyMapping $assoc The association mapping of the association being loaded.
|
||||
* @param object $sourceEntity The entity that owns the collection.
|
||||
* @param PersistentCollection $coll The collection to fill.
|
||||
*/
|
||||
public function loadManyToManyCollection($assoc, array $criteria, PersistentCollection $coll)
|
||||
public function loadManyToManyCollection(ManyToManyMapping $assoc, $sourceEntity, PersistentCollection $coll)
|
||||
{
|
||||
$sql = $this->_getSelectManyToManyEntityCollectionSQL($assoc, $criteria);
|
||||
$params = array_values($criteria);
|
||||
$stmt = $this->_conn->executeQuery($sql, $params);
|
||||
$criteria = array();
|
||||
$sourceClass = $this->_em->getClassMetadata($assoc->sourceEntityName);
|
||||
$joinTableConditions = array();
|
||||
if ($assoc->isOwningSide) {
|
||||
foreach ($assoc->relationToSourceKeyColumns as $relationKeyColumn => $sourceKeyColumn) {
|
||||
if (isset($sourceClass->fieldNames[$sourceKeyColumn])) {
|
||||
$criteria[$relationKeyColumn] = $sourceClass->reflFields[$sourceClass->fieldNames[$sourceKeyColumn]]->getValue($sourceEntity);
|
||||
} else {
|
||||
throw MappingException::joinColumnMustPointToMappedField(
|
||||
$sourceClass->name, $sourceKeyColumn
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$owningAssoc = $this->_em->getClassMetadata($assoc->targetEntityName)->associationMappings[$assoc->mappedBy];
|
||||
// TRICKY: since the association is inverted source and target are flipped
|
||||
foreach ($owningAssoc->relationToTargetKeyColumns as $relationKeyColumn => $sourceKeyColumn) {
|
||||
if (isset($sourceClass->fieldNames[$sourceKeyColumn])) {
|
||||
$criteria[$relationKeyColumn] = $sourceClass->reflFields[$sourceClass->fieldNames[$sourceKeyColumn]]->getValue($sourceEntity);
|
||||
} else {
|
||||
throw MappingException::joinColumnMustPointToMappedField(
|
||||
$sourceClass->name, $sourceKeyColumn
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$sql = $this->_getSelectEntitiesSQL($criteria, $assoc);
|
||||
$stmt = $this->_conn->executeQuery($sql, array_values($criteria));
|
||||
while ($result = $stmt->fetch(PDO::FETCH_ASSOC)) {
|
||||
$coll->hydrateAdd($this->_createEntity($result));
|
||||
}
|
||||
@ -613,10 +741,15 @@ class StandardEntityPersister
|
||||
/**
|
||||
* Processes an SQL result set row that contains data for an entity of the type
|
||||
* this persister is responsible for.
|
||||
*
|
||||
* Subclasses are supposed to override this method if they need to change the
|
||||
* hydration procedure for entities loaded through basic find operations or
|
||||
* lazy-loading (not DQL).
|
||||
*
|
||||
* @param array $sqlResult The SQL result set row to process.
|
||||
* @return array A tuple where the first value is the actual type of the entity and
|
||||
* the second value the prepared data of the entity.
|
||||
* the second value the prepared data of the entity (a map from field
|
||||
* names to values).
|
||||
*/
|
||||
protected function _processSQLResult(array $sqlResult)
|
||||
{
|
||||
@ -640,51 +773,37 @@ class StandardEntityPersister
|
||||
*
|
||||
* @param array $criteria
|
||||
* @param AssociationMapping $assoc
|
||||
* @param string $orderBy
|
||||
* @return string
|
||||
* @todo Refactor: _getSelectSQL(...)
|
||||
*/
|
||||
protected function _getSelectEntitiesSQL(array &$criteria, $assoc = null, $orderBy = null)
|
||||
protected function _getSelectEntitiesSQL(array $criteria, $assoc = null)
|
||||
{
|
||||
// Construct WHERE conditions
|
||||
$conditionSql = '';
|
||||
foreach ($criteria as $field => $value) {
|
||||
if ($conditionSql != '') {
|
||||
$conditionSql .= ' AND ';
|
||||
}
|
||||
|
||||
if (isset($this->_class->columnNames[$field])) {
|
||||
$conditionSql .= $this->_class->getQuotedColumnName($field, $this->_platform);
|
||||
} else if (isset($this->_class->fieldNames[$field])) {
|
||||
$conditionSql .= $this->_class->getQuotedColumnName($this->_class->fieldNames[$field], $this->_platform);
|
||||
} else if ($assoc !== null) {
|
||||
$conditionSql .= $field;
|
||||
} else {
|
||||
throw ORMException::unrecognizedField($field);
|
||||
}
|
||||
$conditionSql .= ' = ?';
|
||||
}
|
||||
$joinSql = $assoc != null && $assoc->isManyToMany() ?
|
||||
$this->_getSelectManyToManyJoinSQL($assoc) : '';
|
||||
|
||||
$orderBySql = '';
|
||||
if ($orderBy !== null) {
|
||||
$orderBySql = $this->_getCollectionOrderBySQL(
|
||||
$orderBy, $this->_getSQLTableAlias($this->_class)
|
||||
);
|
||||
}
|
||||
$conditionSql = $this->_getSelectConditionSQL($criteria, $assoc);
|
||||
|
||||
$orderBySql = $assoc !== null && isset($assoc->orderBy) ?
|
||||
$this->_getCollectionOrderBySQL($assoc->orderBy, $this->_getSQLTableAlias($this->_class->name))
|
||||
: '';
|
||||
|
||||
return 'SELECT ' . $this->_getSelectColumnListSQL()
|
||||
. ' FROM ' . $this->_class->getQuotedTableName($this->_platform) . ' '
|
||||
. $this->_getSQLTableAlias($this->_class)
|
||||
. ($conditionSql ? ' WHERE ' . $conditionSql : '') . $orderBySql;
|
||||
. $this->_getSQLTableAlias($this->_class->name)
|
||||
. $joinSql
|
||||
. ($conditionSql ? ' WHERE ' . $conditionSql : '')
|
||||
. $orderBySql;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate ORDER BY SQL snippet for ordered collections.
|
||||
* Gets the ORDER BY SQL snippet for ordered collections.
|
||||
*
|
||||
* @param array $orderBy
|
||||
* @param string $baseTableAlias
|
||||
* @return string
|
||||
* @todo Rename: _getOrderBySQL
|
||||
*/
|
||||
protected function _getCollectionOrderBySQL(array $orderBy, $baseTableAlias)
|
||||
protected final function _getCollectionOrderBySQL(array $orderBy, $baseTableAlias)
|
||||
{
|
||||
$orderBySql = '';
|
||||
foreach ($orderBy as $fieldName => $orientation) {
|
||||
@ -693,27 +812,28 @@ class StandardEntityPersister
|
||||
}
|
||||
|
||||
$tableAlias = isset($this->_class->fieldMappings[$fieldName]['inherited']) ?
|
||||
$this->_getSQLTableAlias($this->_em->getClassMetadata($this->_class->fieldMappings[$fieldName]['inherited']))
|
||||
$this->_getSQLTableAlias($this->_class->fieldMappings[$fieldName]['inherited'])
|
||||
: $baseTableAlias;
|
||||
|
||||
$columnName = $this->_class->getQuotedColumnName($fieldName, $this->_platform);
|
||||
if ($orderBySql != '') {
|
||||
$orderBySql .= ', ';
|
||||
} else {
|
||||
$orderBySql = ' ORDER BY ';
|
||||
}
|
||||
$orderBySql .= $orderBySql ? ', ' : 'ORDER BY ';
|
||||
$orderBySql .= $tableAlias . '.' . $columnName . ' ' . $orientation;
|
||||
}
|
||||
|
||||
return $orderBySql;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the SQL fragment with the list of columns to select when querying for
|
||||
* an entity within this persister.
|
||||
* an entity in this persister.
|
||||
*
|
||||
* Subclasses should override this method to alter or change the select column
|
||||
* list SQL fragment. Note that in the implementation of StandardEntityPersister
|
||||
* the resulting SQL fragment is generated only once and cached in {@link _selectColumnListSql}.
|
||||
* Subclasses may or may not do the same.
|
||||
*
|
||||
* @return string The SQL fragment.
|
||||
* @todo Rename: _getSelectColumnListSQL()
|
||||
* @todo Rename: _getSelectColumnsSQL()
|
||||
*/
|
||||
protected function _getSelectColumnListSQL()
|
||||
{
|
||||
@ -725,7 +845,7 @@ class StandardEntityPersister
|
||||
|
||||
// Add regular columns to select list
|
||||
foreach ($this->_class->fieldNames as $field) {
|
||||
if ($columnList != '') $columnList .= ', ';
|
||||
if ($columnList) $columnList .= ', ';
|
||||
$columnList .= $this->_getSelectColumnSQL($field, $this->_class);
|
||||
}
|
||||
|
||||
@ -733,15 +853,15 @@ class StandardEntityPersister
|
||||
|
||||
return $this->_selectColumnListSql;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the SQL to select a collection of entities in a many-many association.
|
||||
* Gets the SQL join fragment used when selecting entities from a
|
||||
* many-to-many association.
|
||||
*
|
||||
* @param ManyToManyMapping $manyToMany
|
||||
* @param array $criteria
|
||||
* @return string
|
||||
*/
|
||||
protected function _getSelectManyToManyEntityCollectionSQL($manyToMany, array &$criteria)
|
||||
protected function _getSelectManyToManyJoinSQL(ManyToManyMapping $manyToMany)
|
||||
{
|
||||
if ($manyToMany->isOwningSide) {
|
||||
$owningAssoc = $manyToMany;
|
||||
@ -756,32 +876,12 @@ class StandardEntityPersister
|
||||
$joinSql = '';
|
||||
foreach ($joinClauses as $joinTableColumn => $sourceColumn) {
|
||||
if ($joinSql != '') $joinSql .= ' AND ';
|
||||
$joinSql .= $this->_getSQLTableAlias($this->_class) .
|
||||
$joinSql .= $this->_getSQLTableAlias($this->_class->name) .
|
||||
'.' . $this->_class->getQuotedColumnName($this->_class->fieldNames[$sourceColumn], $this->_platform) . ' = '
|
||||
. $joinTableName . '.' . $joinTableColumn;
|
||||
}
|
||||
|
||||
$joinSql = ' INNER JOIN ' . $joinTableName . ' ON ' . $joinSql;
|
||||
|
||||
$conditionSql = '';
|
||||
foreach ($criteria as $joinColumn => $value) {
|
||||
if ($conditionSql != '') $conditionSql .= ' AND ';
|
||||
$columnName = $joinTableName . '.' . $joinColumn;
|
||||
$conditionSql .= $columnName . ' = ?';
|
||||
}
|
||||
|
||||
$orderBySql = '';
|
||||
if ($manyToMany->orderBy !== null) {
|
||||
$orderBySql = $this->_getCollectionOrderBySQL(
|
||||
$manyToMany->orderBy, $this->_getSQLTableAlias($this->_class)
|
||||
);
|
||||
}
|
||||
|
||||
return 'SELECT ' . $this->_getSelectColumnListSQL()
|
||||
. ' FROM ' . $this->_class->getQuotedTableName($this->_platform) . ' '
|
||||
. $this->_getSQLTableAlias($this->_class)
|
||||
. $joinSql
|
||||
. ' WHERE ' . $conditionSql . $orderBySql;
|
||||
return " INNER JOIN $joinTableName ON $joinSql";
|
||||
}
|
||||
|
||||
/**
|
||||
@ -789,19 +889,36 @@ class StandardEntityPersister
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getInsertSQL()
|
||||
protected function _getInsertSQL()
|
||||
{
|
||||
if ($this->_insertSql === null) {
|
||||
$this->_insertSql = $this->_generateInsertSQL();
|
||||
$insertSql = '';
|
||||
$columns = $this->_getInsertColumnList();
|
||||
if (empty($columns)) {
|
||||
$insertSql = $this->_platform->getEmptyIdentityInsertSQL(
|
||||
$this->_class->getQuotedTableName($this->_platform),
|
||||
$this->_class->getQuotedColumnName($this->_class->identifier[0], $this->_platform)
|
||||
);
|
||||
} else {
|
||||
$columns = array_unique($columns);
|
||||
$values = array_fill(0, count($columns), '?');
|
||||
|
||||
$insertSql = 'INSERT INTO ' . $this->_class->getQuotedTableName($this->_platform)
|
||||
. ' (' . implode(', ', $columns) . ') '
|
||||
. 'VALUES (' . implode(', ', $values) . ')';
|
||||
}
|
||||
$this->_insertSql = $insertSql;
|
||||
}
|
||||
return $this->_insertSql;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the list of columns to put in the INSERT SQL statement.
|
||||
*
|
||||
*
|
||||
* Subclasses should override this method to alter or change the list of
|
||||
* columns placed in the INSERT statements used by the persister.
|
||||
*
|
||||
* @return array The list of columns.
|
||||
* @internal INSERT SQL is cached by getInsertSQL() per request.
|
||||
*/
|
||||
protected function _getInsertColumnList()
|
||||
{
|
||||
@ -826,33 +943,6 @@ class StandardEntityPersister
|
||||
return $columns;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the INSERT SQL used by the persister to persist entities.
|
||||
*
|
||||
* @return string
|
||||
* @internal Result is cached by getInsertSQL() per request.
|
||||
*/
|
||||
protected function _generateInsertSQL()
|
||||
{
|
||||
$insertSql = '';
|
||||
$columns = $this->_getInsertColumnList();
|
||||
if (empty($columns)) {
|
||||
$insertSql = $this->_platform->getEmptyIdentityInsertSQL(
|
||||
$this->_class->getQuotedTableName($this->_platform),
|
||||
$this->_class->getQuotedColumnName($this->_class->identifier[0], $this->_platform)
|
||||
);
|
||||
} else {
|
||||
$columns = array_unique($columns);
|
||||
$values = array_fill(0, count($columns), '?');
|
||||
|
||||
$insertSql = 'INSERT INTO ' . $this->_class->getQuotedTableName($this->_platform)
|
||||
. ' (' . implode(', ', $columns) . ') '
|
||||
. 'VALUES (' . implode(', ', $values) . ')';
|
||||
}
|
||||
|
||||
return $insertSql;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the SQL snippet of a qualified column name for the given field name.
|
||||
*
|
||||
@ -863,7 +953,7 @@ class StandardEntityPersister
|
||||
protected function _getSelectColumnSQL($field, ClassMetadata $class)
|
||||
{
|
||||
$columnName = $class->columnNames[$field];
|
||||
$sql = $this->_getSQLTableAlias($class) . '.' . $class->getQuotedColumnName($field, $this->_platform);
|
||||
$sql = $this->_getSQLTableAlias($class->name) . '.' . $class->getQuotedColumnName($field, $this->_platform);
|
||||
$columnAlias = $this->_platform->getSQLResultCasing($columnName . $this->_sqlAliasCounter++);
|
||||
if ( ! isset($this->_resultColumnNames[$columnAlias])) {
|
||||
$this->_resultColumnNames[$columnAlias] = $columnName;
|
||||
@ -875,17 +965,19 @@ class StandardEntityPersister
|
||||
/**
|
||||
* Gets the SQL snippet for all join columns of the given class that are to be
|
||||
* placed in an SQL SELECT statement.
|
||||
*
|
||||
*
|
||||
* @param $class
|
||||
* @return string
|
||||
* @todo Not reused... inline?
|
||||
*/
|
||||
protected function _getSelectJoinColumnsSQL(ClassMetadata $class)
|
||||
private function _getSelectJoinColumnsSQL(ClassMetadata $class)
|
||||
{
|
||||
$sql = '';
|
||||
foreach ($class->associationMappings as $assoc) {
|
||||
if ($assoc->isOwningSide && $assoc->isOneToOne()) {
|
||||
foreach ($assoc->targetToSourceKeyColumns as $srcColumn) {
|
||||
$columnAlias = $srcColumn . $this->_sqlAliasCounter++;
|
||||
$sql .= ', ' . $this->_getSQLTableAlias($this->_class) . ".$srcColumn AS $columnAlias";
|
||||
$sql .= ', ' . $this->_getSQLTableAlias($this->_class->name) . ".$srcColumn AS $columnAlias";
|
||||
$resultColumnName = $this->_platform->getSQLResultCasing($columnAlias);
|
||||
if ( ! isset($this->_resultColumnNames[$resultColumnName])) {
|
||||
$this->_resultColumnNames[$resultColumnName] = $srcColumn;
|
||||
@ -898,19 +990,92 @@ class StandardEntityPersister
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the SQL table alias for the given class.
|
||||
* Gets the SQL table alias for the given class name.
|
||||
*
|
||||
* @param ClassMetadata $class
|
||||
* @param string $className
|
||||
* @return string The SQL table alias.
|
||||
* @todo Remove. Binding table aliases to class names is not such a good idea.
|
||||
*/
|
||||
protected function _getSQLTableAlias(ClassMetadata $class)
|
||||
protected function _getSQLTableAlias($className)
|
||||
{
|
||||
if (isset($this->_sqlTableAliases[$class->name])) {
|
||||
return $this->_sqlTableAliases[$class->name];
|
||||
if (isset($this->_sqlTableAliases[$className])) {
|
||||
return $this->_sqlTableAliases[$className];
|
||||
}
|
||||
$tableAlias = $class->table['name'][0] . $this->_sqlAliasCounter++;
|
||||
$this->_sqlTableAliases[$class->name] = $tableAlias;
|
||||
$tableAlias = 't' . $this->_sqlAliasCounter++;
|
||||
$this->_sqlTableAliases[$className] = $tableAlias;
|
||||
|
||||
return $tableAlias;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the conditional SQL fragment used in the WHERE clause when selecting
|
||||
* entities in this persister.
|
||||
*
|
||||
* Subclasses are supposed to override this method if they intend to change
|
||||
* or alter the criteria by which entities are selected.
|
||||
*
|
||||
* @param array $criteria
|
||||
* @param AssociationMapping $assoc
|
||||
* @return string
|
||||
*/
|
||||
protected function _getSelectConditionSQL(array $criteria, $assoc = null)
|
||||
{
|
||||
$conditionSql = '';
|
||||
foreach ($criteria as $field => $value) {
|
||||
$conditionSql .= $conditionSql ? ' AND ' : '';
|
||||
|
||||
if (isset($this->_class->columnNames[$field])) {
|
||||
if (isset($this->_class->fieldMappings[$field]['inherited'])) {
|
||||
$conditionSql .= $this->_getSQLTableAlias($this->_class->fieldMappings[$field]['inherited']) . '.';
|
||||
} else {
|
||||
$conditionSql .= $this->_getSQLTableAlias($this->_class->name) . '.';
|
||||
}
|
||||
$conditionSql .= $this->_class->getQuotedColumnName($field, $this->_platform);
|
||||
} else if ($assoc !== null) {
|
||||
if ($assoc->isManyToMany()) {
|
||||
$owningAssoc = $assoc->isOwningSide ? $assoc : $this->_em->getClassMetadata($assoc->targetEntityName)
|
||||
->associationMappings[$assoc->mappedBy];
|
||||
$conditionSql .= $owningAssoc->getQuotedJoinTableName($this->_platform) . '.' . $field;
|
||||
} else {
|
||||
$conditionSql .= $field;
|
||||
}
|
||||
} else {
|
||||
throw ORMException::unrecognizedField($field);
|
||||
}
|
||||
$conditionSql .= ' = ?';
|
||||
}
|
||||
|
||||
return $conditionSql;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a collection of entities in a one-to-many association.
|
||||
*
|
||||
* @param OneToManyMapping $assoc
|
||||
* @param array $criteria The criteria by which to select the entities.
|
||||
* @param PersistentCollection The collection to load/fill.
|
||||
*/
|
||||
public function loadOneToManyCollection(OneToManyMapping $assoc, $sourceEntity, PersistentCollection $coll)
|
||||
{
|
||||
$criteria = array();
|
||||
$owningAssoc = $this->_class->associationMappings[$assoc->mappedBy];
|
||||
$sourceClass = $this->_em->getClassMetadata($assoc->sourceEntityName);
|
||||
foreach ($owningAssoc->targetToSourceKeyColumns as $sourceKeyColumn => $targetKeyColumn) {
|
||||
$criteria[$targetKeyColumn] = $sourceClass->reflFields[$sourceClass->fieldNames[$sourceKeyColumn]]->getValue($sourceEntity);
|
||||
}
|
||||
|
||||
$sql = $this->_getSelectEntitiesSQL($criteria, $assoc);
|
||||
$params = array_values($criteria);
|
||||
$stmt = $this->_conn->executeQuery($sql, $params);
|
||||
while ($result = $stmt->fetch(PDO::FETCH_ASSOC)) {
|
||||
$coll->hydrateAdd($this->_createEntity($result));
|
||||
}
|
||||
$stmt->closeCursor();
|
||||
}
|
||||
|
||||
//TODO
|
||||
/*protected function _getOneToOneEagerFetchSQL()
|
||||
{
|
||||
|
||||
}*/
|
||||
}
|
||||
|
@ -1,7 +1,5 @@
|
||||
<?php
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
@ -44,13 +42,13 @@ class ProxyFactory
|
||||
private $_proxyDir;
|
||||
|
||||
/**
|
||||
* Initializes a new instance of the <tt>ProxyFactory</tt> class that is
|
||||
* connected to the given <tt>EntityManager</tt>.
|
||||
*
|
||||
* @param EntityManager $em The EntityManager the new factory works for.
|
||||
* @param string $proxyDir The directory to use for the proxy classes. It must exist.
|
||||
* @param string $proxyNs The namespace to use for the proxy classes.
|
||||
* @param boolean $autoGenerate Whether to automatically generate proxy classes.
|
||||
* Initializes a new instance of the <tt>ProxyFactory</tt> class that is
|
||||
* connected to the given <tt>EntityManager</tt>.
|
||||
*
|
||||
* @param EntityManager $em The EntityManager the new factory works for.
|
||||
* @param string $proxyDir The directory to use for the proxy classes. It must exist.
|
||||
* @param string $proxyNs The namespace to use for the proxy classes.
|
||||
* @param boolean $autoGenerate Whether to automatically generate proxy classes.
|
||||
*/
|
||||
public function __construct(EntityManager $em, $proxyDir, $proxyNs, $autoGenerate = false)
|
||||
{
|
||||
@ -240,7 +238,7 @@ class ProxyFactory
|
||||
return $sleepImpl;
|
||||
}
|
||||
|
||||
/** Reference Proxy class code template */
|
||||
/** Proxy class code template */
|
||||
private static $_proxyClassTemplate =
|
||||
'<?php
|
||||
|
||||
|
@ -286,9 +286,7 @@ class SqlWalker implements TreeWalker
|
||||
$sql = '';
|
||||
foreach ($this->_selectedClasses AS $dqlAlias => $class) {
|
||||
$qComp = $this->_queryComponents[$dqlAlias];
|
||||
if (isset($qComp['relation']) && ($qComp['relation']->isManyToMany() || $qComp['relation']->isOneToMany())
|
||||
&& $qComp['relation']->orderBy != null) {
|
||||
|
||||
if (isset($qComp['relation']->orderBy)) {
|
||||
foreach ($qComp['relation']->orderBy AS $fieldName => $orientation) {
|
||||
if ($qComp['metadata']->isInheritanceTypeJoined()) {
|
||||
$tableName = $this->_em->getUnitOfWork()->getEntityPersister($class->name)->getOwningTable($fieldName);
|
||||
@ -299,8 +297,8 @@ class SqlWalker implements TreeWalker
|
||||
if ($sql != '') {
|
||||
$sql .= ', ';
|
||||
}
|
||||
$sql .= $this->getSqlTableAlias($tableName, $dqlAlias) . "." .
|
||||
$qComp['metadata']->getQuotedColumnName($fieldName, $this->_platform) . " ".$orientation;
|
||||
$sql .= $this->getSqlTableAlias($tableName, $dqlAlias) . '.' .
|
||||
$qComp['metadata']->getQuotedColumnName($fieldName, $this->_platform) . " $orientation";
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -313,7 +311,7 @@ class SqlWalker implements TreeWalker
|
||||
* @param string $dqlAlias
|
||||
* @return string
|
||||
*/
|
||||
private function _generateDiscriminatorColumnConditionSql($dqlAlias)
|
||||
private function _generateDiscriminatorColumnConditionSQL($dqlAlias)
|
||||
{
|
||||
$sql = '';
|
||||
|
||||
@ -338,7 +336,6 @@ class SqlWalker implements TreeWalker
|
||||
return $sql;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Walks down a SelectStatement AST node, thereby generating the appropriate SQL.
|
||||
*
|
||||
@ -351,7 +348,7 @@ class SqlWalker implements TreeWalker
|
||||
|
||||
if (($whereClause = $AST->whereClause) !== null) {
|
||||
$sql .= $this->walkWhereClause($whereClause);
|
||||
} else if (($discSql = $this->_generateDiscriminatorColumnConditionSql($this->_currentRootAlias)) !== '') {
|
||||
} else if (($discSql = $this->_generateDiscriminatorColumnConditionSQL($this->_currentRootAlias)) !== '') {
|
||||
$sql .= ' WHERE ' . $discSql;
|
||||
}
|
||||
|
||||
@ -385,7 +382,7 @@ class SqlWalker implements TreeWalker
|
||||
|
||||
if (($whereClause = $AST->whereClause) !== null) {
|
||||
$sql .= $this->walkWhereClause($whereClause);
|
||||
} else if (($discSql = $this->_generateDiscriminatorColumnConditionSql($this->_currentRootAlias)) !== '') {
|
||||
} else if (($discSql = $this->_generateDiscriminatorColumnConditionSQL($this->_currentRootAlias)) !== '') {
|
||||
$sql .= ' WHERE ' . $discSql;
|
||||
}
|
||||
|
||||
@ -405,7 +402,7 @@ class SqlWalker implements TreeWalker
|
||||
|
||||
if (($whereClause = $AST->whereClause) !== null) {
|
||||
$sql .= $this->walkWhereClause($whereClause);
|
||||
} else if (($discSql = $this->_generateDiscriminatorColumnConditionSql($this->_currentRootAlias)) !== '') {
|
||||
} else if (($discSql = $this->_generateDiscriminatorColumnConditionSQL($this->_currentRootAlias)) !== '') {
|
||||
$sql .= ' WHERE ' . $discSql;
|
||||
}
|
||||
|
||||
@ -780,7 +777,7 @@ class SqlWalker implements TreeWalker
|
||||
). ')';
|
||||
}
|
||||
|
||||
$discrSql = $this->_generateDiscriminatorColumnConditionSql($joinedDqlAlias);
|
||||
$discrSql = $this->_generateDiscriminatorColumnConditionSQL($joinedDqlAlias);
|
||||
|
||||
if ($discrSql) {
|
||||
$sql .= ' AND ' . $discrSql;
|
||||
@ -1217,7 +1214,7 @@ class SqlWalker implements TreeWalker
|
||||
' OR ', array_map(array($this, 'walkConditionalTerm'), $condExpr->conditionalTerms)
|
||||
);
|
||||
|
||||
$discrSql = $this->_generateDiscriminatorColumnConditionSql($this->_currentRootAlias);
|
||||
$discrSql = $this->_generateDiscriminatorColumnConditionSQL($this->_currentRootAlias);
|
||||
|
||||
if ($discrSql) {
|
||||
$sql .= ' AND ' . $discrSql;
|
||||
|
@ -1,7 +1,5 @@
|
||||
<?php
|
||||
/*
|
||||
* $Id: UnitOfWork.php 4947 2008-09-12 13:16:05Z romanb $
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
@ -33,15 +31,12 @@ use Doctrine\Common\Collections\ArrayCollection,
|
||||
* "object-level" transaction and for writing out changes to the database
|
||||
* in the correct order.
|
||||
*
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
* @link www.doctrine-project.org
|
||||
* @since 2.0
|
||||
* @version $Revision$
|
||||
* @author Benjamin Eberlei <kontakt@beberlei.de>
|
||||
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
|
||||
* @author Jonathan Wage <jonwage@gmail.com>
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
* @internal This class contains performance-critical code.
|
||||
* @internal This class contains highly performance-sensitive code.
|
||||
*/
|
||||
class UnitOfWork implements PropertyChangedListener
|
||||
{
|
||||
|
@ -17,9 +17,10 @@ class ClassTableInheritanceTest2 extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
$this->_schemaTool->createSchema(array(
|
||||
$this->_em->getClassMetadata('Doctrine\Tests\ORM\Functional\CTIParent'),
|
||||
$this->_em->getClassMetadata('Doctrine\Tests\ORM\Functional\CTIChild'),
|
||||
$this->_em->getClassMetadata('Doctrine\Tests\ORM\Functional\CTIRelated')
|
||||
$this->_em->getClassMetadata('Doctrine\Tests\ORM\Functional\CTIRelated'),
|
||||
$this->_em->getClassMetadata('Doctrine\Tests\ORM\Functional\CTIRelated2')
|
||||
));
|
||||
} catch (\Exception $e) {
|
||||
} catch (\Exception $ignored) {
|
||||
// Swallow all exceptions. We do not test the schema tool here.
|
||||
}
|
||||
}
|
||||
@ -49,6 +50,27 @@ class ClassTableInheritanceTest2 extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
|
||||
$this->assertSame($related2, $related2->getCTIParent()->getRelated());
|
||||
}
|
||||
|
||||
public function testManyToManyToCTIHierarchy()
|
||||
{
|
||||
//$this->_em->getConnection()->getConfiguration()->setSQLLogger(new \Doctrine\DBAL\Logging\EchoSQLLogger());
|
||||
$mmrel = new CTIRelated2;
|
||||
$child = new CTIChild;
|
||||
$child->setData('child');
|
||||
$mmrel->addCTIChild($child);
|
||||
|
||||
$this->_em->persist($mmrel);
|
||||
$this->_em->persist($child);
|
||||
|
||||
$this->_em->flush();
|
||||
$this->_em->clear();
|
||||
|
||||
$mmrel2 = $this->_em->find(get_class($mmrel), $mmrel->getId());
|
||||
$this->assertFalse($mmrel2->getCTIChildren()->isInitialized());
|
||||
$this->assertEquals(1, count($mmrel2->getCTIChildren()));
|
||||
$this->assertTrue($mmrel2->getCTIChildren()->isInitialized());
|
||||
$this->assertTrue($mmrel2->getCTIChildren()->get(0) instanceof CTIChild);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -126,3 +148,29 @@ class CTIRelated {
|
||||
$this->ctiParent = $ctiParent;
|
||||
}
|
||||
}
|
||||
|
||||
/** @Entity */
|
||||
class CTIRelated2
|
||||
{
|
||||
/** @Id @Column(type="integer") @GeneratedValue */
|
||||
private $id;
|
||||
/** @ManyToMany(targetEntity="CTIChild") */
|
||||
private $ctiChildren;
|
||||
|
||||
|
||||
public function __construct() {
|
||||
$this->ctiChildren = new \Doctrine\Common\Collections\ArrayCollection;
|
||||
}
|
||||
|
||||
public function getId() {
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function addCTIChild(CTIChild $child) {
|
||||
$this->ctiChildren->add($child);
|
||||
}
|
||||
|
||||
public function getCTIChildren() {
|
||||
return $this->ctiChildren;
|
||||
}
|
||||
}
|
||||
|
@ -66,6 +66,7 @@ class SingleTableInheritanceTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
|
||||
$this->_em->clear();
|
||||
|
||||
// READ by DQL on subtype
|
||||
$query = $this->_em->createQuery("select e from Doctrine\Tests\ORM\Functional\ChildEntity e");
|
||||
$entities = $query->getResult();
|
||||
$this->assertEquals(1, count($entities));
|
||||
@ -77,6 +78,18 @@ class SingleTableInheritanceTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
|
||||
$this->_em->clear();
|
||||
|
||||
// READ by findAll() on subtype
|
||||
$entities = $this->_em->getRepository('Doctrine\Tests\ORM\Functional\ChildEntity')->findAll();
|
||||
$this->assertEquals(1, count($entities));
|
||||
$this->assertTrue($entities[0] instanceof ChildEntity);
|
||||
$this->assertTrue(is_numeric($entities[0]->getId()));
|
||||
$this->assertEquals('thedata', $entities[0]->getData());
|
||||
$this->assertEquals(1234, $entities[0]->getNumber());
|
||||
$this->assertNull($entities[0]->getParentRelated());
|
||||
|
||||
$this->_em->clear();
|
||||
|
||||
// READ by joining into an STI hierarchy from outwards
|
||||
$query = $this->_em->createQuery("select r,o from Doctrine\Tests\ORM\Functional\RelatedEntity r join r.owner o");
|
||||
|
||||
$entities = $query->getResult();
|
||||
@ -194,7 +207,7 @@ class SingleTableInheritanceTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
class ParentEntity {
|
||||
/**
|
||||
* @Id
|
||||
* @Column(type="integer")
|
||||
* @Column(name="parent_id", type="integer")
|
||||
* @GeneratedValue(strategy="AUTO")
|
||||
*/
|
||||
private $id;
|
||||
@ -317,7 +330,7 @@ class ParentRelatedEntity {
|
||||
public function setData($data) {$this->data = $data;}
|
||||
/**
|
||||
* @OneToOne(targetEntity="ParentEntity")
|
||||
* @JoinColumn(name="parent_id", referencedColumnName="id")
|
||||
* @JoinColumn(name="parent_id", referencedColumnName="parent_id")
|
||||
*/
|
||||
private $parent;
|
||||
public function getParent() {return $this->parent;}
|
||||
|
Loading…
x
Reference in New Issue
Block a user