I want to make private messages in my site. I want that user can delete received or sent messages. For it I need two tables one for send message and one for receive....Is it to possible that when user send messages, it automatically add fro two tables? or it is better to make some relations with tables? or maybe exist better solution?
I think you need just one table:
Message:
columns:
from: integer
to: integer
header: string(100)
body: blob
show_in_outcoming:
type: boolean
default: true
show_in_incoming:
type: boolean
default: true
is_read:
type: boolean
default: false
UserFrom:
class: sfGuardUser
local: from
foreign: id
foreignType: one
type: one
UserTo:
class: sfGuardUser
local: to
foreign: id
foreignType: one
type: one
where
is_read indicates whether or not the message been read (false - unread, true - read - for incoming messages only)
If the user who sends the message want to delete it, we simply hide it (not delete from the DB) - set show_in_outcoming to false.
If the user who received the message want to delete it, we hide it too - set show_in_incoming to false. This approach allows us to recover the "hidden" messages (or remove them altogether)
Maybe, you should create a message table, with tow relation to user table:
message:
columns:
user_emitter_id: ...
user_reciever_id: ...
body: ...
relations:
userEmitter:
class: user
local: user_emitter_id
foreign: id
userReciever:
class: user
local: user_reciever_id
foreign: id
There is a symfony plugin that allows you to do this. Check sfSocialPlugin.
Message:
columns:
from: integer
to: integer
header: string(100)
body: blob
show_in_outcoming:
type: boolean
default: true
show_in_incoming:
type: boolean
default: true
is_read:
type: boolean
default: false
relations:
UserFrom:
class: sfGuardUser
local: from
foreign: id
foreignType: one
type: one
UserTo:
class: sfGuardUser
local: to
foreign: id
foreignType: one
type: one
Related
I'm using symfony for a project but got stuck at one point building the schema. In the schema I have one table user that can be created by himself or and administrator and the user ids are stored in sfGuardUser... how can y make a relation between them in the schema.yml?
I have this fields:
tableX
sf_guard_user_id: {type: integer}
sf_guard_user_id_cs: {type: integer}
The first id is the one he gets when created and the second is the administrator's id if it was created by one. So basically, I'm gonna use the id field from sfGuardUser twice in tableX but I'm not able to make this two relations in the schema.yml. Anyone knows how to do the relations?
It is simple. For example:
CoolTable:
actAs:
Timestampable: ~
columns:
sf_guard_user_id: { type: integer() }
sf_guard_user_id_cs: { type: integer() }
relations:
User: { local: sf_guard_user_id, foreign: id, class: sfGuardUser }
UserCs: { local: sf_guard_user_id_cs, foreign: id, class: sfGuardUser }
Main point, that you specify the class of relations.
I've inherited the development of a symfony 1.4 app (though It's my first symfony project).
After digging a bit on that app I've discovered a bug that is driving me nuts.
On the admin generator list page of a module there are two select fields in the filter form that should list each one a type of users (partners and clients), however both listings show all the users.
The generator.yml shows that both select fields should be populated by parter_id and client_id
[...]
filter:
display: [date, client_id, partner_id, ...]
form: ~
edit: ~
new: ~
[...]
Looking at the schema of the module it's obvious why symfony is populating the select fields with the same content because the relations of both client_id and partner_id are equivalent:
SomeModule:
tableName: client_requests
columns:
id: {type: integer, primary: true, autoincrement: true}
partner_id: {type: integer, notnull: true}
client_id: {type: integer, notnull: true}
date: {type: timestamp}
...
relations:
partner:
class: sfGuardUser
local: partner_id
foreign: id
type: one
client:
class: sfGuardUser
local: client_id
foreign: id
type: one
As per the above schema symfony has no other choice but to generate the select fields as:
select * from sf_guard_user;
The difference between partner and client is made by sfGuardGroup and sfGuardUserGroup, the related parts of the schema from ./plugins/sfDoctrineGuardPlugin/config/doctrine/schema.yml are:
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
...
sfGuardUser:
actAs: [Timestampable]
columns:
first_name: string(255)
last_name: string(255
...
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
...
What I would like to is to generate those fields with a query like:
select u.*
from sf_guard_user as u
JOIN (sf_guard_user_group as ug JOIN sf_guard_group as g
ON (ug.group_id = g.id)) ON (u.id = ug.user_id)
where g.name = 'partner';
I've researched for a way to edit the module's schema to reflect the relation between client_id and partner_id with their group name to get the filter form select fields right, but I've ended believing that that is a wrong approach
¿is it possible to modify the module's schema to allow symfony to populate correctly the select fields?
¿or that approach is completely wrong and instead I should hack the methods that render those fields to populate them with the right queries? If so hints in that direction would be appreciated.
Thanks
Just edit your form (probably sfGuardUserForm) and add the query to the partner_id widget. Something like:
$query = Doctrine::getTable('sfGuardUser')->createQuery('u')->etc etc...
$this->widgetSchema['partner_id']->setOption('query', $query)
You'll probably need to do the same to the validator for that field:
$this->validatorSchema['partner_id']->setOption('query', $query)
If you cannot edit that specific form (maybe it is used in another part of the app), just make a new one that extends it. And then, you just need to specify the form class in the generator.yml file.
I am creating a simple CMS and I have a set of templates, each template can have multiple blocks within them.
So I have a one-to-many relationship between the templates and blocks (1 template can have many blocks)
So, when I create a block, it has a drop down of the templates that I can associate the block to using sfDoctrineChoice widget.
In my BlockForm.class.php
new sfWidgetFormDoctrineChoice(array('model' => 'Template', 'multiple'=>true, 'expanded'=>false))
My schema is:
Template:
actAs:
Timestampable: ~
columns:
name:
type: varchar(255)
layout:
type: text
relations:
Block:
class: Block
local: id
foreign: template_id
type: many
foreignType: one
alias: Block
foreignAlias: Template
Block:
columns:
template_id: { type: integer(8), notnull: true }
content: { type: clob, notnull: true }
The problem comes when I try to save the choices. It gives me a:
SQLSTATE[HY093]: Invalid parameter number: number of bound variables does not match number of tokens when I select 2 or more templates or when I select 1 option:
SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails (db.block, CONSTRAINTblock_template_id_template_idFOREIGN KEY (template_id) REFERENCEStemplate(id))
Is my schema correct to do what I'm looking to do?
Thanks
Build the database tables the way you want them first.
Rename your old schema.yml to schema-20110610.yml
Run task symfony doctrine:build-schema
Take a look at the new schema.yml file you created. It may give you an idea of what you are doing wrong...
You must add foreign key constraint. onDelete and onUpdate.
Template:
actAs:
Timestampable: ~
columns:
name:
type: varchar(255)
layout:
type: text
Block:
columns:
template_id: { type: integer(8), notnull: true }
content: { type: clob, notnull: true }
relations:
Template:
local: template_id
foreign: id
foreignAlias: Blocks
Suppose I have defined VendorClientLicense model like this:
VendorClientLicense:
tableName: vendor_client_licenses
columns:
id:
type: integer(4)
primary: true
notnull: true
autoincrement: true
status:
type: string(255)
default: 'pending'
client_id:
type: integer(8)
notnull: true
vendor_id:
type: integer(8)
notnull: true
relations:
sfGuardUser:
class: sfGuardUser
local: client_id
foreign: id
foreignAlias: VendorClientLicenses
foreignType: many
owningSide: true
sfGuardUser:
class: sfGuardUser
local: vendor_id
foreign: id
foreignAlias: VendorClientLicenses
foreignType: many
owningSide: true
indexes:
fk_vendor_client_licenses_sf_guard_user1:
fields: [client_id]
fk_vendor_client_licenses_sf_guard_user2:
fields: [vendor_id]
options:
charset: utf8
collate: utf8_unicode_ci
If you see the two relations are defined with same name 'sfGuarduser'; What I have found for this in mysql is that in generated database client_id does not show any association with sfGuardUser, whereas vendor_id does! If I change it to 'sfGuardUser1' and 'sfGuardUser2' then shows both relationship! So I assume eventually this has important significance and should not be identical for a same model. Is there any other implications for it?
Plus can you name me a good schema generator like 'mysqlworkbenchdoctrineplugin' which handles situation like this automatically?
Yes, you need to name them differently.
I asked & received for the same problem here:
MySQL: Two foreign keys in one table referring to another table
I haven't had any problems with it.
Regarding the plugin, sorry can't help you.
I'm doing a blog engine in Symfony. Here's part of my schema :
Content:
connection: doctrine
tableName: ec_content
columns:
id:
type: integer(4)
fixed: false
unsigned: true
primary: true
autoincrement: true
(...)
relations:
Author:
local: author_id
foreign: id
type: one
State:
local: state_id
foreign: id
type: one
Type:
local: type_id
foreign: id
type: one
(...)
In the administration pages, I want to display the type of the articles, but symfony only shows the type_id, why is that ?
EDIT: here's my generator.yml : I haven't modified it much yet.
generator:
class: sfDoctrineGenerator
param:
model_class: Content
theme: admin
non_verbose_templates: true
with_show: false
singular: ~
plural: ~
route_prefix: content_Brouillons
with_doctrine_route: true
actions_base_class: sfActions
config:
actions: ~
fields: ~
list:
title: Brouillons
display: [Type, State, title, link]
filter: ~
form: ~
edit: ~
new: ~
OK.
In your generator.yml, on the display line, Symfony (via Doctrine) will look for a field name in your model class that corresponds to each field you want to display. If the field name doesn't exist, it will then look for a corresponding getFieldName() method and call that.
In your example, you have Type as a field name, which will be calling getType() - this will fetch the relation in. By default, Doctrine assumes that when you want to convert a model to a string (eg for display in your list), you want to use the primary key - in your case, the ID value.
To overcome this, add a __toString() method as follows, to your Doctrine lib/model/doctrine/EcType.class.php file:
class EcType extends BaseEcType
{
public function __toString()
{
return $this->type;
}
}
and you should see the 'type' field being displayed in your admin generated list.