I have a very strange error in my Symfony app and I don't know how to fix it. I want to set a DateTime in one of my entities with a DateTime after adding a special DateInterval. Here is my code:
$dateInterval = new \DateInterval('P1DT6H');
$snoozedTo = date_add($sickNote->getSickTo(), $dateInterval);
$channelUser->setSnoozedTo($snoozedTo);
$this->em->persist($channelUser);
In my UnitTests I get the following error:
date_add() expects parameter 1 to be DateTime, boolean given
So I double check if $sickNote->getSickTo() really returns a DateTime. A dump() returns:
DateTime {#17791
+"date": "2018-01-01 06:00:00.000000"
+"timezone_type": 3
+"timezone": "UTC"
}
get_class() on the object returns DateTime.
Here is additional my getter method for the field:
/**
* Get sickTo
* #return Date
*/
public function getSickTo() {
return $this->sickTo;
}
Why date_add gets a Boolean and not the DateTime object?
Edit: I also tried the objet method DateTime::add(). Same result.
Edit²: Here is my declaration of sickTo:
/**
* #var datetime $sickTo
* #ORM\Column(type="date", nullable=true)
* #Assert\Date()
*/
protected $sickTo;
The declaration of sickTo is wrong. you declare it as a Date but you use a Datetime. Try to change that with something like that :
/**
* #var \DateTime $sickTo
* #ORM\Column(type="datetime", nullable=true)
* #Assert\DateTime()
*/
protected $sickTo;
Related
I’m trying to persist an entity with doctrine, the entity has a date attribute and this, apparently, is generating the error.
This is how the attribute is declared in the entity:
/**
* #var date
*
* #ORM\Column(name="fecha", type="date")
* #ORM\Id
*/
private $fecha;
And this is how I create the Entity at controller and the code to persist it with doctrine:
$estadistica = new EstadisticaTerceros();
$fecha = date_create_from_format('Y-m-d', '2017-05-04');
$estadistica->setFecha($fecha);
//Set other attributes
$em = $this->getDoctrine()->getManager();
$em->persist($estadistica);
$em = $this->getDoctrine()->getManager();
$em->flush();
In the table the attribute is date type.
And this is the error screen:
Any idea?
I am assuming that your fecha column is not the primary key of the table. So you can drop the #ORM\Id annotation from that column:
/**
* #var \DateTime
*
* #ORM\Column(name="fecha", type="date")
*/
private $fecha;
date_create_from_format is also an alias for DateTime::createFromFormat and I'd recommend using that just so it's a little more explicit that you are creating a \DateTime:
$fecha = \DateTime::createFromFormat('Y-m-d', '2017-05-04');
If $estadistica->setFecha is expecting a string, just pass it the ISO 8601 date string '2017-05-04' directly instead of converting it to a DateTime instance.
Here you have answer for similiar question:
doctrine DateTime could not be converted to string
You should pass the string into Your entity. With DateTime class instance You could do it as follows:
$estadistica->setFecha($fecha->format('Y-m-d'));
I am trying to set time property of type Time to Doctrine entity Availability
class Availability{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\Column(name="start_time", type="time", nullable=true)
* #Assert\Time(message = "wrong time format")
*/
private $startTime;
/**
* #ORM\Column(name="end_time", type="time", nullable=true)
* #Assert\Time(message = "wrong time format")
*/
private $endTime;
}
In controller I am setting time by creating Time object:
use Symfony\Component\Validator\Constraints\Time;
/////
$availability = new Availability();
$availability->setStartTime(new Time('18:00:00'));
$availability->setEndTime(new Time('21:00:00'));
I have this error
No default option is configured for constraint
Symfony\Component\Validator\Constraints\Time (500 Internal Server
Error)
The 'auto-adding' you mentionned in comments is sometimes misleading and put you in bad situations specially when you are just starting to learn something.
startTime and endTime are of type time , Doctrine defines the time field as follows :
time: Type that maps a SQL TIME to a PHP DateTime object.
So you need to pass a DateTime object to your setters and not a Time constraint.
Something like this may work for you :
$availability = new Availability();
$availability->setStartTime(new \DateTime('now'));
$availability->setEndTime(new \DateTime('another date')); // <- change another date
I have a field in database (Time) with this value 09:00:00.
I created the Entity and with Time Field
/**
* #var \DateTime
*
* #ORM\Column(name="m_01_ch", type="time")
*/
private $m_01_ch;
In my controller I retrieve the element and when I do:
$val = $myentity->getM01Ch();
My value is (in XDebug)
$val = {DateTime}[3]
date= "2015-07-08 09:00:00.000000"
timezone_type = 3
timezone "Europe/Rome"
If I get $val->date I have All the Date, but I want to get only 09:00:00
Can I take my "original" value without use Regex etc?
You can modify your entity where you are returning your value. In your function getM01Ch() do something like this
/**
* #return \DateTime
*/
public function getM01Ch()
{
$returnValue = $this->m_01_ch->format('h:i:s')
return $returnValue
}
Other than that I don't know if any better approach exists. More info
I created a Doctrine2 Entity and would like to map a field to timestamp column in MySQL.
/**
* #ORM\Table(name="biz_order")
* #ORM\Entity(repositoryClass="Acme\OrderBundle\Repository\OrderRepository")
*/
class Order
{
/**
* #ORM\Column(name="order_id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
// Lots of other fields ...
/**
* #ORM\Column(name="order_timestamp", type="datetime")
*/
private $createdOn;
}
With annotated type as "datetime" I get following error:
Doctrine\DBAL\Types\ConversionException: Could not convert database value "1390362851" to Doctrine Type datetime. Expected format: Y-m-d H:i:s
at n/a
in /var/www/packer/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/ConversionException.php line 63
at Doctrine\DBAL\Types\ConversionException::conversionFailedFormat('1390362851', 'datetime', 'Y-m-d H:i:s')
in /var/www/packer/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/DateTimeType.php line 67
However in Doctrine 2.4 documentation I found following
datetime: Type that maps a SQL DATETIME/TIMESTAMP to a PHP DateTime object.
How can I map timestamp DB column to a PHP class field in Doctrine2?
EDIT:
So far my workaround is using the type="integer" in ORM mapping and returning it as ValueObject
public function getCreatedOn()
{
$createdOn = new \DateTime();
$createdOn->setTimestamp($this->createdOn);
return $createdOn;
}
You can just create a custom doctrine type defined timestamp, see the documentation
You can look at This post: datetime vs timestamp
Since it is a createdAt property, and represents a point in time, you might want to fetch objects that have been created before $createdAt or after $createdAt.
To do that, your best option is to store the datetime exactly the way you've done it but to associate a \Datetime object to that field: $this->createdAt = new \Datetime();
The best way for you would be to use lifecycle callbacks:
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Table(name="biz_order")
* #ORM\Entity(repositoryClass="Acme\OrderBundle\Repository\OrderRepository")
* #ORM\HasLifecycleCallbacks
*/
class Order
{
/**
* #ORM\Column(name="order_timestamp", type="datetime")
*/
private $createdAt;
/**
* #ORM\PrePersist
*/
public function doStuffOnPrePersist()
{
$this->createdAt= new \DateTime();
}
}
As I was working on my Symfony2 project a strange bug savagely appeared (again).
I created an entity Check containing a dateCreated attribute and some others attributes so I can link Check to different entities that are extending a ProductBase. Here are samples of Check and a AProduct :
/**
* Check
*
* #ORM\Table(name="check")
* #ORM\Entity
*/
class Check
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var \DateTime
*
* #ORM\Column(name="date_created", type="datetime")
*/
private $dateCreated;
[...]
/**
* #ORM\ManyToOne(targetEntity="Acme\BlogBundle\Entity\AProduct", inversedBy="checks")
* #ORM\JoinColumn(name="aproduct_id", referencedColumnName="id", onDelete="CASCADE")
*/
protected $aproduct;
[...]
}
/**
* AProduct
*
* #ORM\Table(name="aproduct")
* #ORM\Entity
*/
class AProduct extends ProductBase
{
[...]
/**
* #ORM\OneToMany(targetEntity="Acme\BlogBundle\Entity\Check", mappedBy="product")
* #ORM\OrderBy({"dateCreated" = "DESC"})
*/
protected $checks;
[...]
}
So my problem is that when I am trying to display the dateCreated attribute in one of my controller, see code below, Symfony2 (or Doctrine2) is adding exactly one month to the date stored in the database and I don't know why it's happening :
[...]
$aproduct = $aproducts[0];
$checks = $aproduct->getChecks();
$lastCheck = $checks->toArray()[0]; //I know it's not 'safe' but it's shorter to expose my problem
var_dump($lastCheck->getDateCreated());
Result :
object(DateTime)[854]
public 'date' => string '2014-01-20 16:21:41' (length=19)
public 'timezone_type' => int 3
public 'timezone' => string 'UTC' (length=3)
Value stored in database :
2013-12-20 16:21:41
What I don't understand the most is that in another controller, with the exact same methods but on a different product (BProduct for instance), I get the correct date...
Has anyone already faced to this problem or have any clue of what to do to solve it?
Thank you again. If you need more information just ask and I will try to help as most as I can.
Edit : The others aproduct stored in aproducts are displaying the correct date...
I see you are using:
#ORM\OrderBy({"dateCreated" = "DESC"})
Might be silly but check the id of returned Check instance.
Well I finally found my problem and my post here was really silly and completely unrelated to Symfony or Doctrine, sorry about that.
I was performing some "tests" on the last instance of my aproduct checks before displaying them and those "tests" were affecting the dateCreated value.
Here is what I was doing :
public static function updateAProductStatus(AProduct $product){
if(($check = $product->getChecks()->first()) instanceof Check){
$date = $check->getDateCreated();
$expiracyDate = $date->add(new \DateInterval('P1M')); //this line is the problem
$status = self::getStatus($expiracyDate); //this is only returning 'expired', 'expiring' or 'good' based on the difference between today's date and dateCreated + 1 month
} else {
$status = 'expired';
}
return $status;
}
So, as written in the code, $date->add(new \DateInterval('P1M')); is changing the stored value of Checks's dateCreated attribute. I don't understand exactly why it's affecting it because I'm not working directly on the Check instance.
The quick way to solve it was to explicitly clone the DateTime instance before adding a DateInterval :
$date = clone $date;
But I will add a new field in my Check or AProduct entity to store the expiracy date instead of calculating it on every update.
Update:
I read that PHP passes objects and arrays as reference and not as value. That's why I was having a problem here. I didn't know PHP was acting like that. I will be more careful in the future then!