easiest way to fetch query to array of object in symfony - php

View in database I mean :
create view `vMaketType` as select * from MaketType
I have a view in database, but because of doctrine cant support it now, i using query, and fetch it one by one :
$em = $this->getDoctrine()->getManager();
$con = $this->getDoctrine()->getEntityManager()->getConnection();
$stmt = $con->executeQuery('SELECT * FROM vMaketType');
$domain = [];
//I must fetch it and set it one by one
foreach ($stmt->fetchAll() as $row){
$obj = new vMaketType();
$obj->setId($row["Id"]);
$obj->setName($row["Name"]);
$obj->setAmount($row["Amount"]);
array_push($domain, $obj);
}
for me this is really takes too much time to code one by one.
vMaketType is a custom entity I created to send data from controller to [Twig]view.
is there any easier way to fetch to array of object vMaketType?
because I have a view with 24 fields, I wish there is easier way for it.

Perhaps you can try with the serializer:
$obj = $this->get('serializer')->deserialize($row, 'Namespace\MaketType', 'array');
Code not tested, tweaks may be done, see the related doc.

Related

Can we remove some records from Active Data provider before passing to grid view?

I am facing issue with a scenario that I have to show data in two different grids present on same view. I don't want to query separately for both grids. What I want to achieve is to query only once and split data for both grids separately and pass it to both grids.
I have the option to hide rows on type basis but I don't want to use this
I have tried the option to hide rows on type basis but I don't want to use this option. I want something to split the main data provider into two data providers
The only way to do that with yii\data\ActiveDataProvider is extending it and overriding its prepareModels() and prepareKeys() methods.
Other option is to use yii\data\ArrayDataProvider instead.
//simple query just for illustration, modify it as you need
$all = MyModel::find()->all();
$first = $second = [];
foreach ($all as $item) {
// condition to decide where the current item belongs
if (someCondition) {
$first[] = $item;
} else {
$second[] = $item;
}
}
$firstProvider = new \yii\data\ArrayDataProvider([
'allModels' => $first,
]);
$secondProvider = new \yii\data\ArrayDataProvider([
'allModels' => $second,
]);
The main disadvantage of using ArrayDataProvider is, that you have to load all models into array even if you plan to use pagination. So if there are many rows in your table, it might be better to use two independent ActiveDataProvider and let them load the data in two queries.

On a Laravel 'update' function, how to parse a JSON object, and store it with a ForEach loop

