is it possible to add a restriction via Doctrine annotation to force a number attribute to be always equal or greater than 0?
Thank you
Either change the datatype to unsigned using the following annotation:
#ORM\Column(type="integer", options={"unsigned":true})
That will alter the type to unsigned (zero and up). I'm not sure it is supported on all DBAL platforms but I'm sure MySQL supports it.
Or, if you use Symfony Validator Component:
// src/Acme/SocialBundle/Entity/Person.php
namespace Acme\SocialBundle\Entity;
use Symfony\Component\Validator\Constraints as Assert;
class Person
{
/**
* #Assert\GreaterThanOrEqual(
* value = 18
* )
*/
protected $age;
}
The above example forces the age property to be 18 or higher.
Related
I have some timestamp records on the DB that have trailing milliseconds at the timestamp and some not have. How to allowing that trailing data (millisecond) in carbon? Is this possible?
Here's the sample of my data
I can't always change the data manually because there are some other services using the same database and sometimes storing timestamp with trailing milliseconds.
As you are using Postgres, your timestamp probably has TIME WITH TIMEZONE
Example: "2018-04-19 07:01:19.929554".
In Such case have to add a date Mutator to your Model.
In your Model add this field for date mutator:
protected $dateFormat = 'Y-m-d H:i:sO';
Alternate Solution:
As you have a mix of timestamps with and without milliseconds I suggest you try this solution using Laravel field mutators:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* Parse the created at field which can optionally have a millisecond data.
*
* #param string $created_at
* #return Carbon::Object
*/
public function getCreatedAtAttribute($created_at)
{
// Try to remove substring after last dot(.), removes milliseconds
$temp = explode('.', $created_at);
// If created_at had milliseconds the array count would be 2
if(count($temp) == 2) {
unset($temp[count($temp) - 1]); // remove the millisecond part
} else {
$temp = [$created_at]; // created_at didnt have milliseconds set it back to original
}
return Carbon::parse(implode('.', $temp))->format('Y-m-d H:i:s')
}
}
I have observed in Laravel, storing datetime in database ignores
millisecond field, probably depends on version and db server type.
Also Laravel has whereData() and whereTime() query builders but we
need something like whereDateTimeTz() in all cases.
I recommend storing datetime as unix timestamps in database.
From user timezone convert to GMT and save it to db as millis-timestamp
Carbon::parse('date', 'user_timezone')->setTimezone('GMT')->getPreciseTimestamp(3);
While displaying just convert the db timestamp (GMT) back to user timezone including DST status.
Laravel 7 provides better date parsing by falling back to Carbon::parse if the recevied timestamp from the database doesn't match the expected $dateFormat.
PR: https://github.com/laravel/framework/pull/30628
I'm using Spring Boot version 1.5.13.
I can set the upper limit on concurrent sessions using the below code snippet in a configuration class -
http.sessionManagement().maximumSession($max_sesssions)
However, I want to know the default value of this limit.
The default is to allow any number of users. I navigated through the source code and found out the value is set to -1 for allowing any number of users by default.
Below is the snippet from ConcurrentSessionControlAuthenticationStrategy class -
/**
* Sets the <tt>maxSessions</tt> property. The default value is 1. Use -1 for
* unlimited sessions.
*
* #param maximumSessions the maximimum number of permitted sessions a user can have
* open simultaneously.
*/
public void setMaximumSessions(int maximumSessions) {
Assert.isTrue(
maximumSessions != 0,
"MaximumLogins must be either -1 to allow unlimited logins, or a positive integer to specify a maximum");
this.maximumSessions = maximumSessions;
}
According to Documentation, the default is to allow any number of
users.
.sessionManagement().maximumSessions(maximumSessions);
you can see the below details by Ctrl + Click on maximumSessions for eclips on windows.
SessionManagementConfigurer.java
/**
* Controls the maximum number of sessions for a user. The default is to allow any
* number of users.
* #param maximumSessions the maximum number of sessions for a user
* #return the {#link SessionManagementConfigurer} for further customizations
*/
public ConcurrencyControlConfigurer maximumSessions(int maximumSessions) {
this.maximumSessions = maximumSessions;
return new ConcurrencyControlConfigurer();
}
I've got a Symfony entity, which has a OneToMany mapping with an OrderBy clause like this:
/**
* #ORM\OneToMany(targetEntity="App\Entity\News", mappedBy="category", orphanRemoval=true)
* #ORM\OrderBy({"id" = "DESC"})
*/
private $news;
Assuming I would like to only display n entries in Twig, I would have the options to either loop over it and ignoring every thing after loop.index n or rather use slice. However these options do have the downside, that if there are a lot of news entries, all of them will be loaded, which isn't very efficient.
Another option would be to use a Criteria in the controller or the entity to limit the amount of loaded entities. If I understood it here correctly, it should modify the doctrine query directly and thus not have any performance impact. Is this the best practice, or would it be better to have a custom query builder in the controller or a function in the repository?
Actually you can set $news relationship as EXTRA_LAZY and use $news->slice() function without triggering a full load as stated in official documentation:
If you mark an association as extra lazy the following methods on
collections can be called without triggering a full load of the
collection:
Collection#contains($entity)
Collection#containsKey($key) (available with Doctrine 2.5)
Collection#count()
Collection#get($key) (available with Doctrine 2.4)
Collection#slice($offset, $length = null)
Therefore your declaration should look like the following:
/**
* #ORM\OneToMany(targetEntity="App\Entity\News", mappedBy="category", orphanRemoval=true, fetch="EXTRA_LAZY")
* #ORM\OrderBy({"id" = "DESC"})
*/
private $news;
I'm running an online food journal where users can record journal entries. There are four types of entries: food entries, exercise entries, measurements, and completed tasks. Entries have several attributes in common (e.g., id, amount, unit_id, etc), but they also have type-specific attributes (e.g., food_id, exercise_id, etc). That's a perfect candidate for a super- and sub-type relationship.
Here are my tables (simplified):
CREATE TABLE entries
`id` int
`user_id` int
`created` datetime
`entered` datetime
`amount` float
`unit_id` int
PRIMARY KEY id
CREATE TABLE exercise_entries
`entry_id` int
`exercise_id` int
PRIMARY KEY entry_id
CREATE TABLE food_entries
`entry_id` int
`food_id` int
PRIMARY KEY entry_id
So my question is, how do I setup super- and sub-type relationships using CodeIgniter's DataMapper ORM? I've looked at the User Guide's Relationships and Advanced Relationships sections, but I can't find anything.
If it's not possible with DataMapper, I can think of a few solutions:
Roll sub-type attributes up (1 big table, ugh)
Roll super-type attributes down (4 separate tables, ugh)
Go nuclear and use Doctrine 2.0 ORM (YAML config files, ugh!)
Use a different framework whose native ORM supports table inheritance (I shortlisted Kohana and FuelPHP with CodeIgniter).
Manually code super- and sub-type relationships (defeats purpose of ORM in the first place).
I'm not thrilled with any of my options. Option 1 and 2 create their own headaches (see the bottom of this article). Option 3 seems like surgery with a sledgehammer. I'm open to Option 4 because I haven't started writing any framework code (it was a really tough choice between CI and Kohana). Option 5 is where I am now.
Any suggestions? Thanks for the help!
I haven't tried this with DataMapper, but you might try (making sure to call the parent constructor and all that). I would assume that Exerciseentry would inherit all of the properties/methods from Entry - but not sure if DataMapper would handle it this way:
class Entry extends DataMapper {
}
// you may have to explicitly include Entry.php in this file:
class Exerciseentry extends Entry {
}
If that doesn't work, you can basically create two objects that are related ( not really pure OOP principle, but would get the job done ):
class Entry extends DataMapper {
// ... some stuff
var $has_many = array('exerciseentry', 'foodentry');
// ... some more stuff
}
class Exerciseentry extends DataMapper {
// ... some stuff
var $has_one = array('entry');
// ... some more stuff
}
class Foodentry extends DataMapper {
// ... some stuff
var $has_one = array('entry');
// ... some more stuff
}
// then when you get an entry, you'd do this
$my_exercise_entry = new Exerciseentry(1);
$my_exercise_entry->include_related('entry', array('user_id', 'amount', 'unit_id');
$my_exercise_entry->get();
echo 'Amount is: ' . $my_exercise_entry->entry_amount;
// etc
Typically i create my entities in symfony2/doctrine from this console commands :
$php app/console doctrine:mapping:import TestSiteBundle yml
$php app/console doctrine:generate:entities Test --path=src/
but my table columns have prefixes like this :
table: user
id_user
id_address (FK)
nm_name
dt_created
bl_active
and it generates entities like this :
$idUser
$idAdress
$nmName
$dtCreated
$blActive
how can i ignore my column prefixes ? do i need to change my entire database column names ?
I think you can add the name like this:
Doctrine\Tests\ORM\Mapping\User:
fields:
created:
name: dt_created
type: datetime
you can see:
http://www.doctrine-project.org/docs/orm/2.1/en/reference/yaml-mapping.html
https://github.com/doctrine/doctrine2/blob/master/lib/Doctrine/ORM/Mapping/Driver/YamlDriver.php
Just so I understand, you want your database column name to be id_user and you want the entity property to be $user? If so, I don't think that's possible without doing some serious hacking of the core libraries. Basically you'd need to intercept the part that generates the entity properties and add your own rules on how to name them. You'd be much better off renaming your columns. IMHO, those prefixes are unnecessary. I would change id_user to user_id, nm_name to name, dt_created to created_at, and bl_active to is_active. Your column names and property names will not only match (this is a good thing) but they'll make more sense.
Hope this helps.
You can patch Doctrine to strip prefixes upon reverse engineering of your database.
Open this file in IDE: https://github.com/doctrine/doctrine2/blob/master/lib/Doctrine/ORM/Mapping/Driver/DatabaseDriver.php
Add method to class DatabaseDriver implements Driver :
private function deprefixFieldName( $fieldName ) {
return implode('_',array_slice(explode('_',$fieldName),1));
}
Edit method:
public function setFieldNameForColumn($tableName, $columnName, $fieldName)
{
/* ADD */ $fieldName = $this->deprefixFieldName($fieldName);
$this->fieldNamesForColumns[$tableName][$columnName] = $fieldName;
}
Edit method:
private function getFieldNameForColumn($tableName, $columnName, $fk = false)
{
/* ... */
/* ADD */ $columnName = $this->deprefixFieldName($columnName);
return Inflector::camelize($columnName);
}
My method is so simple because my prefixes are all consistent ( i took the idea from Media Wiki ), yours may be more complex.
Here's the actual patch taken by Git from working system, just in case i made a typo in description: http://pastebin.com/FHeTCUjZ ( i wonder if patches in posts are allowed).