How create migration with exist data? - doctrine-orm

I have a table order with such fields id, name, email, order_id etc.
I want create new table user and transfer name, email data from order table and create relation oneToMany (user -> order) and add new column to order table user_id which relate to user table
I wrote migration script for a new table
class UserMigration implements Migration, RenameExtensionAwareInterface
{
/**
* #param Schema $schema
* #param QueryBag $queries
* #return void
*/
public function up(Schema $schema, QueryBag $queries)
{
$table = $schema->createTable('user');
$table->addColumn('id', 'integer', ['autoincrement' => true]);
$table->addColumn('name', 'string', ['length' => 65]);
$table->addColumn('email', 'string', ['notnull' => false, 'length' => 129]);
$table->addColumn('createdAt', 'datetime');
$table->setPrimaryKey(['id']);
}
}
But I can’t find information how to correct get data fromn exits table and insert into new and in table order add FK(user_id).
I used this doc https://github.com/orocrm/platform/tree/master/src/Oro/Bundle/MigrationBundle

if both user and order are your own entities - you should check doctrine documentation about migrations and fixtures,
if you'd like to create relation from magento order, you should use extend extension in your migration, see examples in other orocrm bundle's migrations.

Related

AdonisJs: create migration for existent database schema

I have an existent Postgresql database schema which I wrote in SQL. It initializes extensions, enum types, and defines many tables with foreign keys, constraints, indexes, etc.
Now I wish to build an AdonisJs app around that database. I would like new developers to be able to set up an empty database with the same schema, without having to run the SQL command in psql themselves.
I do not want to write all the schema using the Adonis schema builder DSL because there are many tables and it would take a lot of time to translate.
In ruby on Rails, the schema would be kept updated in the db/schema.rb file and new developers would spin up their dev environment using rails db:schema:load. What is the equivalent in AdonisJS?
The current way I'm doing it is by creating a migration that basically runs the raw SQL query. But I'm convinced there should be a cleaner way. Or even a way to get this SQL file away from my migration.
import Database from '#ioc:Adonis/Lucid/Database'
import BaseSchema from '#ioc:Adonis/Lucid/Schema'
export default class extends BaseSchema {
public async up () {
const schemaSql = this.initialSchema()
console.log(schemaSql)
await Database.rawQuery(schemaSql)
}
public async down () {
}
public initialSchema() {
const fs = require('fs');
const path = require('path');
var data = fs.readFileSync(path.resolve(__dirname, './../initial_schema.sql'));
return data.toString();
}
}
and then inside database/initial_schema.sql I have:
CREATE EXTENSION IF NOT EXISTS citext;
CREATE EXTENSION IF NOT EXISTS pgcrypto;
CREATE EXTENSION IF NOT EXISTS btree_gist;
DROP TYPE IF EXISTS nivel_formacion;
CREATE TYPE nivel_formacion AS ENUM ('secundaria', 'grado', 'maestria', 'doctorado');
CREATE TABLE "foobar" (
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid(),
"name" varchar NOT NULL,
"created_at" timestamp NOT NULL,
"updated_at" timestamp NOT NULL
);
-- ...etc etc etc..

dynamodb table tables design for multi user sharing applications

