I'm getting the wrong data when using doctrine in symfony - mysql

I'm trying to build a SQL query using doctrine. Here's my code snippet:
/**
* #Route("/db", name="user_skill_testing")
*/
public function dbTest()
{
//all skills for user
$userName = "Jelle";
$user = $this->getDoctrine()
->getRepository('AppBundle:User')
->findOneByFirstname($userName);
echo "userId: ".$user->getId()."<br />";
$userSkills = $this->getDoctrine()
->getRepository('AppBundle:Userskill')->findById($user->getId());
$proficiencies = array();
foreach ($userSkills as $userSkill) {
array_push($proficiencies, $userSkill);
echo $userSkill->getId();
echo "-";
echo $userSkill->getProficiency()->getId();
echo "<br />";
}
var_dump($userSkills);
$html = "<html><body>".$user->getFirstname()."<br /><br />"."</body></html>";
return new Response($html);
}
It returns the following webpage(screenshot):
When I look at the queries it ran...:
...and rerun them...:
...I get a very different result. :(
I have no idea why, can anyone help me out?
thank you!
Edit: using this code to build the query reproduces the same result.

The problem lies with your PK on UserSkill. When doctrine Hydrates, it will assume entities with the same primary key, are the same entity, ignoring rows with the same PK if one has already been hydrated.
Since your Userskill::$id is not unique, only the first one will be hydrated, subsequent rows with the same id, will get a reference to the same entity.
To solve this, you need to create a compound key, consisting of the id and the proficiencyId.
In you use-case though, this will make things unpractical. So I would just replace your manual id on Userskill with an actual one-to-many relation from Userto Userskill...

Having MySql generate the many-to-many relationship helped doctrine generate the correct entities.

Related

Doctrine and Mysql data migration during table structure change

There is Entities User and Company. Company has user_id.
Now table structure changes and next one user can represent many companies and vice versa (Many to Many eg One to Many - Many to One). This introduces CompanyRepresentative Entity in the middle with fields user_id, company_id and role. Companies user_id will be dropped with that change.
How to make data migration script for that situation? There must be CompanyRepresentative entry for each company present right now that connects same user and company that are connected right now.
Environment is symfony 4 application with Doctrine and Mysql.
Doctrine migrations have functions preUp and postUp. In preUp it is possible to select all needed data and in postUp this data can be inserted to correct places after database structure changes.
For example
public function preUp(Schema $schema)
{
parent::preUp($schema);
$query = "SELECT id, user_id FROM company";
$data = $this->connection->prepare($query);
$data->execute();
foreach ($data as $row) {
$userId = $row['id'];
$companyId = $row['user_id'];
$this->customSQL[] = "($userId, $companyId)";
}
}
public function up(Schema $schema)
{
//Change the schema
}
public function postUp(Schema $schema)
{
parent::postUp($schema);
$SQL = 'INSERT INTO company_rep (user_id, company_id) VALUES ' . implode(', ', $this->customSQL);
$this->connection->executeQuery($SQL);
}
You have to use DoctrineMigrationBundle to do this. look at the documentation here, you should get away with it.

mySQL query for building dynamically populated model

I have some code below which demonstrates a hard-coded example of what I would like to accomplish dynamically.
At a high level, I wish to do something like select * from view_data_$app_state and then get all of the data from that views table into my mustache templates dynamically.
The code I currently must use to group multiple rows of data for a specific column along with the views data is:
<?php
error_reporting(E_ALL);
class Example {
function __construct(){
try {
$this->db = new PDO('mysql:host=localhost;dbname=Example', 'root','drowssap');
}
catch (PDOException $e) {
print($e->getMessage());
die();
}
}
function __destruct(){
$this->db = null;
}
function string_to_array($links_string){
return explode(",", $links_string);
}
function get_view_data(){
$q = $this->db->prepare('select *, GROUP_CONCAT(`links`) as "links" from `view_data_global` ');
$q->execute();
$result = $q->fetchAll(PDO::FETCH_ASSOC);
return $result;
}
}
$Example = new Example();
$result = $Example->get_view_data();
$result[0]["links"] = $Example->string_to_array($result[0]["links"]);
echo json_encode($result);
This gives me the perfect object while
GROUP_CONCAT seems to be doing the trick this way, however I MUST know the column name that will contain multiple rows before writing the query. I am trying to figure out an approach for this and wish to make a custom query + code example that will transform cols with multiple rows of null null and not empty data into an array like above - but return the data.. again like the code above.
Below is an output of the actual data:
[{"id":"1","title":"This is the title test","links":["main","about","store"]}];
How can I replicate this process dynamically on each view table?
Thank you so much SO!
You can use PDOStatement::fetch to retrieve your results, with fetch_style set to PDO::FETCH_ASSOC (some other values will also provide the same information). In this case, the result set will be array indexed by column name. You can access this information with foreach (array_expression as $key => $value)
See the documentation for additional information.

Yii2 - Connect to database inside Controller Action

Greetings,
Facts:
Database named -> acastro
Table called -> contacto
Fields in table are -> id, nome, email
I making an Yii2 application, and need to connect a highcharts chart to a table field in my database.
How can i inside an action called actionAdmin connect to my database and then count the number of id's in my Contacto table stored inside acastro database.
In the old Yii1.xx i used to establish connection this way:
public function actionAdmin() {
$sql = Yii::app()->db->createCommand('
SELECT count(*) as total
FROM contacto
')->queryAll();
$total = array();
for ($i = 0; $i < sizeof($sql); $i++){
$total[] = (int) $sql[$i]["total"];
}
$this->render('admin', array('total' => $total));
}
}
The problem is that this syntax no longer works in Yii2, and i've tried the sintaxe explained in Yii2 api guide but it always give's me error of undefined variable. Here is the code that i'm using to connect acording to Yii2 api guide:
use yii\db\Command;
$total = $connection->createCommand('SELECT count (*) FROM contacto')->queryAll();
What am i doing wrong ? Any solutions ?
Many thanks in advance.
I am not very sure that it will solve ur problem.
But in yii2 this the syntax
use app\models\Contacto; //look your Contacto Model namespace
$query = (new Query())->from('contacto');
$count = $query->count('column_name');
I hope this will help
The easiest syntax in Yii2 is:
$count=(new \yii\db\Query)->from('TBL_NAME')->count('*');
It just returns the count. For example: 500

Translate an SQL query using ISNULL into Datamapper ORM for Codeigniter

I have 3 mySQL tables: user, section and user_section (a joining table).
The SQL below:
SELECT id, description,
NOT ISNULL(
(SELECT user_id
FROM user_section
WHERE user_section.section_id = section.id
AND user_id=5)) AS user_in_section
FROM section
WHERE site_id = 3
nicely produces the following results:
id description user_in_section
3 section1 1
8 section2 0
9 section3 1
I have a form in my view to edit users and the sections they belong to. I'm writing the checkboxes out like so ($user_sections contains the above data):
<div class="checkboxes">
<?php foreach ($users_sections as $row) { ?>
<label class="checkbox"><input <?= ($row->checked>0?'checked':'') ?> type="checkbox" name="section[]" value="<?= $row->id ?>" /> <?= $row->description ?></label></br>
<?php } ?>
</div>
My questions are:
Is there a better way to write the sql query? Or is what I have good / the only way to get the data I want?
I want to use Datamapper ORM to write the query. I have this so far...
$section
->select('sections.id, description')
->select_func('NOT ISNULL', array('(SELECT id FROM sections_site_users where sections_site_users.site_section_id=sections.id and sections_site_users.site_user_id='.$user_id.')'), 'checked')
->where('site_id', $site_id)
->get();
The NOT before the ISNULL is being escaped with single quotes preventing the query from being correct sql. How can I write this properly in Datamapper?
Any suggestions for improvement greatly appreciated. Thanks in advance.
EDIT:
I have found a solution that works - here is my Datamapper code:
$sections = new Section();
$sections
->where('site_id', $site_id)
->get();
foreach ($sections as $s)
{
$s2 = new Section();
$s2
->where('id', $s->id)
->where_related('user', 'id', $user_id)
->get();
$s->checked = ($s2->exists() ? 1 : 0);
}
which produces the same data as the sql at the top of my answer. It does however use more database queries (I was hoping to do it in one database query).
Can anyone confirm for me that I've done the best thing here?
Thanks!
Yes! Simply:
$user = new User();
$sections = $user->section->where('id', $site_id)->get_iterated();
foreach($sections as $section)
{
// $section->id
// $section->description
}
But you have to set your relation properly!
ie:
Class user:
public $has_many = array('section);
Class section:
public $has_many = array('user');
Join table should be : users_sections
User table : users
section table : sections
Edit:
You want the section that have a specific user for a given site. You have a n relationship between sites and users. So you'll end loading the User first, then get his section:
$user = new User($user_id);
if ($user->result_count())
{
$sections = $user->section->where_related_site('id', $site_id)->get_iterated();
}
This should be fine. Sorry I didn't understand all at first.
A short description of your model would have help :)

Adding 2 drop lists to associated table

I am having an issue trying to add the records using 2 drop lists.
I have a table called Urls which holds the details of url. I have a table called category populates a drop list, I have another table called publishers which populates another drop list.
$query = 'INSERT INTO url_associations (url_id, url_category_id, approved, url_publisher_id) VALUES ';
foreach ($_POST['types'] as $v){
$query .= "($uid, $v, 'Y', $k), ";
}
$query = substr ($query, 0, -2); // Chop off the last comma and space.
$result = #mysql_query ($query); // Run the query.
if (mysql_affected_rows() == count($_POST['types'])) { // Query ran OK.
echo '<p><b>Thank you for your submission!</b></p>';
$_POST = array(); // Reset values.
} else { // If second query did not run OK.
The code above allows me to addd data using the categories drop list but when I try to add the url_publisher_id as 'posters' as $k I keep getting errors in my parsing. If anyone can understand what I am trying to achieve your help would be welcomed
If the value of your $k variable is anything other than an integer or float you'll get an error because it needs quotes around it when you're building the SQL INSERT statement:
$query .= "($uid, $v, 'Y', '$k'), ";
Note: There are some major security problems in your example. If you put user input from $_POST into your SQL without escaping it you're giving the user the ability to run whatever SQL commands they want to run on your database.
I have added an extra array foreach ($_POST[posters] as $k)
//so it reads
'foreach ($_POST[types] as $v)
foreach ($_POST[posters] as $k) {`
and it has executed perfectly.
Thanks for your help.
Sean