DBIx::Class resultset creating related data without the select - dbix-class

I'm trying to do something akin to this:
$schema->resultset('Foo')->create({ Property => 1,
Bar => {
Property => 'non-unique',
},
});
Where Bar is a belongs_to relation to another table, Bar, with an auto-incrementing primary key.
Problem is that behind the scenes, dbix is always doing a select and finding an existing row in Bar with Property = 'non-unique', and inserting that row's PK into Foo. What I'd like it to do instead is create a new row in Bar each time with a new auto-generated primary key.
Is there a way to tell DBIx not to search for a matching related row first, but to force it to always create the related row?

create_related() or new_reated()
The latter creates the related object, the former creates the object and saves it in the DB.
So, given an Foo->Bar relationship called 'bars', more like:
$foo = $schema->resultset('Foo')->create({ Property => 1 });
$bardata = {Property => 'non-unique'};
$foo->create_related('bars', $bardata);

Related

How to create a lookup in CakePHP

I'm in the process of converting a 10 year old PHP application. After my boss hired a php consultant, he has set up a CakePHP application environment and we are learning as we go. (fun, I know). Also, I come from a javascript/sharepoint background and have not had a lot of php experience.
As a test, I created a basic address table with these fields: firstname, lastname, state, phonenumber. I've been using justice league members as names and other test data to populate my table. Baked it just fine, default bootstrap pages are working.
I decided I wanted to add a dropdown field called current status, and for now just to keep it simple I wanted the choices: alive, dead.I created the column in my address table.
I created a second table called statuses and pointed the status column in my first table to the status table, using the status id as the foriegn key.
Baked my new table and rebaked my old one.
The status drop down does not give my choices of dead or alive, If I click in the field I get an up or down arrow, and based on which one you click, it either increments or decrements by 1. So the first time I click it inserts a 0. If I go up or down, it adds or takes away one.
I'm not sure what I'm doing wrong, I'm guessing there is some additional code I need to add to the MVC?
ok, if this works, then a lot is working :-). Now to the following: set in the Status Model a query like this:
public function getStatus()
{
$opt = $this->Status->find('list', array(...));
return $opt;
}
Then get the list over to the Adress Controller like this:
$this->loadModel('Status');
$opt => $this->Status->getStatus();
$this->set('opt', $opt);
Now you are able to access the $opt in the view file.
Just delete this line in the view:
$opts = array('0' => __('dead'), '1' => __('alive'));
And it should work.
Keep it simple. Ad to your table this row (only to understand how it works): 'status' as typ "tinyint(1)". Then set this in your view file:
$opts = array('0' => __('dead'), '1' => __('alive'));
When you create the inputfield, do it like that:
echo $this->Form->input('Address.status', array('options' => $opts, 'label'
=> __('Status')));
This should work.

How to apply a condition to a specific table in every request on Entity Framework?

I have a many-to-many structure mapped to entity framework. This is a sample of what it looks like:
User UserTag Tag
------- -------- -------
IdUser(PK) IdUserTag(PK) IdTag(PK)
Name IdUser(FK) TagName
Desc IdTag(FK) Active
Now, I needed to exclude from any request of any method the viewing of Tags that were Active=false.
First, I tried doing it manually in every method, like:
public User GetById(int id)
{
var item = UserRepository.GetById(id); //This is just a repository that calls the EF context
//EF automatically maps it to the *UserTags* property
foreach(var tag in item.UserTags)
{
if(tag.Tag.Active == false)
item.UserTags.Remove(tag);
}
}
But it throws the following exception:
The relationship could not be changed because one or more of the foreign-key properties is non-nullable
So, I wanted to know if there's a way to conditionaly filter every request made to a specific table, whether it is select or a join request.
Try this in your GetById method:
var user.UserTags = dbContext.Entry(user)
.Collection(u => u.UserTags)
.Query()
.Where(ut => ut.Active == true)
.ToList();
The supplied code fails because it is attempting to remove items from the data entities not the list. If you want to pass the data entity around instead of the data model, you need to not use Remove. Something like the below (untested should work).
tags = item.UserTags.Where((ut) => ut.Active).ToList();
This line will get you a list of data entities that are active. However, you should really map all of this into a data model (see AutoMapper) and then you would not be removing items from the database.

How to get Entry Id for a Newly Created Entity in Breeze