I am using the Laravel framework to work with my MySQL database, and currently want to update my database from a JSON object, that will be sent from somewhere else.
Currently, I have it the same as my 'Store' function, which is obviously not going to work, because it will update everything, or refuse to work because it is missing information.
This is the for each I have currently, it does not work, but I am not experienced with how it is best to parse a JSON with a for-each, then store it.
public function update(Request $request,$student)
{
$storeData = User::find($student);
foreach ($request as $value) {
$storeData-> username = $value;
}
Here is my store function, with all the info that the front-end team may send in a JSON format.
$storeData->username=$request->input('username');
$storeData->password=$request->input('password');
$storeData->email=$request->input('email');
$storeData->location=$request->input('location');
$storeData->role=DB::table('users')->where('user_id', $student)->value('role');
$storeData->devotional_id=$request->input('devotional_id');
$storeData->gift_id=$request->input('gift_id');
$storeData->save();
return dd("Info Recieved");
You can write the method like the below snippet.
Also, assume you are working with laravel API, so you don't need to parse the incoming JSON input, but you will receive these values as items in the request object.
However, you should use the filled method in order to determine if the field is existing and has a value, the update function will override with empty values otherwise.
I just added this method to the first input, but you have to use it each and every input if you are not sure what the front end will pass.
public function update(Request $request, $student)
{
$storeData = User::find($student); // should be id
if ($request->filled('username')) { // use this for other items also
$storeData->username = $request->input('username');
}
$storeData->password = $request->input('password');
$storeData->email = $request->input('email');
$storeData->location = $request->input('location');
$storeData->role = DB::table('users')->where('user_id', $student)->value('role');
$storeData->devotional_id = $request->input('devotional_id');
$storeData->gift_id = $request->input('gift_id');
$storeData->update();
dd("Info Recieved");
}
Why would they send json data from the front in a post?
Really it would be from a form input. Like Rinto said it would be request object.
$user->username = $request->user_name;
I'm gathering this is a form on the front to create a new user. Why not use the built in auth scaffolding that has this set up for you in the register area?
So I'd personally use...
//look up user that matches the email or create a new user
$user = User::firstOrNew(['email' => request('email')]);
//add other input values here
$user->name = request('name');
//save
$user->save();
Hard to give an exact answer to this when the question is a bit vague in what you're doing. There are many methods in Laravel to accomplish things. From your code it just looks like registration. Also, the big gotcha I see in your code is you are passing a text only password and then adding that password in plain text to your database. That is a big security flaw.
you can convert your JSON object to an array and then do your foreach loop on the new array. To update a table in Laravel it's update ($storeData->update();) not save. Save is to insert.
$Arr = json_decode($request, true);

Symfony2/3: Is flushing a single entity/object possible? If not, how can I access objects persisted but not flushed after a foreach loop?

I know that in Doctrine (as a general rule) it is better to flush() after persisting all the entities/objects to the database, but in the following case I think it could be useful to do the opposite.
Example:
Imagine that you are cycling through a list of sport results like this one:
playerA_unique_tag (string), playerB_unique_tag (string), result
In the database, playerA and playerB are FOREIGN KEYS (that point to a User entity). So, the database structure would be similar to this one:
Match record
id, playerA_fk, playerB_fk, result
User records
id, playerA_unique_tag, (etc... many other fields)
id, playerB_unique_tag, (etc... many other fields)
Example of a script
$sportResultsArray = array();
foreach($sportResultsArray as $sportResult){
$playerA_tag = $sportResult["$playerA_unique_tag"];
$db_playerA = db->getRepository("App:User")->findOneByTag($playerA);
if(!$db_playerA){
$db_playerA = new User();
$db_playerA ->setPlayer_unique_tag($playerA_tag);
$em->persist($db_playerA );
}
$match = new Match();
$match ->setplayerA($db_playerA );
/*Same thing would be done for playerB*/
$em->persist($match );
}
Problem:
Of course playerA will play MULTIPLE matches, and each time I have to somehow retrieve the corresponding User object and pass it to the new Match object.
But how can I do that if I haven't flushed playerA User object yet.
The only two alternatives I can think of are:
1- Flushing the User entity (and ONLY the User entity) after it is created
2- Create a temporary array of objects like this:
array('playerA_unique_tag' => playerA_Object, etc.)
Problem with option_1:
I have tried $em->flush($db_playerA); but every entity that was persisted to the Entity Manager also gets flushed (contrary to what written here: http://www.doctrine-project.org/api/orm/2.5/source-class-Doctrine.ORM.EntityManager.html#338-359). Basically, the result is the same as $em->flush();
Problem with option_2:
Isn't it a bad and inefficient workaround?
Consider to work with in-memory registry of players as following:
// init registry
$players = [];
foreach ($sportResultsArray as $sportResult) {
$players[$sportResult["$playerA_unique_tag"]] = null;
$players[$sportResult["$playerB_unique_tag"]] = null;
}
// fetch all at once
$existing = $db->getRepository("App:User")->findBy(['tag' => array_keys($players)]);
// fill up the registry
foreach ($existing as $player) {
$players[$player->getTag()] = $player;
}
// match them up
foreach ($sportResultsArray as $sportResult) {
$playerA_tag = $sportResult["$playerA_unique_tag"];
if ($players[$playerA_tag] === null) {
$players[$playerA_tag] = new User();
$players[$playerA_tag]->setPlayer_unique_tag($playerA_tag);
$em->persist($players[$playerA_tag]);
}
$match = new Match();
$match->setplayerA($players[$playerA_tag]);
/*Same thing would be done for playerB*/
$em->persist($match);
}
// finally
$em->flush();

Object Oriented PHP: Loading data from DB to create objects?

I am new to OOP in PHP so here goes this "basic" question:
I have a table of customers:
Table 'customers'
id PRIMARY KEY
name VARCHAR 250
email VARCHAR 1000
is_active ENUM 'n','y'
In a script I need to select all the customers which are active (is_active == 'y') and send them a thank you email. There is a business class associated with the above table called class Customers.
I can write something very simple without using OOP:
$result = mysql_query("SELECT * FROM customers WHERE is_active = 'y'");
while($arr = mysql_fetch_assoc($result))
send this customer a thank you email...
If I were to use OOP, how do I do something as simple as the above? If there are thousands of customers, do I write OO code that loads thousands of customer objects to send each one an email as below?
$result = mysql_query("SELECT * FROM customers WHERE is_active = 'y');
while($arr = mysql_fetch_assoc($result))
$objCustomer = new Customer($arr['id']); //reload what has already been read from the db??
$objCustomer->sendThankYouEmail();
Am I doing something wrong (or silly) above?
I wouldn't reload it from the DB but rather from the array:
$objCustomer = new Customer($arr);
$objCustomer->sendThankYouEmail();
In your Customer object you load the data from the array.
Another way to do it is to do the following (object properties should match the field names):
while($objCustomer = mysql_fetch_object($result, 'Customer')) {
$objCustomer->sendThankYouEmail();
}
Note: If this is something new you are developing you should be using parametrized queries using MySQLI or PDO.
If you really like to work OOP try using Doctrine.
Doctrine 2 maps relational databases to objects.
You could say.
// obtaining the entity manager
$entityManager = EntityManager::create($conn, $config);
$customerRepository = $entityManager->getRepository('Customer');
$customers = $customerRepository->findAll();
forLoop(){
$customers[index]->email // To get the email and do whatever you want with the customer object.
}
With things like this you just have to try and see if it works for you.

Duplicate an AR record & re-insert this into the database

I have a AR model that I am trying to duplicated but just need to manually change the foreign key.
$_POST['competition_id'] = 99;
$prizes = CompetitionPrizes::model()->findAll('competition_id =:competition_id',array(':competition_id'=> $_POST['competition_id']));
This query basically queries the prizes table and gets all the rows for a particular competition. With the prizes object I would like to basically re-insert/duplicate the same information except the competition id which I want to manually set.
I did something similar for an AR object that basically only has one row and that worked well, however in this instance as a competition can have more than one prize this same code won't.
// My existing code for duplication process
$obj = Competitions::model()->find('competition_id=:competition_id', array(':competition_id' => $post['competition_id']));
$clone = clone $obj;
$clone->isNewRecord = true;
unset($clone->competition_id); // i want to remove this so it is auto inserted instead via the db
$clone->save();
This works great - how would I modify this on a 'collection' of prizes and have this duplicated into the database while setting my own 'competition_id' value.
Note - i'm to new to Yii, so please let me know if I have made any obvious errors/bad practice
Cloning won't work. You need to assign the attributes to a new object:
$obj = Competitions::model()->find('competition_id=:competition_id', array(':competition_id' => $post['competition_id']));
$clone = new Competitions;
$clone->attributes = $obj->attributes;
$clone->save();
If a more generic way of duplicating a Model / ActiveRecord in Yii2 Framework is required, you might use this solution:
$copy = clone $model;
$copy->isNewRecord = true;
foreach ($model->getPrimaryKey(true) as $field => $value) {
unset($copy->{$field});
}
$copy->save();
GitHub issue discussion about duplicate models: https://github.com/yiisoft/yii2/issues/7544#issuecomment-77158479
The answer for my problem although Michiel above helped me out - alternatively if you wouldn't mind adding another answer i'll give you the accepted answer.
foreach($models as $model)
{
$clone = new Competitions;
$clone->attributes = $model->attributes;
$clone->competition_id = '123' // custom var i am setting manually.
$clone->save();
}
How about (yii2 syntax):
$model=Competitions::findOne([':competition_id' => $post['competition_id']]);
$model->id = null;
$model->isNewRecord = true;
$model->save();

Categories