Inserting into joined tables in CodeIgniter - php

I just got a joined table set up and running in CodeIgniter; I am retrieving data from the DB very easily using ActiveRecord. The next obstacle though, seems like the hardest: I am new to joins and I have no idea how I'm going to insert data into my joined tables. The data should go in looking the same as it comes out (meaning actual data, not row ids) but short of hard-coding arrays of associations and transforming the data before save, I don't know how I'm going to do that. But there has to be a way, right?
Right?

I actually don't know CodeIgniter, but I can imagine how it should work based on other PHP ORMs.
$something = new ModelObject();
$something->setSomeProperty($someVal);
$something->save();
$related = new RelatedObject();
$related->setModelId($something->getId());
$related->save();
In other words, once you create the object represented by one table, that object's property corresponding to the generated identifier is populated for you. Now you can use it when you create an object in the related ("join") table to set the foreign key property before saving.

Related

Query relationship table with column that its data is an parsed array(1,2,3,4,5,6)

I have a string column in the table that have this kind of data // 1,2,3,4,5,6 comma separated data, supposedly this id has equivalent value to the another table.
I have the solution that I can get the data of the mentioned ids but its a bit mess. This is the step that I have solution
Get all data first
Loop all the data
Convert the column that has comma separated data to array
Loop the converted column
Query to another table
And save the query data
Is there an easy way to achieve this via eloquent query?
Thanks
I don't know what are the situation but you can convert the table column into a n * m relationship. I mean that if you have an "array" that it's identifying another table with multiple values it possible that the best BD structure was a new pivot table to relate the two already existing.
For new pivot table in a similar problem see: https://stackoverflow.com/a/58706027/7702532
For subquerying a new table in a similar problem see: https://stackoverflow.com/a/58706063/7702532
If you can't create a new table and the subquery option is not available for your version you can use accessor & mutators for the model attribute to mutate it and do not do a query on a loop of all results from the first query. https://laravel.com/docs/8.x/eloquent-mutators#accessors-and-mutators
I'm thinking on two options for you, I have not all the data of the problem but I'm trying to help ;D :
In the mutator you can call the other table and return the correct value but its very expensive for your server because all item of the first query you are doing another new query.
Another option are return the well formed array in the mutator. After getting the first query values, merge all the arrays of your attribute and make a unique query to your second table. This option need a loop to the results of the first table to assign the correct values filtering the second query results.
The first option is more easy to code but it's more expensive on memory and computation. The second one can be a little bit hard to code but is a good solution if you can't change the database structure or do correctly the subqueries.
In other hand I think that you can do a custom relationship or find a community contribution.

Create table if not exists is costy?

