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
Related
Below a portion of code stored into a file named
Website.php
<?php
namespace AdamInChains;
class Website
{
/**
* 02.14.2019 13:24:59 creation date
* 02.14.2019 13:28:23 last modified date
* #param array $meta_tags
*
* #return string
*/
public function index(array $meta_tags) : string{}
/**
* 02.14.2019 13:45:59 creation date
* 02.14.2019 13:49:21 last modified date
* #param array $meta_tags
*
* #return string
*/
public function about(array $meta_tags) : string{}
/**
* 02.14.2019 14:01:52 creation date
* 02.14.2019 14:33:01 last modified date
* #param array $meta_tags
*
* #return string
*/
public function contact(array $meta_tags) : string{}
}
I need to extract creation date and last modified date
and then store the regex results into one array this way
$array = [
// method name
"index" => [
"creation_date"=>"02.14.2019 14:01:52",
"last_modified_date"=>"02.14.2019 13:28:23"
]
];
Basically when the user, in this case AdamInChains and you can see this from the namespace declaration, creates a new page on his Website, one new method, declared as the input page name, is added to the class and the dates are added to the doc comment for the method.
until now I'm able to extract just the methods names (see code below), but no success with the other tasks.
// regex pattern
$re = '/public function.(\w{0,})/m';
// file 'Website.php'
$str = file_get_contents('Website.php');
preg_match_all($re, $str, $matches);
// Print the entire match result
var_dump($matches);
This is the var_dump results and I'm happy with it
Anyone?
Here is a regex you can use for that:
(?<creationDate>\d{2}\.\d{2}\.\d{4}\s\d{2}:\d{2}:\d{2})\screation\sdate[^\Z]*?(?<modifiedDate>\d{2}\.\d{2}\.\d{4}\s\d{2}:\d{2}:\d{2})\slast\smodified\sdate[^\Z]*?public\sfunction\s(?<methodName>[^\(\s]+)
https://regex101.com/r/7wrrhj/1
I've got this entity which represents the hire-period of a object. On the current overview page i display all objects which can be hired at this moment. Each products has many ObjectProductPeriods
class ObjectProductPeriod
{
/**
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(type="date")
*/
private $datumUit;
/**
* #ORM\Column(type="date")
*/
private $datumTerug;
/**
* #ORM\ManyToOne(targetEntity="App\Entity\ObjectProduct", inversedBy="orderPeriods")
*/
private $objectProduct;
/**
* #ORM\OneToOne(targetEntity="App\Entity\KlantOrder", inversedBy="objectPeriod")
*/
private $klantOrder;
}
I'm retrieving the availible objects in the ObjectProductPeriodRepository:
public function getAvailibleObjects(){
$currentDate = new \DateTime('now');
$query = $this->createQueryBuilder('qb')
->where(':current NOT BETWEEN qb.datumUit AND qb.datumTerug')
->setParameter('current', $currentDate)
->getQuery();
$result =$query->execute();
$objects = array();
foreach ($result as $key => $period){
$objects[] = $period->getObjectProduct();
}
return $objects;
}
The only issue is, that when a object has multiple periods. When the current date isn't between the start date and end end date it gets added to the objects displayed on the page. But if there's a period that's below both start and end period of that object, the whole object get's between other available objects (while it shouldn't be listed there). The overview should display objects where the current date isn't between the start and end date of any period for that particular object. So if there would be 2 Periods, one where the current date is between the first period and the second period the current date isn't between the period, in this scenario none of the objects should get displayed.
How can i use query builder to filter objects in this particular scenario?
Thanks in advance!
I believe you have to do something like this:
$qb = $this->createQueryBuilder('qb');
$qb->where('qb.datumUit > :current')
->andWhere('qb.datumTerug < :current')
->setParameter('current', currentDate)
my appointment model has a value $created which is of the datatype DateTime. But for some reason i am not able to set the $created values.
I tried many formats, but it just won't set the value. It gets stuck when the function reaches the setCreated(). (All other values (ints, strings) are set successfully, just this \DateTime var not)
$appointment->setCreated('1439878630'); //Doesn't work
$appointment->setCreated(1439878630); //Doesn't work
$appointment->setCreated('1990-11-14T15:32:12+00:00'); //Doesn't work
$appointment->setCreated('1990-11-14 15:32:12'); //Doesn't work
my setter method:
/**
* Sets the created
*
* #param \DateTime $created
* #return void
*/
public function setCreated(\DateTime $created) {
$this->created = $created;
}
how can i set the $created value with a timestamp (or any other date-format)??
any help is appreciated!
tia for your efforts.
The setCreated-method needs a DateTime object, not a string. So give it one:
$appointment->setCreated(new \DateTime('<insert your date string here>'));
The list of accepted time strings can be found in the PHP documentation.
Can you try this? It should be working...
$appointment->setCreated(new \DateTime('1990-11-14T15:32:12+00:00'));
Have you tried:
$appointment->setCreated('1990-11-14 15:32:12');
I'm doing a project in Symfony 2.3 with Doctrine 2.4 using MySQL database.
I have an Entity of FieldValue (simplified):
class FieldValue
{
/**
* The ID
*
* #var integer
*/
protected $fieldValueId;
/**
* Id of associated Field entity
*
* #var integer
*/
protected $fieldId;
/**
* Id of associated user
*
* #var integer
*/
protected $userId;
/**
* The value for the Field that user provided
*
* #var string
*/
protected $userValue;
/**
* #var \MyProjectBundle\Entity\Field
*/
protected $field;
/**
* #var \MyProjectBundle\Entity\User
*/
protected $user;
The problem I have is the fact that $userValue, while it's LONGTEXT in my database, can represent either actual text value , date or number, depending in the type of the Field.
The Field can be dynamically added. After adding a one to any of the users every other user can also fill it's own value for that Field.
While querying the database I use orderBy to sort on a certain column, which also can be one of those Fields. In that case I need to sort on $userValue. This is problematic when I need to have number fields sorted as numbers, and not as strings ('123' is less than '9' in that case...).
The solution for it (I thought) is to CAST the $sort, so I would get SQL like:
ORDER BY CAST(age AS SIGNED INTEGER) ASC
Since Doctrine does not have a built-in DQL function for that, I took the liberty of adding that to my project as INT DQL function (thanks to Jasper N. Brouwer):
class CastAsInteger extends FunctionNode
{
public $stringPrimary;
public function getSql(SqlWalker $sqlWalker)
{
return 'CAST(' . $this->stringPrimary->dispatch($sqlWalker) . ' AS SIGNED INTEGER)';
}
public function parse(Parser $parser)
{
$parser->match(Lexer::T_IDENTIFIER);
$parser->match(Lexer::T_OPEN_PARENTHESIS);
$this->stringPrimary = $parser->StringPrimary();
$parser->match(Lexer::T_CLOSE_PARENTHESIS);
}
}
So happy with myself finding an easy solution I did that:
$sort = "INT(".$sort.")";
$queryBuilder->orderBy($sort, $dir);
which produced expected DQL:
ORDER BY INT(age) ASC
But also produced an exception:
An exception has been thrown during the rendering of a template ("[Syntax Error] line 0, col 12272: Error: Expected end of string, got '('") in MyProject...
So I've tried to find out what is going on and got into this in Doctrine\ORM\Query\Parser.php:
/**
* OrderByItem ::= (
* SimpleArithmeticExpression | SingleValuedPathExpression |
* ScalarExpression | ResultVariable
* ) ["ASC" | "DESC"]
*
* #return \Doctrine\ORM\Query\AST\OrderByItem
*/
public function OrderByItem()
{
...
}
Does that mean that there is no possibility to use DQL functions inside ORDER BY?
And if this is the case - is there any other way to achieve this?
UPDATE
I actually already have INT used in my select query, inside CASE WHEN:
if ($field->getFieldType() == 'number') {
$valueThen = "INT(".$valueThen.")";
}
$newFieldAlias = array("
(CASE
WHEN ...
THEN ".$valueThen."
ELSE ...
END
) as ".$field->getFieldKey());
Later on the $newFieldAlias is being added to the query.
Doesn't change anything...
UPDATE 2
Even when I add an extra select to the query, which will result in this DQL:
SELECT age, INT(age) as int_age
and then sort like that:
ORDER BY int_age ASC
I still don't het the correct result.
I've checked var_dump from $query->getResult(), and this is what I got:
'age' => string '57' (length=2)
'int_age' => string '57' (length=2)
Like CAST does not matter. I'm clueless...
Doctrine DQL does not accept functions as sort criteria but it does accept a "result variable". It means that you can do the following:
$q = $this->createQueryBuilder('e')
->addSelect('INT(age) as HIDDEN int_age')
->orderBy('int_age');
Doctrine 2 does not support INT by default, but you can use age+0.
$q = $this->createQueryBuilder('e')
->addSelect('age+0 as HIDDEN int_age')
->orderBy('int_age');
It is problem in your parser.php file. I have similar kind of issue and I solve this issue to replace below code in my parser file.
/**
* OrderByClause ::= "ORDER" "BY" OrderByItem {"," OrderByItem}*
*
* #return \Doctrine\ORM\Query\AST\OrderByClause
*/
public function OrderByClause()
{
$this->match(Lexer::T_ORDER);
$this->match(Lexer::T_BY);
$orderByItems = array();
$orderByItems[] = $this->OrderByItem();
while ($this->lexer->isNextToken(Lexer::T_COMMA)) {
$this->match(Lexer::T_COMMA);
$orderByItems[] = $this->OrderByItem();
}
return new AST\OrderByClause($orderByItems);
}
Just use this:
->orderBy('u.age + 0', 'ASC');
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!