i want to create a registration form that will be in batch with a continuation button, getting the id of the entry will help me to call the save method.
I want to immediately get the primary key of a new Entry Created using BreezeJS, Pls i need help on this.
Thanks
Not entirely sure I understand your question, but it sounds like you want to get the id of a newly saved record immediately after the save. If so then the answer below applies.
When the save promise resolves it returns both the list of saved entities as well as a keyMappings array for any entities whose ids changed as a result of the save. i.e. a mapping from temporary to real ids. i.e. (Documented here: http://www.breezejs.com/sites/all/apidocs/classes/EntityManager.html#method_saveChanges)
myEntityManager.saveChanges().then(function (saveResult) {
// entities is an array of entities that were just saved.
var entitites = saveResult.entities;
var keyMappings = saveResult.keyMappings;
keyMappings.forEach(function(km) {
var tempId = km.tempValue;
var newId = km.realValue;
});
});
On the other hand if you have an entity and you just want its 'key' you can use the EntityAspect.getKey method. (see http://www.breezejs.com/sites/all/apidocs/classes/EntityAspect.html#method_getKey)
// assume order is an order entity attached to an EntityManager.
var entityKey = order.entityAspect.getKey();

MVCGrid w/Expander (parent) invoking an MVC Form(child) and loading child record - UPDATED

My multi-level MVCGrid/MVCForm/MVCGrid saga continues....
I am using nested MVCGrids with expander buttons that invoke MVCForms to perform different data operations. ALL mySQL tables in this process have an "id" data element and that is the primary key for each table. Each mySQL table also has a point to its parent when necessary using _id naming convention. All of the foreign-keys have been setup in mySQL to work this way as well.
The model for the parent is like this:
class Model_uidcontrol extends Model_Table {
public $entity_code='uidcontrol';
public $table_alias='uc';
function init(){
parent::init();
The model for the child is like this:
class Model_uiddetails extends Model_Table {
public $entity_code='uiddetails';
public $table_alias='ud';
function init(){
parent::init();
Each model has its own "id" and a pointer to its parent.
The expander column in the MVCGrid (parent) invokes this child function:
$um=$this->add('MVCForm');
$um->setModel('uiddetails')
->loadData(($_GET['uidcontrol_id']));
I have tried this in the child model:
$this->addRelatedEntity('uc','uidcontrol','uidcontrol_ID');
and this as well:
$this->addField('uidcontrol_id')
->refModel('Model_uidcontrol')
->caption('System Info')
->visible(true);
I've tried each technique separately and together to get child records to be coordinated with the proper parent.
debug() shows this
where
ud.id = '121'
ud.uidcontrol_id = '121'
OK, I understand the $GET and how it works and how that relates to dsql - at least I think I do.
What I can't figure out is how to tell MVCForm to use "ud.uidcontrol_id = '121 " that come
via the $GET when building the dsql for data loading and not use 'ud.id'
In the above example, there is a parent record "uidcontrol" with that id. I forced the 'id' of the child record to be 121 to see if it would pull data and display it in the form. OK, data displays as it should.
When I try this parent whose 'id' = 10, debug() produces this
ud.id = '10'
ud.uidcontrol_id = '10'
and no data is returned. There is a uidcontrol record with id = 10 but the dsql is trying to match to ud.id = 10 as well.
I can post more of what I am working to clarify what I am trying to do if that helps.
Ideally, I would like to tell MVCForm "Hey! Don't use the 'id' data element when building the dsql, use the one I am supplying instead. Problem is, I can't figure out how to do that... but I've learned a bunch along the way. Me thinks that I am probably "over thinking" something here.
Thanks for any suggestions!
Monday Feb 6th Notes:
var_dump($_GET); says:
'id' => string '10' (length=2) <=== uidcontrol.id
'uidcontrol_id' => string '10' (length=2) <=== uidcontrol.id
I write this:
$um->setModel('uiddetails')
->addCondition('uidcontrol_id',($_GET['id']))
->loadData(($_GET['id']));
And the SQL debug shows this being built:
where
ud.id = '10'
ud.uidcontrol_id = '10'
The issue is that I want ONLY " ud.uidcontrol_id = '10' ". Table uiddetails has its own id of 125 and a uidcontrol_id value of 10. As a result of that, the query doesn't return a record.
The loadData method only loads records by their id. To link the "child" model through his referenced record you must use setMasterField or addCondition to instruct the model to filter on the relationship.

how to display the data returned by get_by_user_id() in DataMapper Code Igniter?

I am new to code igniter data mapper. I have a table called user, and I am trying to retrieve data from the database table and show them to the user.
Here is what I have in the model:
$u=new User();
$results=$u->get_by_user_id($id);
//$results here will be set to huge bunch of none sense data( which also includes the row that I am looking for as well)
if ($u->exists())
{
foreach ($results->all as $row){
$data['user']['first_name']=($row->user_first); //this where I am stuck ..
$data['user']['last_name']=($row->user_last);//this is also where I am stuck..
}
I don't know how to treat results to get a required fields I am looking for and store them in the $data I am passing to the user to view.
Thanks!
When you call get_by_x() on the model, the fields will be populated with data and you can access them like this:
$u = new User();
$u->get_by_user_id($id);
if($u->exists())
{
// you can access the table columns as object fields
$data['user']['first'] = $u->first;
$data['user']['last'] = $u->last;
}
else
{
$data['error'] = 'No such user!';
}
Have a look at the documentation which is really helpful: see Get and Get By.
Also, DataMapper expects all tables to have an id column: see Table Naming Rules. If your column is named id you should then call $u->get_by_id($id) instead of $u->get_by_user_id($id).

Resources