Symfony - Doctrine - Cannot store a blob file in Oracle database - symfony

I want to store uploaded files in Oracle database .
I'm using Doctrine in Symfony 5.
I made an entity "Attachment", with a property "filename" (type string) and "filecontent" (type blob).
The following code is in controller, to get files uploaded, transform file content in stream, and store it in database
$attachments = $form->get('attachments')->getData();
if (count($attachments) > 0) {
foreach ($attachments as $attachment) {
$attach = new Attachment();
$attach->setFilename($attachment->getClientOriginalName());
$strm = fopen($attachment->getRealPath(), 'rb');
$attach->setFilecontent(stream_get_contents($strm));
$em->persist($attach);
}
}
When i submit the form, i have the error :
Warning: PDOStatement::execute(): supplied argument is not a valid stream resource
On a MySQL database, all is allright. File is correctly stored in database, no "stream ressource" issue.
I've found an old workaround here : https://groups.google.com/g/doctrine-user/c/JILLBji__MU but maybe there is a final solution to this problem.
Could you help me ?
Thanks

Oracle and doctrine have not a good compatibility.
So I do it in php and native SQL to do the trick
More information here:
https://www.php.net/manual/en/pdo.lobs.php
In your repository, it's looks like this :
$conn = $this->getEntityManager()->getConnection();
// Get Next Sequence
$sqlSeq = "SELECT DOCUMENT_FILE_id_seq.nextval FROM DUAL";
$stmtSeq = $conn->prepare($sqlSeq);
$stmtSeq->execute();
$nextId = (int)$stmtSeq->fetchFirstColumn()[0];
$fp = fopen($attachment->getRealPath(), 'rb');
// Insert file
$sql = "INSERT INTO DOCUMENT_FILE (id, file_content) VALUES (?,EMPTY_BLOB()) RETURNING file_content INTO ?";
$stmt = $conn->prepare($sql);
$stmt->bindParam(1, $nextId, \PDO::PARAM_INT);
$stmt->bindParam(2, $fp, \PDO::PARAM_LOB);
$conn->beginTransaction();
$stmt->execute();
$conn->commit();
That work for me.

Related

Symfony / Doctrine findBy

Hove to create custom Repository function who query by json field. I have params column in my database who look like this:
"params": {
"product": "stopper",
"itemIdentifier": ""
}
I want to query record by product value. In this case stopper term.
You can achieve this with a classic example :
In your repository :
For one result
public function findOneProduct($value): ?Params
{
return $this->createQueryBuilder('p')
->andWhere('p.product = :val')
->setParameter('val', $value)
->getQuery()
->getOneOrNullResult()
;
}
For multiple result
public function findParamsByProduct($value): ?Params
{
return $this->createQueryBuilder('p')
->andWhere('p.product = :val')
->setParameter('val', $value)
->orderBy(/*some field */)
->setMaxResults(/*if needed*/)
->getQuery()
->getResults()
;
}
In your controller:
$stoppers = $entityManager->getRepository(Params::class)->findParamsByProduct('stopper');
If I understood your question correctly, you have a table with a column named params. And inside this mysql column, you store JSON text.
And then you want to query that table and filter by looking into the JSON in your column.
This can be a bit tedious and was also highly discouraged in the past (prior to the JSON Type in Mysql 5.7.8).
Best practices would be to have a NoSQL DB such as MongoDB which is actual JSON stored in a collection(table).
Anyways, there is a solution for you.
Taking into account #AppyGG explained how to make a custom repository function.
First of all, we have to make a query using pure SQL.
It can be done two ways:
1.Return arrays containing your data.
$conn = $this->getEntityManager()->getConnection();
$sql = '
SELECT * FROM product p
WHERE p.price > :price
ORDER BY p.price ASC
';
$stmt = $conn->prepare($sql);
$stmt->execute(['price' => $price]);
// returns an array of arrays (i.e. a raw data set)
return $stmt->fetchAll();
2.Return hydrated Entities
use Doctrine\ORM\Query\ResultSetMappingBuilder;
$rsm = new ResultSetMappingBuilder($entityManager);
$rsm->addRootEntityFromClassMetadata('MyProject\Product', 'p');
$sql = '
SELECT * FROM product p
WHERE p.price > :price
ORDER BY p.price ASC
';
$nql = $this->_em->createNativeQuery( $sql, $rsm );
$nql->setParameter('price', $price);
//Return loaded entities
return $nql->getResult();
Now, knowing how to make make a MySQL query with doctrine, we want to select results filtered in JSON data.
I'm am referencing this beautiful stackoverflow which explains it all:
How to search JSON data in MySQL?
The easiest solution proposed in there requires at least MySQL 5.7.8
Your MySQL query would be as follow:
//With $entity->getParams() == '{"params": {"product":"stopper", "itemIdentifier":""}}'
$conn = $this->getEntityManager()->getConnection();
$sql = '
SELECT * FROM Entity e
WHERE JSON_EXTRACT(e.params, "$.params.product") = :product
';
//Or Like this if the column is of Type JSON in MySQL(Not doctrine, yes check MySQL).
$sql = '
SELECT * FROM Entity e
WHERE e.params->"$.params.product" = :product
';
$stmt = $conn->prepare($sql);
$statement->bindValue("product","stopper");
$stmt->execute();
return $statement->fetchAll();
Hope this helps!
P.S: Note that my example uses a column named 'params' with a Json containing also a named attribute 'params', this can be confusing. The intended purpose is to show how to do multiple level filtering.

