2013-02-26 7 views
15

Trong bảng DB của chúng tôi, chúng tôi cột refIDdate là một khóa chính composite, với một lĩnh vực nhận dạng được ánh xạ như một datetime:thuyết 2 ORM DateTime trường trong nhận dạng

class corpWalletJournal 
{ 
    /** 
    * @ORM\Column(name="refID", type="bigint", nullable=false) 
    * @ORM\Id 
    * @ORM\GeneratedValue(strategy="NONE") 
    */ 
    private $refID; 

    /** 
    * @ORM\Column(name="date", type="datetime", nullable=false)  
    * @ORM\Id 
    * @ORM\GeneratedValue(strategy="NONE") 
    */ 
    private $date; 

    public function setRefID($refID) 
    { 
     $this->refID = $refID; 
    } 

    public function setDate(\DateTime $date) 
    { 
     $this->date = $date; 
    } 
} 

Nếu chúng tôi mô tả chúng trong thực thể như @ORM \ Id mã này sẽ trở lại ngoại lệ "không thể chuyển đổi datetime để chuỗi" ...

$filter = array(
    'date' => $this->stringToDate($loopData['date']), 
    'refID' => $loopData['refID'] 
)); 

$oCorpWJ = $this->em->getRepository('EveDataBundle:corpWalletJournal')->findOneBy($filter); 
// ... 
$oCorpWJ->setDate($this->stringToDate($loopData['date'])); 
// ... 

Nếu chúng tôi mô tả corpWalletJournal#date như một cột đơn giản, mã hoạt động tốt. Tại sao?

Làm cách nào để chúng tôi có thể giải quyết vấn đề này? Chúng tôi cần có cả hai số daterefID trong khóa chính.

thêm:

Vì vậy, tôi tạo ra lớp mới

use \DateTime; 

class DateTimeEx extends DateTime 
{ 

public function __toString() 
{ 
    return $this->format('Y-m-d h:i:s'); 
} 

} 

Và kiểu mới cho nó

use Doctrine\DBAL\Types\Type; 
use Doctrine\DBAL\Platforms\AbstractPlatform; 
use Eve\DataBundle\Entity\Type\DateTimeEx; 

class DateTimeEx extends Type 
{ 
    const DateTimeEx = 'datetime_ex'; 

    public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform) 
    { 
     return 'my_datetime_ex'; 
    } 

    public function convertToPHPValue($value, AbstractPlatform $platform) 
    { 
     return new DateTimeEx($value); 
    } 

    public function convertToDatabaseValue($value, AbstractPlatform $platform) 
    { 
     return $value->format('Y-m-d h:i:s'); 
    } 

    public function getName() 
    { 
     return self::DateTimeEx; 
    } 

    public function canRequireSQLConversion() 
    { 
     return true; 
    } 

} 

Làm thế nào tôi có thể sử dụng chúng trong thực thể?

của tôi (chỉnh sửa) Gõ Lớp

use Doctrine\DBAL\Types\Type; 
use Doctrine\DBAL\Platforms\AbstractPlatform; 

class DateTimeEx extends Type 
{ 
    const DateTimeEx = 'datetime_ex'; 

    public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform) 
    { 
     return 'my_datetime_ex'; 
    } 

    public function convertToPHPValue($value, AbstractPlatform $platform) 
    { 
     return $value; 
    } 

    public function convertToDatabaseValue($value, AbstractPlatform $platform) 
    { 
     return $value; 
    } 

    public function getName() 
    { 
     return self::DateTimeEx; 
    } 

} 

Trả lời

33

thuyết 2 ORM cần phải chuyển đổi lĩnh vực nhận dạng các chuỗi trong UnitOfWork. Điều này là bắt buộc để có EntityManager có thể theo dõi các thay đổi đối với đối tượng của bạn.

Vì đối tượng thuộc loại DateTime không thực hiện phương pháp tự nhiên __toString, chuyển đổi chúng thành chuỗi không đơn giản như truyền chúng thành chuỗi.

Do đó, mặc định date, datetimetime loại are not supported as part of the identifier.

Để giải quyết vấn đề này, bạn nên xác định custom field typemydatetime được ánh xạ tới lớp MyDateTime của riêng bạn thực hiện __toString. Bằng cách đó, ORM cũng có thể xử lý các mã định danh nếu chúng chứa các đối tượng.

Dưới đây là một ví dụ về cách lớp có thể trông giống như:

class MyDateTime extends \DateTime 
{ 
    public function __toString() 
    { 
     return $this->format('U'); 
    } 
} 

Và đây là một ví dụ về cách các kiểu tùy chỉnh DBAL sẽ trông như thế:

use Doctrine\DBAL\Types\DateTimeType; 
use Doctrine\DBAL\Platforms\AbstractPlatform; 

class MyDateTimeType extends DateTimeType 
{ 
    public function convertToPHPValue($value, AbstractPlatform $platform) 
    { 
     $dateTime = parent::convertToPHPValue($value, $platform); 

     if (! $dateTime) { 
      return $dateTime; 
     } 

     return new MyDateTime('@' . $dateTime->format('U')); 
    } 

    public function getName() 
    { 
     return 'mydatetime'; 
    } 
} 

Sau đó, bạn đăng ký nó với ORM của bạn cấu hình trong khi khởi động (phụ thuộc vào khung bạn đang sử dụng). Trong symfony, nó được ghi lại trên symfony doctrine documentation.

Sau đó, bạn có thể sử dụng nó trong các tổ chức của bạn:

class corpWalletJournal 
{ 
    // ... 

    /** 
    * @ORM\Column(name="date", type="mydatetime", nullable=false)  
    * @ORM\Id 
    * @ORM\GeneratedValue(strategy="NONE") 
    */ 
    private $date; 
+0

bạn có thể giải thích, ở đâu và như thế nào tôi cần thay đổi lớp DateTime? và cách sử dụng nó trên ví dụ của tôi – user1954544

+0

Bạn chỉ cần mở rộng lớp 'DateTime' với lớp' của riêng bạn MyDateTime extends \ DateTime {public function __toString() {return $ this-> format ('U'); }} '. Tôi đã cập nhật câu trả lời. Phần còn lại nằm trong tài liệu được liên kết (liên kết đến các loại trường tùy chỉnh: http://docs.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/types.html#custom-mapping-types) – Ocramius

+0

i đã thêm mã \ classes vào bài đăng hàng đầu, bạn có thể giải thích cách tôi có thể sử dụng chúng không? – user1954544

0

Hãy cẩn thận với

return new DateTimeEx('@' . $dateTime->format('U')); 

Các múi giờ sẽ không được tốt. Bạn nên làm:

$val = new DateTimeEx('@' . $dateTime->format('U')); 
$val->setTimezone($dateTime->getTimezone()); 

return $val;