Sorry for the abstract title of the question but i will try to explain my intention in details in my question.
I want to create a reminders application in which each user has a separate login in the system but he/she can choose to share an item(in this case a reminder) with another user if he/she chooses. So when that user with whom the item is shared searches in his app he can also see the reminders which are shared with him.
So a user can have a reminder for only himself + a reminder which is shared with him.
This are my data access/retrieval patterns:
So when a user goes inside the application he should be able to see a list of reminders that he created and also the ones which are shared with him
From that list he should be able to search for a reminder by tag(i plan to do that outside dynamodb since the tag would be a set and not a scalar field hence i cannot have an index on that) and also should be able to search for a reminder by title
3.A user should be able to update or delete a reminder
4.A user should be able to create a reminder
5.Also the user should only be able to see future reminders and not the ones in which the expiration date is passed
The table and index creation that i have is created using the below create_table script :
import boto3
def create_reminders_table():
"""Just create the reminders table."""
session = boto3.session.Session(profile_name='dynamo_local')
dynamodb = session.resource('dynamodb', endpoint_url="http://localhost:8000")
table = dynamodb.create_table(
TableName='Reminders',
KeySchema=[
{
'AttributeName': 'reminder_id',
'KeyType': 'HASH'
}
],
AttributeDefinitions=[
{
'AttributeName': 'reminder_id',
'AttributeType': 'S'
},
{
'AttributeName': 'user_id',
'AttributeType': 'S'
},
{
'AttributeName': 'reminder_title_reminder_id',
'AttributeType': 'S'
}
],
GlobalSecondaryIndexes=[
{
'IndexName': 'UserTitleReminderIdGsi',
'KeySchema': [
{
'AttributeName': 'user_id',
'KeyType': 'HASH'
},
{
'AttributeName': 'reminder_title_reminder_id',
'KeyType': 'RANGE'
}
],
'Projection': {
'ProjectionType': 'INCLUDE',
'NonKeyAttributes': [
'reminder_expiration_date_time'
]
}
}
],
BillingMode='PAY_PER_REQUEST'
)
return table
if __name__ == '__main__':
movie_table = create_reminders_table()
print("Table status:", movie_table.table_status)
So the decision for the global secondary index us to allow a user to search for reminders with a reminder title.
Now to achieve the above case in which a user wants to also share his reminder with someone else i want to do the below change to my table schema . Basically i want to rename the user_id attribute to something like users_id which initially contains the user id of the user who created it but if that reminder is shared with someone then the user_id of the second user is also concatenated with the creator user id and the users_id column is modified .
If i do this i have 2 issues which i can think of:
How do i know the user_id of the user with whom the reminder is shared ? May be now i need to maintain a new table holding user information ? Or can i use some other service like amazon cognito for this?
If i still have the Global Secondary index on the users_id column when i need to search for reminders for a user the query needs to be like : select * from reminders where users_id startswith("Bob")( for example) .
Another option which i can think of(preferred way) is to drop the idea of creating a users_id attribute but instead of keeping the user_id column as is . I would the add the user_id as a sort key (RANGE) key to the table so that the combination of reminder_id and user_id is unique. Then when a user wants to share his created reminder with some other user a new entry is created inside the database with the same reminder_id and a new user id (which is the user id of the user with whom the reminder is shared)
Any help on my dilemma would be greatly appreciated.
Thanks in advance.
You don't mention your query access pattern in any detail, and with DynamoDB your data model flows from the query access pattern. So the below is based only on my imagination of what query patterns you might need. I could be off.
The PK can be the user_id. The SK can be the reminder_id of all reminders the user keeps. That lets you do a Query to get all reminders for a given user. The primary key then is the user id and reminder id in combination, so if you're passing around a reference, use that (not just the reminder_id).
A share gets added by putting another item under the user_id of the person getting shared with. That way a Query for that user can retrieve both their own reminders and those shared with them.
If you need people to list what reminders they've shared and with others, you can put that into the reminder itself as a list of who it's been shared with, if the list is short enough, or instead create a GSI on that share reference (against a shared_by attribute) if the list might be large.
If you need to query for a user's reminders and differentiate their own vs shared, you can prepend the SK with that so SHARED#reminder_id or SELF#reminder_id so a begins_with on the SK can differentiate.
You can refine this in various ways, but I think it would optimize for the "show me my reminders and the reminders shared with me" use cases, while making sharing (or undoing sharing) easy to implement.

Doctrine and ZF2

I am facing trouble using doctrine join. I can't share my code. But I can tell you scenario.
Please help me to achieve that.
I have created 2 entity. One User and Language.
User table is having foreign key language_id. and Language is master table with id and code fields.
I want to fetch user with some criteria, such a way it returns Language code from Language table as well.
I write join for that but it returns some full object...
Not sure how to fetch corresponding language code from Language table for language_id set in user table
If there is some example you know which can help me then also fine
i have return this in __construct()
$this->languageObj = new ArrayCollection();
when we print it is gives this
[languageObj:User:private] => Common\User\Entity\Language Object
(
[languageId:Language:private] => 1
[languageCode:Language:private] => en
[languageName:Language:private] => English
[languageCode2:Language:private] => User Object
RECURSION
)
I am not able to fetch languageCode from the object
You need methods defined in your entity to return the value from the object. It seems like everything is correct you would just need to grab the value from the entity. Here is an example:
$userEntity->getLanguageObj()->getLanguageId();
Your user Entity would need the getLanguageObj method which you can define like this:
public function getLanguageObj() {
return $this->languageObj;
}
And your Language Entity would also need a getLanguageId method:
public function getLanguageId() {
return $this->languageId;
}
Hope that helps!

Change/Define the saving end of a many-to-many relationship