I`m creating a simple data mapping system with PHP, PDO and Mysql.
One of its premises is to map arrays to entities by creating tertiary tables (not sure if the name is correct).
So, when I map an Array, I create the table with a works-for-all statement that uses the class name and method name passed, something like this:
"create table if not exists ".$tablename." (id_".$firstName." int unsigned not null, ".$secondName." ".$type.", constraint fk_".$tablename." foreign key (id_".$firstName.") references ".$firstName."(id) ".$secondReference.");"
The code is not the problem here.
What I wanted to know is if its a bad idea to TRY to create a table (if not exists) in every iteration (it does only create it for real in the first iteration of each element).
EDIT (explaining): As stated, creating inumerous tables is not the worry (wont happen), for this process is automated according to the classes (models) I`m using. The worry is if it is too costy memory and trafic-wise to check if the table exists at every iteration (this way for each item I would access the database twice, once for checking if the table exists and then again for inserting the new element into the table).
Another option would be to check if the table exists trough a select statement first, but it doesn`t seem much better.
One important information is that these methods used for mapping will olny be accessed through the objects DAO referencing each entity.
Edit: The link for the GitHub with the project is https://github.com/Sirsirious/SPDMap
to me it doesn't sound ideal to create a table each time. Might be better to reuse the same table (with an additional column as identifier between your current 'tables'
if you do create the table, don't see anything wrong with create table if not exist. this is a safe and good programming
I'd also consider using temp tables for this thing. if you create the table each time, it sounds like they are one-time usage as well. so if you don't need the data forever, temp can be a good way to go

Read from one database and write to another php/laravel

I'm learning Laravel and would know howto read data from a db and write it automatically to a second db.
First I read from db1 and it works:
$paciente_q = Pacientes::on('db1')->find($id);
Then I wish to move the data to an identical table on db2 (assigned in the configuration)
Pacientes::create($paciente_q);
The error is that I pass an object and "::create" wants an array. I converted it to an array but didn't work. The only option that I can find is to create an array with the data and then make the ::create. But I think that there should be an easier way. I'm talking about 10 columns.
What could I do if we talk about hundreds of columns?
Your approach didn't work probably because by default mass assignment is prevented for security reasons; you need to manually set the model's fields that are mass assignable in the fillable property of the model (that should be an array) - if you do not care about that security or are sure that you'll never directly mass-assign user input to your models you can make all the fields mass assignable by setting the guarded property of the model to an empty array.
Once that's done, your code is mostly correct, just convert the model to an array and don't forget to select the second database when creating the model, like so :
// the model to insert, converted to an array - get() would also work but first() ensures we get only one record even if the primary key is messed up and there are multiple values with the same ID
$paciente_q = Pacientes::on("db1")->find($id)->first()->toArray();
// create the same model on the second database
Pacientes::on("db2")->create($paciente_q);
Now, if you want to do it occasionally for a few rows then the above approach is suitable, otherwise you may look at bulk insertion, here's an example for copying the entire table from your first database to the second one :
// an array with all the rows
$patients = Pacientes::on("db1")->all()->toArray();
// get the model's table name
$table = with(new Pacientes)->getTable();
// bulk insert all these rows into the second database
DB::connection("db2")->table($table)->insert($patients);
Note that here we're not using Eloquent for inserting them, so we must first get the table's name from an instance of the model; if the table's name on the second database is different from the first then adjust the $table variable accordingly.
The solution was to change the get() to first() because we were searching for one item. I read wrong the first solution from #André... sorry! Should learn to read instead of Laravel!
$paciente_q = Pacientes::on('db1')->where('numerohistoria',$numerohistoria)->first()->toArray();
Pacientes::create($paciente_q);
Now it works!! Thanks to all and specially to #André !

What Database model should I use to store this data format?

I basically have a bunch of objects with the fields;
a string identifier of this object instance id : "banana"
a dictionary of string keys and values data : {}
an array of ids of instances related to this one friends: ["apple", "orange" ]
an array of related (in a different way) instance ids. followers: ["grapefuit"]
You may have deduced this data will model a Twitter network.
Over the life of my data (which will extend beyond the life of any particular program execution), the number of instances and the data stored in the fields will change (expectedly grow), so I would like to store all this data in a MySQL database to be interfaced by a PHP script.
I'm a complete rookie in the world of databases, but I somewhat understand the table model and query structure.
How should I structure the database for this particular problem?
In working with a MySQL-like database, one thing to remember is that you should avoid having things like dicts and arrays in a particular column. The reason is that this makes querying on these values horrible.
What I would do is have, for example, a "Friends" schema with two columns, FriendA and FriendB. For every friend pair you have, this will be a row in this database. You can do the same with with "Followers", have a Follower and a Followee column.
Now querying across these tables just requires a join, and more importantly if two friends get unfriended or someone decides to unfollow someone else, this is just one delete instead of two (and no arrays!)
And of course, unless you're planning on having unstructured key/value data, expand that to a full schema.

Storing and retrieving a serialized array in a Symfony2 form

In my database there is a table, which has a column of the type text. This column holds a serialized array. This array is read and stored by another application, and I cannot change its format.
The serialized array holds a selection of database names, table names and column names in two different languages.
I would like to write a controller, entity, form, etc. in Symfony2 that is able to modify this serialized array.
There is a script that I can use that can provide an array of all possible db names, table names and column names that each serialized array may contain.
The goal is to present a list of check boxes where users can select db's, tables and columns. Next, they can do a translation of the names.
Since all data is so volatile, I am not sure whether this is even possible in Symfony2.
An alternative is to make the following entities: { database, table, column } and do it fully OO. And then I could export a selection in a serialized array, to the external application that expects it that way...
Can you guys follow my reasoning? Am I overlooking a strategy here...?
Added:
The array is a nested array up to the fifth degree. Databases contain tables, which contain columns. And every item has an original name and a translated name.
I think you answered your own guestion:
An alternative is to make the following entities: { database, table, column } and do it fully OO.
And then I could export a selection in a serialized array, to the external application that
expects it that way...
You would start with a master entity mapped to your table.
class SomeEntity
{
protected $serializedInfo;
public getDatabases()
{
// Process serializedInfo into an array of database objects and return
You then pass SomeEntity to SomeEntityFormType which in turn uses a collection of DatabaseFormTypes. The DatabaseFormType then has a collection of TableFormTypes and so on.
Eventually your form would be posted and SomeEntity would be updated. You then serialize before posting. Should be straight forward. Might be a bit more challenging if you want users to add information but even then it is doable.
I know it's really late but I was really busy with university so I couldn't answer sooner
This is what I think is the best to do
Imagine that the table that contains the column which contains your array is called foo
So you make an entity which is called Foo and contains a field(type text) that has the name you like
Now the tricky part is to make an object called Database that contains all the relations you need(To a Table object and Table objects to column Objects)
So even though I told you to make the field type as text you will pas the object Database to this field
So how it's going to work
The Database object will have a __string method that will return the serialized array of the object the way you want
This way when doctrine2 tries to save the Database object in the text field it will be saved as the string that __string method returns
And you will have getDatabase that will converts the serialized array to the database object
This is the idea that I have and not sure if it suits you or not

Categories