I'm repeatedly getting confused between Language & Culture in Symfony.
- I'm setting culture as (en_US) which I guess is correct
- but translation files are created for a language (en)
- also, when using translation in the database, the lang=en
I have a model whose definition is as follows:
Option:
package: Options
tableName: Com_Options
actAs:
I18n:
fields: [name, tooltip]
columns:
id:
type: integer(2)
primary: true
notnull: true
unsigned: true
# autoincrement: true
name:
type: string(50)
notnull: true
notblank: true
tooltip:
type: string(100)
sequence:
type: integer(1)
unsigned: true
range: [0,255]
This class is referred by several other classes.
When I try to print the name as $refObj->Option->Name I get nothing. When I check the queries, I see that 3 queries are fired in all.
1) to get refObj
2) to get Option
3) to get Translation
But the real problem is that for 3, there is no language parameter in the query.
I wonder how it will get the translated name? Current value of sf_culture: en_US
Is there another way to access the 'name' according to user's language?
Or do I need to write custom queries on every model?
Is the problem because autoincrement is OFF, or because Im using a package?
Thanks a lot!
Found this: a very tedious & costly method, but works:
$class->relation->Translation[$lang]->property
If you wish to read directly from database
$q = Table::getInstance()->createQuery('a')
->select('a.id, t.name')
->leftJoin('a.Translation t')
->where('t.lang = ?', $lang);
return $q->execute(array(), Doctrine::HYDRATE_NONE);
If you use XLIFF files, you need not pass culture/language
__('text which is translated in the XLIFF for user\'s culture');
Related
I refer to an other component, and some of its fields become required.
Example with AbstractQuestion, a component that I will refer to later on:
AbstractQuestion:
type: object
properties:
title:
description: Question statement
type: string
label:
description: Question label
type: string
required:
description: whether an answer is required for this question or if it could be left blank
type: boolean
question_type:
description: campaign type
enum:
- profile
- feeling
type: string
answer_type:
enum:
- string
- list
- date
type: string
max_length:
description: >-
for open ended questions this is the max characters possible. for list type questions
this would be the max number of options to select when multiple answers are accepted
type: integer
modelizable:
description: 'whether the questions'' answers are suitable for feeding ML models (e.g. 1,2,3,4)'
type: boolean
choices:
$ref: '#/components/schemas/QuestionChoices'
Now, I will use it to define a Post request body, specifying which field are required. NB: I didn't specify this in the previous object because it is also used in an other context (GET or PUT requests for example) where those fields are not required.
QuestionPost:
allOf:
- $ref: '#/components/schemas/AbstractQuestion'
required:
- title
- label
- required
- question_type
- answer_type
- modelizable
When I try this solution, my tests do not pass, as they match the yaml file to my api and find this error:
openapi_spec_validator.exceptions.ExtraParametersError: Required list has not defined properties: ['label', 'title', 'answer_type', 'question_type', 'modelizable', 'required']
It seems unable to find the required properties in the referenced component.
When I try this solution:
QuestionPost:
$ref: '#/components/schemas/AbstractQuestion'
required:
- title
- label
- required
- question_type
- answer_type
- modelizable
I get a warning in my editor. My understanding of the doc is that the required field will be ignored.
Maybe what I'm trying to achieve is just not possible? How would you do it?
I've got two little questions:
actAs: { Timestampable: ~ }
What the "~" what mean in the code above?
Then, I've seen that tables with actAs: { Timestampable: ~ } have two fields (created_at and updated_at).
Is it possible to bind the updated_at field to a particular field (I update this field, then updated_at get a new value) ?
The "~" means that you will use default values or default configuration. In your case, the behavior Timestampable, will use the default value and configuration. So you don't have to redefine them.
From the doc, here are some configuration:
Timestampable:
created:
name: created_at
type: timestamp
format: Y-m-d H:i:s
updated:
disabled: true
You will also find this "~" (a lot) in the default generator.yml. This way, the generator, even empty, will generate a nice admin:
config:
actions: ~
fields: ~
list: ~
filter: ~
form: ~
edit: ~
new: ~
For your second question, the goal of the Timestampable is for each modification on a row, the field updated_at will be set with the current date. So you don't need to take care of it.
Edit:
And if you want to manually update the updated_at field:
first: you will have to disable the timestampable behavior for this field (see the example above
second: you will have to do the behavior on your own.
The easiest way is to extends the preSave function of your model and do the job here. Like:
class Article extends BaseArticle
{
public function preSave($event)
{
if(array_key_exists("your_field", $this->getModified())
{
$this->setUpdatedAt(time());
}
}
I have a many to many relationship between products and colours.
What I am trying to do is find products by their colours.
eg)
$colours = $em->getRepository('Xxxxx\XxxxxBundle\Entity\Colour')->findBy(array('name'=>'red');
$products = $em->getRepository('Xxxxx\XxxxxBundle\Entity\Product')->findBy(array('colours'=>$colours));
This is my Yaml config:
Xxxxx\XxxxxBundle\Entity\Product:
type: entity
manyToMany:
colours:
targetEntity: Colour
joinTable:
name: Product_Colour
joinColumns:
product_id:
referencedColumnName: id
inverseJoinColumns:
colour_id:
referencedColumnName: id
.
Xxxxx\XxxxxBundle\Entity\Colour:
type: entity
id:
id:
type: integer
generator:
strategy: AUTO
fields:
hex:
type: string
length: 320
name:
type: string
length: 320
The error message I am getting is:
Notice: Undefined index: joinColumns in /home/xxx/public_html/products/vendor/doctrine/lib/Doctrine/ORM/Persisters/BasicEntityPersister.php line 1217
Would someone be able to shine some light on why this is not working.
I know this is an old question, but if anyone else arrives here via Google (like I did), I had to eschew the findBy and use DQL in the repository:
$products = $em->getRepository('Vendor\Bundle\Entity\Product')->findByColours($colours);
And in the repository:
public function findByColours($colours)
{
$qb = $this->getEntityManager()->createQueryBuilder();
$qb ->select(array('p'))
->from('VendorBundle:Product', 'p')
->join('p.colours', 'c', 'WITH', $qb->expr()->in('c.id', $colours));
$result = $qb->getQuery()->execute();
return $result;
}
You may need to change the join based on what $colours is. This is assuming it's an array of colour IDs. If it's a string you can forgo the in() or if it's an array of strings you'll need to bind the strings as parameters (see the following link). Clarification on expr() and such is in the Doctrine docs
I don't know why Undefined index: joinColumns occurs, but this is a method to side-step it altogether. Hopefully someone can clarify as to the error, as my solution adds extra work to the Many to Many relationship.
I have a versionable table in my schema. I want it not to be versioned when i change status for example, but versioned when i change shippingPrice.
MyOrder:
actAs:
Timestampable:
Versionable:
versionColumn: version
className: %CLASS%Version
auditLog: true
columns:
userId: { type: integer, notnull: true }
status: {type: enum, values: ["status1", "status2"]}
shippingPrice: { type: float, notnull: true }
#more columns
How can i do that ?
This article might be of some interest:
http://blog.solutionset.com/wpmu/2009/08/26/doctrine-with-nested-i18n-versionable/
The author wants to nest I18N functionality with Versionable. The problem is slightly different; you can't even build the database when you nest I18N and Versionable, but the solution he came up with might be useful.
In essence, he rolled his own Versionable. Not the most pleasant prospect, but looking at how he implemented it might save you some time on your own spike.
This is a bit hacky but should do what is required I think.
I haven't tested it but my understanding is that if you do a dql update() Versionable is not triggered.
Like this
$result = $this->createQuery()
->update('MyOrder m')
->set('m.status', $var)
->execute();
But if you retrieve the object, change it and save thus:
$m = MyOrderTable::getInstance()->findOneById($id);
$m->setShippingPrice($price);
$m->save();
Then Versionable will be triggered so you should get a new version.
So you could use this to solve the problem.
I have a doctrine form in Symfony, which saves certain object in a table in the DB.
By doing this, I wish to also update another object, which has a relation to the first one, so the objects get the relation (one-to-many) updated as the first object gets saved.
I really don't know if this is possible at all...
I'll post my code, as a reference:
Schema:
Entry:
columns:
pic: { type: integer, notnull: false, default: null }
relations:
Pic:
local: pic
foreign: id
onDelete: SET NULL
Pics:
type: many
class: Pic
local: id
foreign: entry_id
Pic:
columns:
id: { type: integer, notnull: true, primary: true, autoincrement: true }
entry_id: { type: integer, notnull: true, primary: true }
pic: { type: string(255), notnull: true }
relations:
Entry:
local: entry_id
foreign: id
onDelete: CASCADE
I have another many-to-many relation between Pic and Entry, because an Entry may have a lot of Pics, but the first Pic I create must also be defined as the 'default' Pic which I stablish in the Entry.pic field...
(I previously and correctly create an Entry, so now I must get a new Pic, which will be the 'default' one for the Entry)... In the create actions for the Pic table, I wish to update the Entry so it knows the brand new Pic I have just added and that should get linked by 'default' with it...
Pic actions.class.php:
public function executeCreate(sfWebRequest $request)
{
$this->form = new PicForm();
$this->form->bind(
$request->getParameter($form->getName()),
$request->getFiles($form->getName())
);
if ($form->isValid())
{
$this->pic = $form->save();
$entry = $this->pic->getEntry();
$entry->updateSetPic($this->pic);
$this->redirect('entry_show', $entry);
}
}
Finally, I have the following 'updateSetPic' method in the lib/model/doctrine/Entry.class.php file:
public function updateSetPic(Pic $pic)
{
$this->setPic($pic);
$this->save();
}
The problem I have right now is that, seemingly, the upateSetPic method, receiving the recently saved Pic object (in the Pic actions create method), just receives nothing, as if the Pic object that the $form->save() method has nothing in it (even though, it truly saves, but maybe at this stage it isn't commited or something?)
So my question is, am I doing this all right? Or where am I wrong? Is there a way to acomplish what I need? If so, what is that way? Maybe I need to mingle into another part of the Pic save process, but I'm kind of lost by now...
Any ideas?
Thank you!
In your "$form->isValid()" if statement, it seems your $entrada, that you're calling updateSetPic on, is not set.
But to answer your question, you might want to look at the postSave() function you can add to your object ( http://www.doctrine-project.org/projects/orm/1.2/docs/manual/event-listeners/en ).