I've got a many-to-many relationship in my Application between Users and Conversations
App.User = DS.Model.extend,
conversations: DS.hasMany('App.Conversation')
App.Conversation = DS.Model.extend
participants: DS.hasMany('App.User')
But every time i create and save a conversation, ember tries to save each participant including the ids of their related conversations. But i want the exact opposite of that, i want it to update just that one conversation and send the related participant_ids with it.
Is there a way to make that work?
What i tried so far:
specifying the inverse key on the user model (conversations: DS.hasMany('App.Conversation', inverse: 'participants'))
the workaround below.
.
App.RESTAdapter = DS.RESTAdapter.extend
serializer: DS.RESTSerializer.extend
addHasMany: (hash, record, key, relationship) ->
type = record.constructor
name = relationship.key
serializedHasMany = []
embeddedType = this.embeddedType(type, name)
return unless embeddedType is 'always'
record.get(name).forEach (record) ->
serializedHasMany.push record.get('id')
, #
hash[#singularize(key) + '_ids'] = serializedHasMany
App.RESTAdapter.map 'D4S.Conversation',
participants:
embedded: 'always'
After that it will save the conversation including the foreign keys but still tries to update the users, so i tried to save it with a custom request and just reset participant sates :/
App.Conversation._createWith = (participants) ->
conversation = #createRecord()
participants.forEach (p) ->
conversation.get('participants').addObject(p)
# conversation.save()
adapter = conversation.get('store._adapter')
adapter.ajax(adapter.buildURL('conversation'), 'POST',
data: { conversation: conversation.serialize() }
).then ->
conversation.setProperties(arguments[0].conversation)
conversation.get('stateManager').transitionTo('saved')
conversation.get('participants').forEach (user) ->
user.get('stateManager').transitionTo('saved')
conversation.trigger('didCommit')
conversation
Which finally worked \o/ But throw up the next error :(
Upon loading ember doesn't load the relationship, conversations participants property is always an empty DS.ManyArray
So is there a way to make that work?
Solution: Implement your own mapping key, don't use one thats already used.
This implementation solved all my problems:
serializer: DS.RESTSerializer.extend
###
Custom implementation to realize manySaving mapping
###
addHasMany: (hash, record, key, relationship) ->
#_super(hash, record, key, relationship)
type = record.constructor
name = relationship.key
serializedHasMany = []
manySaving = this.manySaving(type, name)
return unless manySaving
record.get(name).forEach (record) ->
serializedHasMany.push record.get('id')
, #
hash[key] = serializedHasMany
###
Check if manySaving option for a specific relationship is enabeld
#param {String} type The record type (usally a model class)
#param {String} name The attribute name of the relationship
#return {Boolean}
###
manySaving: (type, name) ->
this.mappingOption(type, name, 'manySaving')
D4S.RESTAdapter.map 'D4S.User',
conversations:
manySaving: false
D4S.RESTAdapter.map 'D4S.Conversation',
participants:
manySaving: true
key: 'participant_ids'

symfony 1.4 and propel - foreign constraints fails saved relation

I am working in a Symfony 1.4 project with Propel 1.4.2.
I have 2 related tables. workshop and trainers which is a many to many relation mapped by a join table (workshop_trainers) which contains the workshop_id and the trainer_id).
In my Workshop Form I have a select box for adding the trainers to the workshop. The problem is when the workshop is new (Create) I get an error:
Cannot add or update a child row: a foreign key constraint fails
This happens because, when saving the workshop_trainers relation the workshop_id field is null. Isn´t Propel intelligent enough to know that there is a relation between the tables and save the base object first? What I am doing wrong?
My trainer list widget.
$this->widgetSchema['workshop_trainer_list'] = new sfWidgetFormChoice(array(
'choices' => $trainers,
'multiple' => true,
));
Thanks for your help.
This is not fixing the problem but that's the easiest practical solution to this problem:
In the form, simply deactivate the workshop_trainer_list field if the object is a new one (doesn't have an ID yet).
Something like:
if ($this->getObject()->isNew())
{
$this->offsetUnset('workshop_trainer_list'); // not sure of that method name
}
A better solution is to update the doSave method to have the ID first, something like this:
protected function doSave($con = null)
{
$isNew = $this->getObject()->isNew();
if (null === $con)
{
$con = $this->getConnection();
}
// retrieve the value of workshop_trainer_list here and remove it from the form
$trainers = ...
$this->offsetUnset('workshop_trainer_list');
// save without it
parent::doSave($con);
// add it back
$this->getObject()->set...
// save
$this->getObject()->save($con);
}