wordpress wpdb->update strange error by converting single quote to html entity

Update Julu 2018:
I find out problem is something else. The print error method will always print out a encoded html message like the one below. If the message is not showing any extra piece of information means the SQL query is fine.
Original Question:
I tried to update the invite_code by using the $wpdb->update method, but it return strange error, it seems like WordPress convert the single quote to html entity - &#39
Please help me if anyone knows why it will convert the single quote to HTML entity automatically.
I am not able to do use any WordPress built-in method to update the query because the problem seems to happen at the prepared statement which will use in every built-in method.
WordPress database error: UPDATE exhibitor_invite SET invite_code =
&#039 ;8j8mxfkkubd0kppi082p&#039 ; WHERE id = 10
function createCode() {
$length = 20;
$inviteCode = "";
$characters = "0123456789abcdefghijklmnopqrstuvwxyz";
for ($p = 0; $p < $length; $p++) {
$inviteCode .= $characters[mt_rand(0, strlen($characters))];
}
return $inviteCode;
}
function updateCode($id) {
global $wpdb;
$wpdb->show_errors();
$prefix = $wpdb->prefix;
$invite_code = createCode() ;
// I tried to esc the string, but it doesn't work
// $invite_code = $wpdb->esc_like($invite_code);
// I also tried to use normal query, but it return the same error
// $affected_rows = $wpdb->query( $wpdb->prepare(
// " UPDATE {$wpdb->prefix}exhibitor_invite SET invite_code = %s WHERE id = %d", $invite_code, $id ));
$affected_rows = $wpdb->update( $prefix.'exhibitor_invite',
array('invite_code' => $invite_code),
array('id' => $id),
'%s',
'%d' );
$wpdb->print_error();
if(!is_bool($affected_rows)) {
return $affected_rows > 0;
}
return $affected_rows;
}
Perhaps way too late, but in case not I had the exact same problem and spent hours looking for a solution.
It seems that the WordPress property 'update' of wpdb object is where the problem occurs.
One solution that I found to work is to store the entire SQL string in a variable and then before using it, pass the variable through a PHP function of mysqli_real_escape_string().
PHP manual states:
This function is used to create a legal SQL string that you can use in an SQL statement. The given string is encoded to an escaped SQL string, taking into account the current character set of the connection.
Your solution may look something like this (untested).
$sql_string =
"
UPDATE ${prefix}exhibitor_invite
SET invite_code = %s
WHERE id = %d
";
//procedural style
mysqli_real_escape_string( $your_conn_to_server, $sql_string );
//update
$wpdb->update( $wpdb->prepare(
$sql_string,
array(
$invite_code,
$id
)
), OBJECT );

