I'm editing a product and its current properties in a form with embedRelation('ProductProperty'). Everything is good so far. E/R diagram here http://d.pr/1N7R
However, now I want to split up the form and show attribute sets in different AJAX tabs according to its SetID. I still want to have a single 'Save' button, but it is not critical if I need to have multiple. How can I do this?
In my _form.php I'm iterating Sets but I can't seem to get the SetID for the ProductProperty form object. Am I going about this the wrong way?
I'm using symfony 1.4 and Doctrine 1.2. Here is my schema.yml
Product:
tableName: products
actAs:
Timestampable: ~
Sluggable:
unique: true
fields: [title]
canUpdate: true
columns:
id:
type: integer
primary: true
autoincrement: true
category_id:
type: integer
notnull: true
sku:
type: string(50)
notnull: true
title:
type: string(150)
notnull: true
relations:
Category:
foreignType: many
foreignAlias: Products
Property:
tableName: properties
actAs:
Timestampable: ~
Sluggable:
unique: true
fields: [description]
canUpdate: true
columns:
id:
type: integer
primary: true
autoincrement: true
set_id:
type: integer
notnull: true
description:
type: string(100)
notnull: true
relations:
Set:
foreignType: many
foreignAlias: Properties
Set:
tableName: sets
actAs:
Timestampable: ~
columns:
id:
type: integer
primary: true
autoincrement: true
title:
type: string(100)
notnull: true
ProductProperty:
tableName: product_properties
actAs:
Timestampable: ~
columns:
product_id:
type: integer
primary: true
property_id:
type: integer
primary: true
value:
type: text
notnull: true
relations:
Product:
alias: Product
foreignType: many
foreignAlias: ProductProperties
onDelete: cascade
Property:
alias: Property
foreignType: many
foreignAlias: PropertyProperties
onDelete: cascade
I managed to solve this with the help from dustin10 on the #symfony IRC channel (irc.freenode.net). In case anyone else need it, here is the solution:
We added a hidden field in my ProductPropertyForm with the SetID I was trying to retrieve in my form:
$this->setWidget('property_set_id', new sfWidgetFormInputHidden());
$this->setDefault('property_set_id', $this->getObject()->getProperty()->getSetId());
$this->setValidator('property_set_id', new sfValidatorString());
That way I could retrieve the value in my form with:
$eForm['property_set_id']->getValue()
I now have my form separated into multiple tabs with jQuery :) Again, thanks a lot to dustin10 for his help.
Related
I use symfony 1.4.11 with Doctrine
I have sfGuardUser module in backend. I have sfGuardUserProfile table.
sfGuardUserProfile:
connection: doctrine
tableName: sf_guard_user_profile
columns:
id: { type: integer(4), primary: true, autoincrement: true }
user_id: { type: integer(4), notnull: true }
salutation: { type: string(10), notnull: true }
first_name: { type: string(30), notnull: true }
last_name: { type: string(30), notnull: true }
country: { type: string(255), notnull: true }
postcode: { type: string(10) , notnull: true }
city: { type: string(255), notnull: true }
address: { type: string() , notnull: true }
phone: { type: string(50) }
email: { type: string(255), notnull: true }
validate: { type: string(17) }
banned: { type: boolean, default: 0 }
payed_until: { type: datetime, notnull: true}
relations:
User:
class: sfGuardUser
foreign: id
local: user_id
type: one
onDelete: cascade
onUpdate: cascade
foreignType: one
foreignAlias: Profile
indexes:
user_id_unique:
fields: [user_id]
type: unique
SfGuardUser table:
GuardUser:
actAs: [Timestampable]
columns:
id:
type: integer(4)
primary: true
autoincrement: true
username:
type: string(128)
notnull: true
unique: true
algorithm:
type: string(128)
default: sha1
notnull: true
salt: string(128)
password: string(128)
is_active:
type: boolean
default: 1
is_super_admin:
type: boolean
default: false
last_login:
type: timestamp
indexes:
is_active_idx:
fields: [is_active]
relations:
groups:
class: sfGuardGroup
local: user_id
foreign: group_id
refClass: sfGuardUserGroup
foreignAlias: Users
permissions:
class: sfGuardPermission
local: user_id
foreign: permission_id
refClass: sfGuardUserPermission
foreignAlias: Users
I have next sfGuardUserForm:
public function configure()
{
parent::configure();
$profileForm = new sfGuardUserProfileForm($this->object->Profile);
unset($profileForm['user_id'],$profileForm['banned'],$profileForm['validate'],$profileForm['payed_until']);
$profileForm->widgetSchema['salutation'] = new weWidgetSalutationI18n();
$profileForm->widgetSchema['country'] = new sfWidgetFormI18nChoiceCountry();
$profileForm->setDefault('country', 'DE');
$this->embedForm('Profile', $profileForm);
}
So, when I add new user from backend, in my sfGuardUserProfile table user_id = 0 ...
Try if this works for you:
public function configure()
{
parent::configure();
$profile = new sfGuardUserProfile();
$profile->setUserId($this->getObject()->id);
$profileForm = new sfGuardUserProfileForm($profile);
$this->embedForm('Profile', $profileForm);
}
I'm not really sure, but form the top of my head it's because you unset the user_id value.
Somethings that first came to mind are:
Read this (to define a primary key, the keyword is primaryKey: true not primary: true and they dont need to be defined as autoincremental, ORM can guess it for himself)
Dont unset the user_id or any ids of forms , they are hidden by default so that should not be a problem.
Check those poitns and see if he problem persist, if so i cuold be something not properly updated when changing the schema (remember always clearing cache and building all classes every time you modify your schema)
Hope this helps!
I'm trying to update a foreign key in processForm() and get this error.
It's a valid value
I can set values to a normal field without problem, I only get this error when I try to update foreign keys
This way i get the error:
$form->getObject()->setPriority(1);
This way i get no error but doesn't work too:
$form->getObject()->setPriorityId(1);
Schema:
schedule:
columns:
id:
primary: true
type: integer
notnull: true
autoincrement: true
sdate:
type: date
notnull: true
stime:
type: time
notnull: true
scope:
default: 1
type: boolean
schedule_count:
default: 0
type: integer(4)
reschedule_justify:
type: string
priority_id:
type: integer
notnull: true
schedule_type_id:
type: integer
notnull: true
pending_id:
default: NULL
type: integer
cancelled_id:
default: NULL
type: integer
scheduled_by:
type: integer
notnull: true
in_charge:
type: integer
notnull: true
so_id:
unique: true
type: integer
notnull: true
relations:
priority:
local: priority_id
foreign: id
scheduleType:
local: schedule_type_id
foreign: id
cancelled:
onDelete: SET NULL
local: cancelled_id
foreign: id
pending:
onDelete: SET NULL
local: pending_id
foreign: id
ScheduledBy:
class: employee
local: scheduled_by
foreign: id
InCharge:
class: employee
local: in_charge
foreign: id
soOrder:
local: so_id
foreign: id
Employees:
class: employee
refClass: schedule_employee
local: schedule_id
foreign: employee_id
priority:
actAs:
SoftDelete:
columns:
id:
primary: true
type: integer
notnull: true
autoincrement: true
name:
unique: true
type: string(255)
notnull: true
img:
type: string(255)
These are the main tables i'm using, I'm in schedule and trying to update priority
So, your task is to manually set a 'Priority' relation to a 'Schedule' object before saving it.
// PriorityForm
class ScheduleForm extends BaseScheduleForm
{
public function doSave($con = null)
{
//update object with form values (not necessary in your case, but will be if you need to
//use values that were in form
$this->updateObject();
$priority = Doctrine::getTable('Priority')->findOneById(1);
$this->getObject()->setPriority($priority);
return parent::doSave($con);
}
}
How can I implement pagination using Doctrine_Pager or sfDoctrinePager while my query selects multiple columns from two or more tables ?
Edit1:
Ok, now I figured out that it can be done how Nathan has described below! I got confused as I couldn't retrieve certain data from the query! Let me describe it below:
This is my pager query:
$pager = new sfDoctrinePager('sfGuardUser', '5');
$q = Doctrine_Query::create()
->select('u.id, u.username, p.org_name, g.name, l.status')
->from('sfGuardUser u')
->leftJoin('u.Profile p')
->leftJoin('u.Groups g')
->leftJoin('u.LicensedVendors l')
->where('g.name = \'client\'');
$pager->setQuery($q);
$pager->setPage($request->getParameter('page', 1));
$pager->init();
Now in my Template I can retrieve my sfGuardUser and Profile data like this:
foreach ($pager->getResults() as $data) {
echo $data->username ; //outputs 'username' from sfGuardUser table
echo '<br />' ;
echo $data->Profile->org_name ; //outputs 'Organization name' from sfGuardUserProfile table
}
I was wrongly trying to retrieve the profile data by $data->org_name and not $data->Profile->org_name! Now its working for this part correctly, but there is still an issue !
I am still unable to retrieve the Groups & LicensedVendors data using $data->Groups->name or $data->LicensedVendors->status ! It does not show any error or any value either! looks like it outputs an empty string. Shouldn't it get the value just like Profile data ?
But when I hydrate the query by setting:
$q->setHydrationMode(Doctrine_Core::HYDRATE_SCALAR);
I can retrieve all data through:
foreach ($pager->getResults() as $data) {
echo $data['u_username'];
echo $data['p_org_name'];
echo $data['g_name'];
echo $data['l_status'];
}
How to get those data without setting **Doctrine_Core::HYDRATE_SCALAR** ? Where I'm doing wrong for retrieving those Groups and LicensedVendors table data?
Here is the schema definition of the tables described above:
License:
actAs: [Timestampable]
tableName: licenses
columns:
id:
type: integer(4)
primary: true
notnull: true
autoincrement: true
status:
type: enum
values: ['approved','pending_admin','pending_client','pending_vendor','rejected']
default: 'pending'
client_id:
type: integer(8)
notnull: true
vendor_id:
type: integer(8)
notnull: true
product_desc:
type: clob(16777215)
supplier_name:
type: string(80)
other_desc:
type: string(50)
financial_statement:
type: clob
relations:
VendorUser:
class: sfGuardUser
local: client_id
foreign: id
foreignAlias: LicensedVendors
onDelete: cascade
foreignType: many
owningSide: true
ClientUser:
class: sfGuardUser
local: vendor_id
foreign: id
foreignAlias: LicensedClients
onDelete: cascade
foreignType: many
owningSide: true
sfGuardUser:
actAs: [Timestampable]
columns:
first_name: string(255)
last_name: string(255)
email_address:
type: string(255)
notnull: true
unique: true
username:
type: string(128)
notnull: true
unique: true
algorithm:
type: string(128)
default: sha1
notnull: true
salt: string(128)
password: string(128)
is_active:
type: boolean
default: 1
is_super_admin:
type: boolean
default: false
last_login:
type: timestamp
indexes:
is_active_idx:
fields: [is_active]
relations:
Groups:
class: sfGuardGroup
local: user_id
foreign: group_id
refClass: sfGuardUserGroup
foreignAlias: Users
sfGuardUserProfile:
actAs:
Timestampable: ~
columns:
user_id:
type: integer
notnull: true
email:
type: string(80)
notnull: true
unique: true
email_new:
type: string(80)
unique: true
firstname:
type: string(30)
lastname:
type: string(70)
org_name:
type: string(80)
notnull: true
relations:
User:
class: sfGuardUser
foreign: id
local: user_id
type: one
onDelete: cascade
foreignType: one
foreignAlias: Profile
sfGuardGroup:
actAs: [Timestampable]
columns:
name:
type: string(255)
unique: true
description: string(1000)
relations:
Users:
class: sfGuardUser
refClass: sfGuardUserGroup
local: group_id
foreign: user_id
foreignAlias: Groups
Edit2: I posted my new issues which I described in first edit as a separate question here !
I guess as long as your query gives back a Doctrine_Collection object, you can use it with a pager, can't you?
Yeah, what greg0ire said. This documentation is a bit old, but it shows what you'd need with Propel in the old days. Updating to Doctrine would be like,
public function executeList ()
{
$pager = new sfDoctrinePager('Comment', 2);
$q = Doctrine_Core::getTable('Comment')
->createQuery('c')
->where('c.author = ?', 'Steve')
->leftJoin('c.Article a')
->andWhere('a.content LIKE ?', '%enjoy%')
->orderBy('c.created_at ASC');
$pager->setQuery($q);
$pager->setPage($request->getParameter('page', 1));
$pager->init();
$this->pager = $pager;
}
This blog post, "Symfony doctrine pager for two tables" has a more extended/convoluted example. Oh, looks like that was the author's answer to his own SO question.
I'm building a schema.yml and I'm trying to add foreign key constraints to the table sf_guard_user.
But, when I do doctrine:insert-sql (edit: doctrine:build --all), the links between my tables and sf_guard_user are not there ! Am I missing something ?
I'm using mysql (InnoDB) and Symfony 1.4
Here's a sample of my schema.yml :
Author:
connection: doctrine
tableName: ec_author
actAs:
Sluggable:
fields: [name]
unique: true
canUpdate: false
columns:
sf_guard_user_id:
type: integer
fixed: false
unsigned: false
primary: true
autoincrement: false
name:
type: string(30)
fixed: false
unsigned: false
primary: false
notnull: true
autoincrement: false
contents:
type: string()
fixed: false
unsigned: false
primary: false
notnull: false
autoincrement: false
relations:
User:
class: sfGuardUser
foreignType: one
local: sf_guard_user_id
foreign: id
There are no links to sfGuardUser, even though they are described in schema.yml :
This one works:
Author:
connection: doctrine
tableName: ec_author
actAs:
Sluggable:
fields: [name]
unique: true
canUpdate: false
columns:
sf_guard_user_id:
type: integer
fixed: false
unsigned: false
primary: false
autoincrement: false
name:
type: string(30)
fixed: false
unsigned: false
primary: false
notnull: true
autoincrement: false
contents:
type: string()
fixed: false
unsigned: false
primary: false
notnull: false
autoincrement: false
relations:
User:
class: sfGuardUser
foreignType: one
local: sf_guard_user_id
foreign: id
foreignAlias: author
sf_guard_user_id is a foreign key, then it can't be a primary key. so I changed
primary: true to primary: false.
You should be rebuilding the models and sql as well. Try running:
symfony doctrine:build --all
This will clobber all existing data. If you don't want that, you'll have to write a migration.
The Class name needs to be the same name as you specified when opening the corresponding table in your schema file.
So, for example, you are using:
relations:
User:
class: sfGuardUser
foreignType: one
The class name here must match the declaration of the sfGuardUser table. Just make sure they are the same. Sometimes, it can be declared as sf_guard_user.
If that is fine, you can try adding a few more definitions to your Relations entry:
relations:
User:
class: sfGuardUser
foreignType: one
local: sf_guard_user_id
foreign: sf_guard_user_id
I'm getting a weird error in symfony 1.4 with doctrine 1.2. My schemas seem to be normal. But whenever I execute the doctrine:build --all --no-confirmation --and-load task, it would output the error SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'default_edition_id' cannot be null. If I set notnull to false for the default_edition_id field, it would actually just be null. Can anyone help me out on what I may be missing?
Here is my schema file (chapter.yml):
Chapter:
actAs:
Timestampable: ~
Versionable:
versionColumn: version
className: %CLASS%Version
SoftDelete: ~
columns:
name: string
chapter_number: { type: integer, notnull: true }
series_id: { type: integer, notnull: true }
default_edition_id: { type: integer, notnull: true }
disabled:
type: enum
values: [1, 0]
default: 0
notnull: true
relations:
DefaultEdition:
local: default_edition_id
class: Edition
foreign: id
foreignAlias: DefaultChapter
foreignType: one
type: one
# onDelete: CASCADE
Series:
local: series_id
foreign: id
onDelete: CASCADE
Editions:
type: many
class: Edition
local: id
foreign: chapter_id
and my edition schema (edition.yml):
Edition:
actAs:
Timestampable: ~
Sluggable:
fields: [name]
Versionable:
versionColumn: version
className: %CLASS%Version
SoftDelete: ~
columns:
name: string
completed_reads: { type: integer, notnull: true, default: 0}
views: { type: integer, notnull: true, default: 0 }
language_id: { type: integer, notnull: true }
chapter_id: { type: integer, notnull: true }
disabled:
type: enum
values: [1, 0]
default: 0
notnull: true
relations:
Pages:
type: many
class: Page
local: id
foreign: edition_id
Language:
local: language_id
foreign: id
type: one
onDelete: CASCADE
Chapter:
local: chapter_id
foreign: id
onDelete: CASCADE
Fixtures:
Chapter:
bakuman_chapter:
Series: bakuman
chapter_number: 86
DefaultEdition: edition_1
bakuman_chapter2:
Series: bakuman
DefaultEdition: edition_2
chapter_number: 90
Edition:
edition_1:
name: edition 1
Chapter: bakuman_chapter
ScanlationGroup: [group_1, group_2, group_3]
Language: english
edition_2:
name: edition 2
Chapter: bakuman_chapter2
ScanlationGroup: [group_4]
Language: japanese
edition_2_2:
name: edition 2_2
Chapter: bakuman_chapter2
ScanlationGroup: [group_4, group_2]
Language: english
"If I set notnull to false for the default_edition_id field, it would actually just be null". In this sentence, was does "it" refer to? Notnull means that the value 'null' is acceptable for this field, not that its value will always be null, if this was what you meant.