I am using Symfony2 for my application and I am using two Entity Managers; one is for read and other is for write.
I am creating entity manager object like that:
$em = $this->getDoctrine()->getEntityManager('write');
$em = $this->getDoctrine()->getEntityManager('read');
Initially it was working fine but now the following error is coming:
A new entity was found through the relationship 'AppBundle\Entity\ProfileViewer#viewer' that was not configured to cascade persist operations for entity: shamsi. Explicitly persist the new entity or configure cascading persist operations on the relationship.
Here is my ProfileViewer Entity:
/**
* AppBundle\Entity\ProfileViewer
*
* #ORM\Table(name="profile_viewer")
* #ORM\Entity
*/
class ProfileViewer
{
/**
* #var bigint $id
*
* #ORM\Column(name="id", type="bigint", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* #var bigint $userId
*
* #ORM\Column(name="user_id", type="bigint", nullable=false)
*/
private $userId;
/**
* #var datetime $viewedAt
*
* #ORM\Column(name="viewed_at", type="datetime", nullable=true)
*/
private $viewedAt;
/**
* #ORM\ManyToOne(targetEntity="user", inversedBy="viewers")
* #ORM\JoinColumn(name="viewer_id", referencedColumnName="id")
*/
private $viewer;
public function __construct()
{
$this->viewedAt = new \DateTime();
}
/**
* Get id
*
* #return bigint
*/
public function getId()
{
return $this->id;
}
/**
* Set userId
*
* #param bigint $userId
*/
public function setUserId($userId)
{
$this->userId = $userId;
}
/**
* Get UserId
*
* #return bigint
*/
public function getUserId()
{
return $this->userId;
}
/**
* Set viewedAt
*
* #param datetime $viewedAt
*/
public function setViewedAt($viewedAt)
{
$this->viewedAt = $viewedAt;
}
/**
* Get viewedAt
*
* #return datetime
*/
public function getViewedAt()
{
return $this->viewedAt;
}
/**
* Set viewer
*
* #param AppBundle\Entity\User $viewer
*/
public function setViewer(AppBundle\Entity\User $viewer)
{
$this->viewer = $viewer;
}
/**
* Get viewer
*
* #return AppBundle\Entity\User
*/
public function getViewer()
{
return $this->viewer;
}
}
This error comes when I have created two entity managers.
By default, no operations are cascaded in Doctrine2.
You can add cascade={"persist"} to your association:
/**
* #ORM\ManyToOne(targetEntity="user", inversedBy="viewers", cascade={"persist"})
* #ORM\JoinColumn(name="viewer_id", referencedColumnName="id")
*/
You can read this to understand cascade operations on associations in doctrine. This is important to underline:
Cascade operations are performed in memory. That means collections and
related entities are fetched into memory, even if they are still
marked as lazy when the cascade operation is about to be performed.
However this approach allows entity lifecycle events to be performed
for each of these operations.
However, pulling objects graph into memory on cascade can cause
considerable performance overhead, especially when cascading
collections are large. Makes sure to weigh the benefits and downsides
of each cascade operation that you define.
Related
My entity class is:
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* #var \Doctrine\Common\Collections\Collection
*
* #ORM\ManyToMany(targetEntity="AppBundle\Entity\TipiVendita", inversedBy="idAgente")
* #ORM\JoinTable(name="tipi_vendita_agenti",
* joinColumns={
* #ORM\JoinColumn(name="id_agente", referencedColumnName="id")
* },
* inverseJoinColumns={
* #ORM\JoinColumn(name="id_tipo_vendita", referencedColumnName="id")
* }
* )
*/
private $idTipoVendita;
/**
* Constructor
*/
public function __construct()
{
$this->idTipoVendita = new \Doctrine\Common\Collections\ArrayCollection();
}
and when i use the command 'doctrine:generate:entities', methods that generates are wrongly named:
/**
* Add idTipoVendita
*
* #param \AppBundle\Entity\TipiVendita $idTipoVendita
* #return Agenti
*/
public function addIdTipoVenditum(\AppBundle\Entity\TipiVendita $idTipoVendita)
{
$this->idTipoVendita[] = $idTipoVendita;
return $this;
}
/**
* Remove idTipoVendita
*
* #param \AppBundle\Entity\TipiVendita $idTipoVendita
*/
public function removeIdTipoVenditum(\AppBundle\Entity\TipiVendita $idTipoVendita)
{
$this->idTipoVendita->removeElement($idTipoVendita);
}
/**
* Get idTipoVendita
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getIdTipoVendita()
{
return $this->idTipoVendita;
}
How can i have addIdTipoVentita instead of addIdTipoVenditum, removeIdTipoVendita instead of removeIdTipoVenditum?
Update
The issue is that doctrine don't generate properly my entity! It generates methods names with the doctrine inflector component and add these kind of suffixes. How can i configure it in the right way?
Riccardo, You should name your properties in English.
And you should be aware that you are in a Object world, you work with objects and not with object_ids.
So the Entity TipiVendita should be named something like SellType (english, singular).
While the `idTipoVendita' field, if I understand, should enforce an N-M relation with SellType and Agents, so it should be named something like sellTypes (english, plural because it is a collection).
To make a long story short idTipoVendita - beeing a field for a collection, is seen as a plural form and is singularized in idTipoVenditum (just like "Curricula" and "Curriculum").
Best regards.
I have a situation where I need to add columns to a many-to-many join table, so I'm trying to follow the recommended practice of having the join table represented by an entity with ManyToOne relationships with each of the other two entities.
In this case, we have a court interpreter management system where there's an entity called Event, another called Interpreter. The InterpreterAssignment entity is one-to-many with both of these, but it also needs two metadata columns: a created datetime, and the Application\Entity\User who created it (I leave out the latter for simplicity's sake).
So, this works just fine:
$interpreter = $entityManager->getRepository('Application\Entity\Interpreter')
->findOneBy(['lastname'=>'Mintz']);
$assignment = new Entity\InterpreterAssignment();
$assignment->setInterpreter($interpreter)->setEvent($event);
$event->addInterpretersAssigned($assignment);
$em->flush();
...and I don't even need to say persist() because of the cascade={"persist","remove"}) on Event#interpretersAssigned.
However, when I try to do the reverse, that is,
use the removeInterpretersAssigned() method that Doctrine wrote for me:
$event = $entityManager->find('Application\Entity\Event',103510);
$assignment = $event->getInterpretersAssigned()[0];
$event->removeInterpretersAssigned($assignment);
$em->flush();
the database is untouched; Doctrine does not delete the row in the join table.
I can work around by saying $entityManager->remove($assignment). But I can't help but think that $event->removeInterpretersAssigned($assignment) is supposed to work.
So, I must be missing something but I can't see what. The Doctrine cli tool says my mappings are OK. Here are the entities, in relevant part:
/* namespace declarations and use statements omitted */
class Event
{
/* other fields and methods omitted */
/**
* #ORM\OneToMany(targetEntity="InterpreterAssignment",mappedBy="event",cascade={"persist","remove"})
* #var InterpreterAssignment[]
*/
protected $interpretersAssigned;
/* the following created by the Doctrine cli tool */
/**
* Remove interpretersAssigned
*
* #param \Application\Entity\InterpreterAssignment $interpretersAssigned
*/
public function removeInterpretersAssigned(\Application\Entity\InterpreterAssignment $interpretersAssigned)
{
$this->interpretersAssigned->removeElement($interpretersAssigned);
}
/**
* Get interpretersAssigned
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getInterpretersAssigned()
{
return $this->interpretersAssigned;
}
}
class Interpreter
{
/**
* #ORM\OneToMany(targetEntity="InterpreterAssignment",mappedBy="interpreter")
* #var InterpreterAssignment[]
*/
protected $assignments;
/**
* Remove assignment
*
* #param \Application\Entity\InterpreterAssignment $assignment
*/
public function removeAssignment(\Application\Entity\InterpreterAssignment $assignment)
{
$this->assignments->removeElement($assignment);
}
/**
* Get assignments
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getAssignments()
{
return $this->assignments;
}
}
and here is the InterpreterAssignment
/**
* #ORM\Entity
* #ORM\Table(name="interp_events", uniqueConstraints={#ORM\UniqueConstraint(name="unique_deft_event",columns={"interp_id","event_id"})})
* #ORM\HasLifeCycleCallbacks
*/
class InterpreterAssignment
{
/**
* #ORM\Id
* #ORM\ManyToOne(targetEntity="Interpreter",inversedBy="assignments")
* #ORM\JoinColumn(name="interp_id", referencedColumnName="interp_id")
* #var Interpreter
*/
protected $interpreter;
/**
* #ORM\Id
* #ORM\ManyToOne(targetEntity="Event",inversedBy="interpretersAssigned")
* #ORM\JoinColumn(name="event_id", referencedColumnName="event_id")
* #var Event
*/
protected $event;
/**
* #ORM\Column(type="datetime",nullable=false)
* #var \DateTime
*/
protected $created;
/**
* #ORM\PrePersist
*/
public function onPrePersist()
{
$this->created = new \DateTime();
}
/**
* Set interpreter
*
* #param \Application\Entity\Interpreter $interpreter
*
* #return InterpreterAssignment
*/
public function setInterpreter(\Application\Entity\Interpreter $interpreter)
{
$this->interpreter = $interpreter;
return $this;
}
/**
* Get interpreter
*
* #return \Application\Entity\Interpreter
*/
public function getInterpreter()
{
return $this->interpreter;
}
/**
* Set event
*
* #param \Application\Entity\Event $event
*
* #return InterpreterAssignment
*/
public function setEvent(\Application\Entity\Event $event)
{
$this->event = $event;
return $this;
}
/**
* Get event
*
* #return \Application\Entity\Event
*/
public function getEvent()
{
return $this->event;
}
/* other stuff ommitted */
}
Many thanks.
I think you need to do 2 things:
(optional) You need to call $assignment->setEvent(null) after calling $event->removeInterpretersAssigned($assignment);
Also you may want to use Orphan Removal to remove the entity from the many to many table. and so the entity code should changed to (notice the addition of , orphanRemoval=true to the mapping code):
/**
* #ORM\OneToMany(targetEntity="InterpreterAssignment",mappedBy="event",cascade={"persist","remove"}, orphanRemoval=true)
* #var InterpreterAssignment[]
*/
protected $interpretersAssigned;
The documentation on how to retrieve joined entites as one object is very sparse, and most Stack Overflow questions on the subject are many years old.
I have a symfony project up and running with a database schema fully mapped in Doctrine. In my controllers I am able to run these two queries one after the other and they work fine.
$page = $this->getDoctrine()
->getRepository('PageBundle:SitePages')
->findByprodpageid($id);
$matrices = $this->getDoctrine()
->getRepository('PageBundle:SiteMatrices')
->findByprodpageid($id);
however both of them contain the attribute prodpageid and I would like to join the two entities on this column and receive one object containing all column values from both tables.
I am building this on top of an existing database structure so anything to do with changing the database structure etc is out of the question.
I have added annotations in my entities to specify which columns should be joined, in a ManyToOne relationship. But how do I activate that relation and receive the joined object?
Thanks for any info on the subject.
EDIT: Here are my relationships from the entities
//Entities/SitePages
/**
* #var integer
*
* #ORM\Column(name="ProdPageID", type="smallint")
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*
* #ORM\OneToMany(targetEntity="SiteMatrices")
* #ORM\JoinColumn(name="prodpageid", referencedColumnName="prodpageid")
*/
private $prodpageid;
//Entities/SiteMatrices
/**
* #var integer
*
* #ORM\Column(name="ProdPageID", type="smallint", nullable=false)
* #ORM\ManyToOne(targetEntity="SitePages")
* #ORM\JoinColumn(name="prodpageid", referencedColumnName="prodpageid")
*
*/
private $prodpageid;
You are saying that a Page has many Matrices. I will make some changes by your permission in mapping annotations:
/**
* Entities/SitePages
*
* #var integer
*
* #ORM\Column(name="ProdPageID", type="smallint")
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*
* #ORM\OneToMany(targetEntity="SiteMatrices")
* #ORM\JoinColumn(name="prodpageid", referencedColumnName="prodpageid")
*/
private $matrices;
/**
* #return ArrayCollection
*/
public function getMatrices(){
return $this->matrices;
}
/**
* #param Entities/SiteMatrices[]
* #return $this
*/
public function setMatrices($matrices){
$this->matrices = $matrices;
return $this;
}
and
/**
* Entities/SiteMatrices
*
* #var integer
*
* #ORM\Column(name="ProdPageID", type="smallint", nullable=false)
* #ORM\ManyToOne(targetEntity="SitePages")
* #ORM\JoinColumn(name="prodpageid", referencedColumnName="prodpageid")
*
*/
private $page;
/**
* #return Entities/SitePages
*/
public function getPage(){
return $this->page;
}
/**
* #param Entities/SitePages
* #return $this
*/
public function setPage($page){
$this->page = $page;
return $this;
}
Now if you query the Pages with this DQL:
$pages = $this->getDoctrine()
->getRepository('PageBundle:SitePages')
->findByprodpageid($id);
Then you could get each page's matrices simply by traversing on matrices association:
foreach($pages as $page){
$matrices = $page->getMatrices(); // will give you an ArrayCollection of all matrices objects joined by prodpageid to this page.
}
Hope I did not get you wrong and it helps.
Even if the object is correctly updated it seems that the data is not persisted and I don't get it why.
Here is my Entity:
Article.php
/**
* #var AttributeInArticle
*
* #ORM\OneToMany(
* targetEntity="XXX\DatabaseBundle\Entity\AttributeInArticle",
* mappedBy="article"
* )
*/
private $attributeInArticles;
....
public function __construct()
{
$this->attributeInArticles = new ArrayCollection();
}
/**
* #return AttributeInArticle
*/
public function getAttributeInArticles()
{
return $this->attributeInArticles;
}
public function addAttributeInArticle(AttributeInArticle $attributeInArticles)
{
$this->attributeInArticles[] = $attributeInArticles;
return $this;
}
public function removeAttributeInArticle(AttributeInArticle $attributeInArticles)
{
$this->attributeInArticles->removeElement($attributeInArticles);
}
AttributeInArticle.php
/**
* #var Attribute
*
* #ORM\ManyToOne(
* targetEntity="XXX\DatabaseBundle\Entity\Attribute",
* inversedBy="attributeInArticles"
* )
* #ORM\JoinColumns({
* #ORM\JoinColumn(
* name="attribute_id",
* referencedColumnName="id")
* })
*/
private $attribute;
/**
* #var Article
*
* #ORM\ManyToOne(
* targetEntity="XXX\DatabaseBundle\Entity\Article",
* inversedBy="attributeInArticles"
* )
* #ORM\JoinColumns({
* #ORM\JoinColumn(
* name="article_id",
* referencedColumnName="id"
* )
* })
*
*/
private $article;
/**
* #return Attribute
*/
public function getAttribute()
{
return $this->attribute;
}
/**
* #param Attribute $attribute
*/
public function setAttribute($attribute)
{
$this->attribute = $attribute;
}
+ getter & setter for $article
And in the controller I am calling it like this:
$article->removeAttributeInArticle($attributeInArticle);
If I dumpthe $article object before and after the remove action the $article object has the corect data in it. That means that $attributeInArticle was removed.
But for some reason it does not persist this data.
The answer is easy here.
You are removing an Attribute from an Article and the persisting/flushing Article. If you look to your mappings you'll notice easily that the relationship between Article and AttributeInArticole is owned by the latter.
When you do flushing operations, doctrine, for performance reasons, "looks" only to owning side of a relationship and for changes in it: if nothing changed there's no need to write it in db.
So, what you can do here, is to remove the $attributeInArticle directly without worry about Article entity.
So, basically
$em = $this
->getDoctrine()
->getManager();
$em->remove($attributeInArticle);
$em->flush();
Another option is to use orphanRemoval on $attribueInArticles of your Article entity.
So, basically,
//Article.php
/**
* #var AttributeInArticle
*
* #ORM\OneToMany(
* targetEntity="XXX\DatabaseBundle\Entity\AttributeInArticle",
* mappedBy="article",
* orphanRemoval=true
* )
*/
private $attributeInArticles;
and
$article->removeAttributeInArticle($attributeInArticle);
You need cascade={"remove"}
/**
* #var AttributeInArticle
*
* #ORM\OneToMany(
* targetEntity="XXX\DatabaseBundle\Entity\AttributeInArticle",
* mappedBy="article",
* cascade={"remove"}
* )
*/
Read doctrine documentation: 8. Working with Associations. Also check "Orphan Removal"
After I successfuly created TaskBundle with One-to-Many relation between category and tasks, now I'm trying to create a new TaskBundle with Many-to-Many relation. I get also problem with checking checkbox in this relation, but now it is not a primary problem (maybe after solving this). I deleted all tables, which is TaskBundle using and trying to create a new, but here is problem (description at the bottom).
My Task object:
<?php
namespace Acme\TaskBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
* #ORM\Entity
* #ORM\Table(name="tasks")
*/
class Task
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\Column(type="string", length=200)
* #Assert\NotBlank(
* message = "Task is empty"
* )
* #Assert\Length(
* min = "3",
* minMessage = "Task is too short"
* )
*/
protected $task;
/**
* #ORM\Column(type="datetime")
* #Assert\NotBlank()
* #Assert\Type("\DateTime")
*/
protected $dueDate;
/**
* #Assert\True(message = "You have to agree.")
*/
protected $accepted;
/**
* #ORM\ManyToMany(targetEntity="Category", inversedBy="tasks")
* #ORM\JoinTable(name="categories")
*/
protected $category;
/**
* Constructor
*/
public function __construct()
{
$this->category = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set task
*
* #param string $task
* #return Task
*/
public function setTask($task)
{
$this->task = $task;
return $this;
}
/**
* Get task
*
* #return string
*/
public function getTask()
{
return $this->task;
}
/**
* Set dueDate
*
* #param \DateTime $dueDate
* #return Task
*/
public function setDueDate($dueDate)
{
$this->dueDate = $dueDate;
return $this;
}
/**
* Get dueDate
*
* #return \DateTime
*/
public function getDueDate()
{
return $this->dueDate;
}
/**
* Add category
*
* #param \Acme\TaskBundle\Entity\Category $category
* #return Task
*/
public function addCategory(\Acme\TaskBundle\Entity\Category $category)
{
$this->category[] = $category;
return $this;
}
/**
* Remove category
*
* #param \Acme\TaskBundle\Entity\Category $category
*/
public function removeCategory(\Acme\TaskBundle\Entity\Category $category)
{
$this->category->removeElement($category);
}
/**
* Get category
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getCategory()
{
return $this->category;
}
}
and Category object
<?php
namespace Acme\TaskBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
* #ORM\Entity
* #ORM\Table(name="categories")
*/
class Category
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\Column(type="string", length=200, unique=true)
* #Assert\NotNull(message="Categories cannot be empty", groups = {"adding"})
*/
protected $name;
/**
* #ORM\ManyToMany(targetEntity="Task", mappedBy="category")
*/
private $tasks;
public function __toString()
{
return strval($this->name);
}
/**
* Constructor
*/
public function __construct()
{
$this->tasks = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* #param string $name
* #return Category
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* Add tasks
*
* #param \Acme\TaskBundle\Entity\Task $tasks
* #return Category
*/
public function addTask(\Acme\TaskBundle\Entity\Task $tasks)
{
$this->tasks[] = $tasks;
return $this;
}
/**
* Remove tasks
*
* #param \Acme\TaskBundle\Entity\Task $tasks
*/
public function removeTask(\Acme\TaskBundle\Entity\Task $tasks)
{
$this->tasks->removeElement($tasks);
}
/**
* Get tasks
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getTasks()
{
return $this->tasks;
}
}
So, after i put doctrine:schema:update --force i'll get error: Table 'symfony.categories' already exists. I've tried to delete all caches, but same problem. Any idea?
There's only problem, if it is as m2m relation.
PS: I was looking for this problem at the Google, but no one answers at this problem. There were only questions, but not correct answers, where the problem is and how to solve it.
Looks like you already have table named "categories" in that database. Remove this line #ORM\JoinTable(name="categories") and try without it.
P.S. "Categories" is really a strange name for join table. You should probably follow some conventions and let doctrine name it. Common names for join tables are category_task or category2task as they are more self-explanatory. Nothing that important, just trying to suggest what I consider good practice.
The thing is that doctrine doesn't understand how your existing table should be used. But you can give him some help.
You have two options :
You don't care about the existing table : simple, you can remove the #ORM\JoinTable(name="categories") annotation, and doctrine will create an other table etc.
You want to keep your existing table, which sounds pretty logical : you have to be more explicit in your annotation by adding #ORM\JoinColumn annotation.
Here is an example:
class
<?php
...
/**
* #ORM\Entity
* #ORM\Table(name="tasks")
*/
class Task
{
...
/**
* #ORM\ManyToMany(targetEntity="Category", inversedBy="tasks")
* #ORM\JoinTable(name="categories",
* joinColumns={#ORM\JoinColumn(name="category_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="task_id", referencedColumnName="id")})
*/
protected $category;
...
}
and Category object
<?php
...
/**
* #ORM\Entity
* #ORM\Table(name="categories")
*/
class Category
{
...
/**
* #ORM\ManyToMany(targetEntity="Task", mappedBy="category")
* #ORM\JoinTable(name="categories",
* joinColumns={#ORM\JoinColumn(name="task_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="category_id", referencedColumnName="id")})
*/
private $tasks;
...
Doing so, you will be able to keep your table without any doctrine error.
My fix for this, as far as I can tell, was a case-sensitivity issue with table names. Doctrine let me create a Users and a users table but afterwards would die on migrations:diff or migrations:migrate .
I used the -vvv option to get more detail on this error message; it seems that the error happens when Doctrine is loading up its own internal representation of the current database's schema. So if your current database has table names that Doctrine doesn't understand (like two tables that are identical, case-insensitive) then it will blow up in this fashion.
Seems like most of the answers above assume that the error is in your code, but in my case it was in the database.
I got this error with 2 ManyToMany targeting the same entity (User in the exemple below).
To create the table name doctrine use the entity and target entity name.
So in my case it was trying to create two time the table thread_user
To debug this it's easy. Just use the '#ORM\JoinTable' annotation and specify the table name.
Here is a working exemple.
/**
* #ORM\ManyToMany(targetEntity="App\Entity\User")
* #ORM\JoinTable(name="thread_participant")
*/
private $participants;
/**
* #ORM\ManyToMany(targetEntity="App\Entity\User")
* #ORM\JoinTable(name="thread_recipient")
*/
private $recipients;
in Symfony4.1 you can force the migration using the migration version
doctrine:migrations:execute <migration version>
ex
for migration version123456.php use
doctrine:migrations:execute 123456
there is another using the table name ,you can search it in your project . Maby be demo,I think it...
sorry for my chinese english !
Try to drop everything inside of your proxy directory.
I fix same issue after check other entities on each bundles, be aware of this.