Symfony Insert into sub table

As i am new to symfony framework, for my client symfony website doing the maintenance. i have tried to insert a record into a new table, which was actually a sub table of a already existing table.
But i am not able to write the insert query in this. which shows the error only.
Please check and provide the solutions for the below code,
public function executeUpdatednc(sfWebRequest $request)
{
$patient_id = $_REQUEST['pid'];
$q = Doctrine_Query::create()
->update('patient')
->set('isadmindnc', '?', 1)
->where('id = ?', $patient_id)
->execute();
$datetime = date("Y-m-d H:i:s");
##### Here i need to write the sub query to insert into the new table, Please suggest #####
//$rsm = new ResultSetMapping();
//$query = $this->_em->createNativeQuery('INSERT INTO patient_phone SET ph_pid = ?', $patient_id);
//$query->setParameter(1, $items);
//$result = $query->getResult();
}
For me, simple way to resolve this problem (for update):
$patient = Doctrine_Core::getTable('patient')->findOneById($patient_id);
$patient->setIsadmindnc(1);
$patient->save();
For insert:
$patient = new Patient();
$patient->setIsadmindnc(1);
$patient->save();

Symfony2 (doctrine2) native sql insert

How to insert data in symfony2 doctrine2 on native sql?
My query
insert into propriedades (id,name,descripcion,num_lote,cod_imovel,imovel,convenio,proprietar,cpf,area_ha,perimetro,location,centro) VALUES (nextval('propriedades_id_seq'),'?','?','?','?','?','?','?','?','?','?',ST_GeomFromKML('<Polygon><outerBoundaryIs><LinearRing><coordinates>".$terra['coordinates']."</coordinates></LinearRing></outerBoundaryIs></Polygon>'),ST_Centroid(ST_GeomFromKML('<Polygon><outerBoundaryIs><LinearRing><coordinates>".$terra['coordinates']."</coordinates></LinearRing></outerBoundaryIs></Polygon>')))
You have to use $conn->insert('table', $dataArray);. See documentation
In 2020 you can do something like (example query, adapt it to your params):
$query = "
INSERT INTO `user_challenges_claimed`
SET
`season_id` = :seasonId,
`user_id` = :userId,
`interval_type` = :intervalType,
`is_claimed` = true
ON DUPLICATE KEY UPDATE
`is_claimed` = true
;
";
// set query params
$queryParams = [
'seasonId' => $seasonId,
'userId' => $userId,
'intervalType' => $intervalType,
];
// execure query and get result
$result = $this->manager->getConnection()
->executeQuery(
$query,
$queryParams
);
// clear manager entities
$this->manager->clear();
// optional - assert row has been inserted/modified
if ($result->rowCount() < 1) {
throw new ChallengeAlreadyClaimedException(
"[{$seasonId}:{$userId} - {$intervalType}]"
);
}
$this->manager is an object implementing EntityManagerInterface (ie EntityManager).
Usually you do not use what you call native sql in a symfony 2 project but the high level Doctrine ORM layer.
However there is a doctrine dbal layer which enables e.g. mysql queries instead of DQL. Here is the reference
http://symfony.com/doc/2.0/cookbook/doctrine/dbal.html

Query database and store results in array in drupal module

I have a table in my database called gsm_tariff. Basically I just want to run a simple select query
"SELECT * FROM {gsm_tariff} WHERE Country='Afghanistan'"
and store the results in an array. Can anyone help me with how to do this please? I know where to put the code and everything; I just need the code to do the query and store the results in an array.
$array = array();
$result = db_query('SELECT * FROM {gsm_tariff} WHERE Country = "%s"', 'Afghanistan');
while ($record = db_fetch_object($result)) {
$array[] = $record->(data to reference);
}
Note that I don't know the field you want to reference given the question, but it would be in the $record object.

Resources