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é !
Related
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.
I have a keys only query - something like this -
$Sub = $obj_store->fetchOne("SELECT key WHERE key HAS ANCESTOR KEY(Subscribe, $key)");
I set a value on one of the fields
$Sub->active = TRUE;
then do an upsert
$obj_store->upsert($Sub);
The one value is updated, but the other existing columns are erased. If I do a select * the values are not erased.
I need to avoid a full record read for billing.
How can I update a field in a record and avoid deleting all the others? I'm using the php-gds wrapper for cloud-datastore.
the desire would a query like the following
update subscribe set active = TRUE where keyid = 1234
Writes to Cloud Datastore assume that you are sending in a "whole" entity. You cannot update specific properties of an entity like you can in a relational database. Like you found out, correct way to update an entity is to first read the whole entity from the Datastore, then change one or more properties and then save.
I've just updated L4 (both skeleton and packages) to the latest version.
Now, when I try to create a new instance of one of the Models and save it to the DB, I get an empty record, except for the timestamps and the primary key.
This behaviour persists over all models (Users, Bids, Projects etc...) so It's not a local problem.
I tried both
Project::create($project);
and, following this thread:
$new_project = new Project;
$new_project->fill($project);
$new_project->save();
But the result is the same: an empty record.
So, as it turns out from the docs Mass assignment is now blocked by default for security reasons (e.g fetching all data from the form without specifying the fields (Input::all()) and saving it as is to the DB might result in unwanted fields being assigned, in case the client manipulates the form by adding a field with a name that corresponds to the field in the DB).
To designate the fields that are allowed to be assigned, one should either explicitly add the fields in question as a white-list to a protected $fillable array on the model, or alternatively, create a black-list using the $guarded array
i was facing the same problem and found solution hope help others
$new_project = new Project;
$new_project->unguard();
$new_project->create($project);
$new_project->reguard();
or
Project::unguard();
$new_project = Project::create($project);
$new_project->reguard();
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
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.