I am trying to do add embedding forms dynamically using a single table in my schema.
What i mean by this is, in my sfGuardUserProfile table, I have numerous fields to determine what a user is, i.e. practice_id, nurse_id, patient_id
So, with that in mind, i am trying to dynamically add nurses to practices.
I have a practice form, that extends sfGuardUserAdminForm, which extends sfGuardUser, this is so i can get the username, password etc stored in the sfGuardUser table.
Within my practiceForm I am embedding a practiceProfileform, which displays the fields i need from the sfGuardUserProfile table. I hope everyone is following...
This works fine and I see the fields from both tables.
Now, the bit i am now unsure how to do: embedding the nurses. I am particularly unsure how to do this, as the practices and nurses are to be saved in the same table.
practiceForm
class Practiceform extends sfGuardUserAdminForm
{
public function configure()
{
$form = new PracticeProfileForm($this->getObject()->getProfile());
$this->embedForm('profile', $form);
}
}
I also have a nurseForm, which again extends sfGuardUser, embeds a nurseProfileForm, which extends sfGuardUserProfile to get the fields i need.
nurseForm
class dentistForm extends sfGuardUserAdminForm
{
public function configure()
{
$profileForm = new nurseProfileForm($this->object->Profile);
$this->embedForm('profile', $profileForm);
{
}
My schema.yml is as follows:
sfGuardUserProfile:
actAs:
Timestampable: ~
columns:
user_id:
type: integer(11)
notnull: true
default:
unsigned: false
primary: false
unique: false
autoincrement: false
email_new:
type: string(255)
unique: true
firstname:
type: string(255)
lastname:
type: string(255)
practice_id:
type: integer(11)
nurse_name:
type: varchar(255)
practice_name:
type: varchar(255)
practice_type:
type: varchar(255)
validate_at:
type: timestamp
validate:
type: string(33)
relations:
User:
class: sfGuardUser
foreign: id
local: user_id
type: one
onDelete: cascade
foreignType: one
foreignAlias: Profile
Practice:
class: sfGuardUserProfile
foreign: id
local: practice_id
type: one
onDelete: cascade
indexes:
validate:
fields: [validate]
Is there an easy way to achieve adding these nurses dynamically with the schema/forms i currently have using Doctrine/SF1.4?
Manay thanks
I would highly suggest to rethink your schema first. Do you really need to store all the entities in one table?
Instead, have different entities (classes) with their specific fields that relate to sfGuardUser. For example:
Nurse:
columns:
account_id: integer(4)
name: string(255)
...
relations:
Account:
class: sfGuardUser
local: account_id
foreign: id
type: one
foreignType: one
Then, you can embed Nurse relation in your sfGuardUserForm:
class sfGuardUserForm
{
public function configure()
{
$this->embedRelation('Nurse');
}
}
Or, the other way around:
class NurseForm
{
public function configure()
{
$this->embedRelation('Account');
}
}
And do the same for all the other entities. If you feel however, that your enities are pretty much the same, you can have a look at Doctrine's inheritance, though it is usually frowned upon.
Related
In my application (developed with Symfony 1.4 and Doctrine) I'm trying to get all users based on idempresa of the user logged in. idempresa is in a sf_guard_user_profiletable and this is the schema for that:
SfGuardUserProfile:
connection: doctrine
tableName: sf_guard_user_profile
columns:
id: { type: integer(8), primary: true }
user_id: { type: integer(8), primary: false }
idempresa: { type: integer(4), primary: false }
relations:
User:
local: user_id
class: sfGuardUser
type: one
foreignType: one
foreignAlias: SfGuardUserProfile
onDelete: CASCADE
onUpdate: CASCADE
I'm trying with this query:
Doctrine_Core::getTable('sfGuardUser')
->createQuery('u')
->leftJoin('u.Profile p')
->where('idempresa = ?', $id_empresa)
->execute();
But get this error:
Unknown relation alias Profile
What is wrong in my code?
Your relation between the sfGuardUser and sfGuardUserProfile is not called Profile but SfGuardUserProfile. So you should use in your query builder:
->leftJoin('u.SfGuardUserProfile p')
I have setup 3 tables in symfony:
A flipbook table, A Skills table, and a relations table, to connect each skill id with each flipbook id.
WHen I built the model, symfony constructed everything correctly, and by default gave a drop-down menu for the skills, which had all skills from the skills table as options. You can select an option and it creates the appropriate relationships.
This is working (sort of). When you submit the form, it does not add the skill_id to the record. It just adds the auto-increment id to the skills relations table and neither the flipbook_id or skill_id. Aaaaaand, if you click more than one checkbox, you get this nice message:
invalid parameter number number of bound variables does not match number of tokens
Whaaaat does that mean? This has got to be a schema issue eh?
How about some code? yes.please.
Schema:
Flipbook:
tableName: flipbook
inheritance:
extends: SvaGeneric
type: concrete
columns:
title: { type: string(255) }
career_associations: { type: clob }
skills: { type: string(255) }
skills_associations: { type: clob }
program: { type: string(255) }
program_associations: { type: clob }
draft_id: { type: integer(10) }
FlipbookSkills:
tableName: flipbook_skills
columns:
title: { type: string(255) }
relations:
Flipbook:
foreignAlias: flipbook_skills
alias: skills
local: title
onDelete: SET NULL
FlipbookSkillRelations:
tableName: flipbook_skill_relations
actAs:
SoftDelete: ~
options:
columns:
flipbook_id: { type: integer(10), notnull: false }
skill_id: { type: integer(10), notnull: false }
relations:
Flipbook:
foreignAlias: flipbook_skills_flipbook
alias: flipbook
local: flipbook_id
onDelete: CASCADE
FlipbookSkills:
foreignAlias: flipbook_skills_skills
alias: flipbookskills
local: skill_id
onDelete: CASCADE
FlipbookSkillsRelationsForm.class.php:
$this->widgetSchema['flipbook_id'] = new sfWidgetFormInputText(array(), array('class' => 'text size-500'));
$this->widgetSchema['skill_id'] = new sfWidgetFormSelectCheckbox(array('choices' => "**WHAT GOES HERE??**"), array('class' => 'text size-500'));
$useFields = array(
'flipbook_id',
'skill_id',
);
$this->useFields($useFields);
Let me know if I should provide further code or explanation.
Here is the FlipbookSkillsTable.class generated in the model:
<?php
/**
* FlipbookSkillsTable
*
* This class has been auto-generated by the Doctrine ORM Framework
*/
class FlipbookSkillsTable extends Doctrine_Table
{
/**
* Returns an instance of this class.
*
* #return object FlipbookSkillsTable
*/
public static function getInstance()
{
return Doctrine_Core::getTable('FlipbookSkills');
}
public function retrieveForFilter()
{
$res = $this->createQuery('s')
->select('s.id, s.name')
->orderBy('s.name ASC')
->execute(array(), Doctrine_Core::HYDRATE_NONE);
// if you want an empty line
$rets = array('' => '');
foreach ($res as $ret)
{
$rets[$ret[0]] = $ret[1];
}
return $rets;
}
public function getAllFlipbookSkills() {
$allSkills = Doctrine_Query::create()
->from('FlipbookSkills')
->orderBy('title ASC')
->execute();
return $allSkills;
}
}
UPDATE
I believe the issue is it is trying to bind the multiple values in the same record. It should make a new record for each skill chosen, like this:
id flipbook_id skill_id
1 2 1
2 2 2
3 2 3
SO I still don't have the schema nailed down correctly, otherwise Doctrine would know how to handle the data correct? Should I explicitly put one to many relationship?
Also, when submitted, it is only adding the flipbook_id value to the record. The skill_id record is 0
FLipbookRelationsForm:
class FlipbookSkillRelationsForm extends BaseFlipbookSkillRelationsForm
{
public function configure()
{
$this->widgetSchema['skill_id'] =
new sfWidgetFormDoctrineChoice(array('model' =>
$this->getRelatedModelName('flipbookskills'),
'expanded' => true, 'multiple' => true, 'add_empty' => false));
$useFields = array(
'flipbook_id',
'skill_id',
);
$this->useFields($useFields);
}
}
Multiple issues (maybe this post can help: Embedded forms in symfony 1.4 not saving propperly)
Your n-m relations doesn't look well defined. Your entities should looks like:
FlipbookSkill:
tableName: flipbook_skill
columns:
title: { type: string(255) }
relations:
Flipbooks:
class: Flipbook
refClass: FlipbookSkillRelation
local: skill_id
foreign: flipbook_id
/* Not foreignAlias and onDelete behaviour defined */
Flipbook:
tableName: flipbook
inheritance:
extends: SvaGeneric
type: concrete
columns:
title: { type: string(255) }
career_associations: { type: clob }
skills: { type: string(255) } # why this????
skills_associations: { type: clob } # why this????
program: { type: string(255) }
program_associations: { type: clob }
draft_id: { type: integer(10) }
relations:
Skills:
class: FlipbookSkill
refClass: FlipbookSkillRelation
local: flipbook_id
foreign: skill_id
FlipbookSkillRelation:
tableName: flipbook_skill_relation
actAs:
SoftDelete: ~
options:
columns:
flipbook_id: { type: integer(10), notnull: false }
skill_id: { type: integer(10), notnull: false }
relations:
Flipbook:
foreignAlias: FlipbookSkills
local: flipbook_id
foreign: id
onDelete: CASCADE
FlipbookSkill:
foreignAlias: FlipbookSkills
local: skill_id
foreign: id
onDelete: CASCADE
Then, you methods/join allowed are:
$flipbookObject->getSkills(); Because flipbook entity n-m relation name "Skills", wich returns a FlipbookSkill DoctrineCollection. Or in query ('f.innerJoin Skills s')
$flipbookObject->getFlipbookSkills(); Because flipbookSkillRelation 1-n foreignAlias name, but probably you will never use this (because you don't really care about relations inself, instead you care about related skills).
... etc
If you have a well defined schema.yml, then your forms should work properly.
Plus:
why are you using and text input widget for an id field (flipbook_id) ????
And why are you using a sfWidgetFormSelectCheckbox if you are working with doctrine entities? You should use sfWidgetFormDoctrineChoice like the BaseEntity defines.
I hope this can help you.
Where are your validators ? Symfony forms don't work properly with missing validators or inappropriate ones. If your validator accept 1-1 relationship, and you send multiple values, it won't work.
Try this :
$this->validatorSchema->setOption('allow_extra_fields' , true);
$this->validatorSchema->setOption('filter_extra_fields' , false);
If your error disappear, then you have a problem with validators. Otherwise you can try to use a the sfEmbedded forms, you render an sfForm, and add multiple time your FlipbooSkillForm with selects. If i remeber well there is some tutorials showing how to add them in js.
http://nacho-martin.com/dynamic-embedded-forms-in-symfony
I have just created a new project with a many-to-many relation (User-Group) and the code below.
As you can guess in the code I'm trying to assign manually groups to a user, but it doesn't assign it anything...any idea?
User:
columns:
id:
type: integer(4)
autoincrement: true
primary: true
username:
type: string(255)
password:
type: string(255)
attributes:
export: all
validate: true
Group:
tableName: group_table
columns:
id:
type: integer(4)
autoincrement: true
primary: true
name:
type: string(255)
relations:
Users:
foreignAlias: Groups
class: User
refClass: GroupUser
GroupUser:
columns:
group_id:
type: integer(4)
primary: true
user_id:
type: integer(4)
primary: true
relations:
Group:
foreignAlias: GroupUsers
User:
foreignAlias: GroupUsers
The code is this:
public function executeIndex(sfWebRequest $request)
{
$user = Doctrine_Core::getTable('User')->find(1);
$groups = Doctrine_Core::getTable('Group')->findAll();
$user->setGroups($groups);
$user->save();
$this->forward('default', 'module');
}
Try defining the relation in the User entity too (and don't using foreingAlias in Groups). Also use the local and foreign fields.
So, schema.yml should look like:
User:
...
relations:
Groups:
class: Group
refClass: GroupUser
local: user_id
foreign: group_id
Group:
...
relations:
Users:
class: User
refClass: GroupUser
local: group_id
foreign: user_id
If that doesn't work, I think you can set the groups with the Doctrine "link" method.
See Record.php (probably in lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine folder)
Example:
$groups_ids = array();
foreach($groups as $group) $groups_ids[] = $group->getId();
$user->link('Groups',$groups_ids);
Also, if you are trying only to add instances to that relation (and you hate the person who will fix your code in the future) you can create N-GroupUsers
Example:
foreach($groups as $group) {
$ug = new GroupUser();
$ug->setUserId($user->getId());
$ug->setGroupId($user->getId());
$ug->save();
}
Please, use the first option and let me know if any of this works for you!
Hy guys
I've got the following schema for my objects:
Product:
columns:
name: { type: string(255) }
Basket:
columns:
current_status: { type: integer }
relations:
Products: { class: Product, refClass: BasketProducts, onDelete: CASCADE }
BasketProducts:
columns:
product_id: { type: integer, primary: true }
basket_id: { type: integer, primary: true }
quantity: { type: integer(4) }
relations:
Product: { local: product_id, onDelete: CASCADE }
Basket: { local: basket_id, onDelete: CASCADE }
Now in the frontend I try to show the users basket, getting the products by
foreach($basket->getProducts() as $product) {
echo $product->getId();
echo $product->getName();
}
The question now, how can i access the quantity field from the BasketProducts?
You will need to query the middle table directly in order to do this.
A good way to do this, is to add a function in your Basket.class.php that will retrieve the data you need based on a BasketID.
You could also create the function in your BasketTable.class.php if you'd like to include the data when fetching a particular basket (ie. getBasketWithProductQuantities())
I don't have any Doctrine code handy at this time.
I'm getting this error when I'm trying to implement this code. The first code block with $user seems to work as the database is updated, but the second part fails. This is the error:
Unknown record property / related component “sf_guard_user” on “sfGuardUserProfile”
public function executeCreateAccount()
{
$user = new sfGuardUser();
$user->setUsername($this->getRequestParameter('username'));
$user->setPassword($this->getRequestParameter('password'));
$user->setIsActive(false);
$user->save();
$profile = new sfGuardUserProfile();
$profile->setsfGuardUser($user);
$profile->setEmail($this->getRequestParameter('user_email'));
$profile->setRemember($this->getRequestParameter('remember', true));
$profile->save();
$this->getRequest()->setAttribute('user', $user);
$raw_email = $this->sendEmail('user', 'registrationConfirmation');
$this->logMessage($raw_email, 'debug');
$this->setFlash('user_email', $this->getRequestParameter('user_email'));
$this->redirect('user/askConfirmation');
}
Here is my schema.yml for the user profile:
sf_guard_user_profile:
columns:
id: { type: integer, primary: true, autoincrement: true }
user_id: { type: integer }
firstname: { type: string(255) }
lastname: { type: string(255) }
user_email: { type: string(255) }
relations:
sfGuardUser:
type: one
foreignType: one
class: sfGuardUser
local: user_id
foreign: id
onDelete: cascade
foreignAlias: Profile
I see that the following two lines, do not match up with your schema file:
$profile->setEmail($this->getRequestParameter('user_email'));
$profile->setRemember($this->getRequestParameter('remember', true));
The setEmail should be setUserEmail.
The setRemember doesn't exist in your schema.
EDIT
I guess the error message would be indicating that the following line is bad:
$profile->setsfGuardUser($user);
I'm not sure if you can do that or not though, settings a related model with a set method.
Try changing this line:
$profile->setsfGuardUser($user);
to
$profile->setSfGuardUser($user);
(note the capital S)