save a link to mysql database php - mysql

I have a html form (for blogposts) and I want to save everything in a database table. It works fine but when I add a column for an image, which can also be uploaded in the same html form, then it is not saving anything.
Here's the code:
$imagepath = 'https://myurl.com/uploads/' . $_FILES['image']['name'];
$db = new PDO($dsn, $dbuser, $dbpass);
$query = $db->prepare(
"INSERT INTO posts (author, title, text, date, image)
VALUES(:author, :title, :text, NOW()), '$imagepath'");
$query->execute(array("author" => $author, "title" => $title, "text" => $text));
$db = null;

Try This..
<?php
if(isset($_POST['Upload'])) // upload button press
{
$file_name = $_FILES['file']['name'];
$file_size = $_FILES['file']['size'];
$file_type = $_FILES['file']['type'];
$file_temp = $_FILES['file']['tmp_name'];
$folder = "uploads/";
$file_url="http://localhost/../../uploads/$file_name"; //file location
move_uploaded_file($file_temp,"Song_uploads/".$file_name);
$sql="INSERT INTO imagepost(file_NAME,file_URL,file_SIZE) VALUES(:file_name,:file_url,:file_size)";
$stmt= $conn->prepare($sql);
$stmt->bindParam(':file_name',$file_name);
$stmt->bindParam(':file_url',$file_url);
$stmt->bindParam(':file_size',$file_size);
if($stmt->execute())
{
$message="<br/><h1> ---> "."[".$file_name."]"." File Has Been Uploaded !! </h1>";
}
else
{
$message="<br/> <h1> ---> "."[".$file_name."]"." File Not Be Uploaded !! Please Try Again !! </h1>";
}
}
?>

the closing parenthese is wrongly placed
"INSERT INTO posts (author, title, text, date, image)
VALUES(:author, :title, :text, NOW()), '$imagepath'");
should be
"INSERT INTO posts (author, title, text, date, image)
VALUES(:author, :title, :text, NOW(), '$imagepath' )");

Related

Symfony3 : How to do a massive import from a CSV file as fast as possible?

I have a .csv file with more than 690 000 rows.
I found a solution to import data that works very well but it's a little bit slow... (around 100 records every 3 seconds = 63 hours !!).
How can I improve my code to make it faster ?
I do the import via a console command.
Also, I would like to import only prescribers that aren't already in database (to save time). To complicate things, no field is really unique (except for id).
Two prescribers can have the same lastname, firstname, live in the same city and have the same RPPS and professional codes. But, it's the combination of these 6 fields which makes them unique !
That's why I check on every field before create a new one.
<?php
namespace AppBundle\Command;
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Helper\ProgressBar;
use AppBundle\Entity\Prescriber;
class PrescribersImportCommand extends ContainerAwareCommand
{
protected function configure()
{
$this
// the name of the command (the part after "bin/console")
->setName('import:prescribers')
->setDescription('Import prescribers from .csv file')
;
}
protected function execute(InputInterface $input, OutputInterface $output)
{
// Show when the script is launched
$now = new \DateTime();
$output->writeln('<comment>Start : ' . $now->format('d-m-Y G:i:s') . ' ---</comment>');
// Import CSV on DB via Doctrine ORM
$this->import($input, $output);
// Show when the script is over
$now = new \DateTime();
$output->writeln('<comment>End : ' . $now->format('d-m-Y G:i:s') . ' ---</comment>');
}
protected function import(InputInterface $input, OutputInterface $output)
{
$em = $this->getContainer()->get('doctrine')->getManager();
// Turning off doctrine default logs queries for saving memory
$em->getConnection()->getConfiguration()->setSQLLogger(null);
// Get php array of data from CSV
$data = $this->getData();
// Start progress
$size = count($data);
$progress = new ProgressBar($output, $size);
$progress->start();
// Processing on each row of data
$batchSize = 100; # frequency for persisting the data
$i = 1; # current index of records
foreach($data as $row) {
$p = $em->getRepository('AppBundle:Prescriber')->findOneBy(array(
'rpps' => $row['rpps'],
'lastname' => $row['nom'],
'firstname' => $row['prenom'],
'profCode' => $row['code_prof'],
'postalCode' => $row['code_postal'],
'city' => $row['ville'],
));
# If the prescriber doest not exist we create one
if(!is_object($p)){
$p = new Prescriber();
$p->setRpps($row['rpps']);
$p->setLastname($row['nom']);
$p->setFirstname($row['prenom']);
$p->setProfCode($row['code_prof']);
$p->setPostalCode($row['code_postal']);
$p->setCity($row['ville']);
$em->persist($p);
}
# flush each 100 prescribers persisted
if (($i % $batchSize) === 0) {
$em->flush();
$em->clear(); // Detaches all objects from Doctrine!
// Advancing for progress display on console
$progress->advance($batchSize);
$progress->display();
}
$i++;
}
// Flushing and clear data on queue
$em->flush();
$em->clear();
// Ending the progress bar process
$progress->finish();
}
protected function getData()
{
// Getting the CSV from filesystem
$fileName = 'web/docs/prescripteurs.csv';
// Using service for converting CSV to PHP Array
$converter = $this->getContainer()->get('app.csvtoarray_converter');
$data = $converter->convert($fileName);
return $data;
}
}
EDIT
According to #Jake N answer, here is the final code.
It's very very faster ! 10 minutes to import 653 727 / 693 230 rows (39 503 duplicate items!)
1) Add two columns in my table : created_at and updated_at
2) Add a single index of type UNIQUE on every column of my table (except id and dates) to prevent duplicate items with phpMyAdmin.
3) Add ON DUPLICATE KEY UPDATE in my query, to update just the updated_at column.
foreach($data as $row) {
$sql = "INSERT INTO prescripteurs (rpps, nom, prenom, code_prof, code_postal, ville)
VALUES(:rpps, :nom, :prenom, :codeprof, :cp, :ville)
ON DUPLICATE KEY UPDATE updated_at = NOW()";
$stmt = $em->getConnection()->prepare($sql);
$r = $stmt->execute(array(
'rpps' => $row['rpps'],
'nom' => $row['nom'],
'prenom' => $row['prenom'],
'codeprof' => $row['code_prof'],
'cp' => $row['code_postal'],
'ville' => $row['ville'],
));
if (!$r) {
$progress->clear();
$output->writeln('<comment>An error occured.</comment>');
$progress->display();
} elseif (($i % $batchSize) === 0) {
$progress->advance($batchSize);
$progress->display();
}
$i++;
}
// Ending the progress bar process
$progress->finish();
1. Don't use Doctrine
Try to not use Doctrine if you can, it eats memory and as you have found is slow. Try and use just raw SQL for the import with simple INSERT statements:
$sql = <<<SQL
INSERT INTO `category` (`label`, `code`, `is_hidden`) VALUES ('Hello', 'World', '1');
SQL;
$stmt = $this->getDoctrine()->getManager()->getConnection()->prepare($sql);
$stmt->execute();
Or you can prepare the statement with values:
$sql = <<<SQL
INSERT INTO `category` (`label`, `code`, `is_hidden`) VALUES (:label, :code, :hidden);
SQL;
$stmt = $this->getDoctrine()->getManager()->getConnection()->prepare($sql);
$stmt->execute(['label' => 'Hello', 'code' => 'World', 'hidden' => 1);
Untested code, but it should get you started as this is how I have done it before.
2. Index
Also, for your checks, have you got an index on all those fields? So that the lookup is as quick as possible.

Mysql error message using PDO

I'd like my database not to insert duplicate e-mails, I used the unique key and it works perfectly. However, no message is shown to the user, and it seems like he signed up correctly, but when he tries to login he finds out it's impossible.
I made this code, but it returns success for both situations.
$sql4 = "INSERT INTO users (username, email, password, id_group, id_company)
VALUES (:username, :email, :password, :id_group, :id_company)";
$stmt4 = $PDO->prepare($sql4);
$stmt4->bindParam(':username', $username);
$stmt4->bindParam(':email', $email);
$stmt4->bindParam(':password',md5($password));
$stmt4->bindParam(':id_group', $id_group);
$stmt4->bindParam(':id_company', $id_company);
$stmt4->execute();
$erro = mysql_errno();
if ($erro == 0) {
echo '<p align="center">Success!</p>';
} elseif ($erro == 1062) {
echo '<p align="center"> Email already registered. Try using another.
</p>';
}
I tried another way and it worked:
$sql4 = $PDO->prepare("SELECT COUNT(*) as us FROM users WHERE email =
:email");
$sql4->bindValue(":email",$email);
$sql4->execute();
$row = $sql4->fetch();
if($row['us'] == '0'){
$sql4 = "INSERT INTO users (username, email, password, id_group, id_company)
VALUES (:username, :email, :password, :id_group, :id_company)";
$stmt4 = $PDO->prepare($sql4);
$stmt4->bindParam(':username', $username);
$stmt4->bindParam(':email', $email);
$stmt4->bindParam(':password',md5($password));
$stmt4->bindParam(':id_group', $id_group);
$stmt4->bindParam(':id_company', $id_company);
$stmt4->execute();
return '1';
//se o email for repetido exibe mensagem de erro.
}else{
echo 'Email already registered. Try another.';
}

HTML from database replace with bbcode

I found some script on internet to from bbcode like [b] replace
function bbcodehtml($bbtext){
$bbtags = array(
'[b]' => '<strong>','[/b]' => '</strong>',
'[i]' => '<em>','[/i]' => '</em>',
'[u]' => '<span style="text-decoration: underline;">', '[/u]' => '</span>',
'[code]' => '<blockquote>','[/code]' => '</blockquote>'
);
$bbtext = str_ireplace(array_keys($bbtags), array_values($bbtags), $bbtext);
$bbextended = array(
"/\[url](.*?)\[\/url]/i" => "<a target=\"_blank\" href=\"http://$1\" title=\"$1\">$1</a>",
"/\[url=(.*?)\](.*?)\[\/url\]/i" => "<a target=\"_blank\" href=\"$1\" title=\"$1\">$2</a>",
"/\[img\]([^[]*)\[\/img\]/i" => "<img style=\"max-width:700px;\" src=\"$1\" alt=\" \" />",
"/\[image\]([^[]*)\[\/image\]/i" => "<img style=\"max-width:700px;\" src=\"$1\" alt=\" \" />"
);
foreach($bbextended as $match=>$replacement){
$bbtext = preg_replace($match, $replacement, $bbtext);
}
return $bbtext;
}
But now i have from when i want to display content in textarea i cant replace HTML for BBcodes..
I tried to change values for preg_replace and i got errors..
Hmm...
1) Your code have many security problems. One for example. User can write text for XSS attack like this:
[img]" onmouseover="alert(document.cookie);[/img]
2) You must have TWO fields on DB, where first field contains source (unreplaced bb-codes) text, and second field contains replaced (readonly html) text. For this case you can run replace process (bb to html) only for create or edit text action.

Parsing PubMed XML to submit to mySQL database (XML::Twig)

I'm new to XML::Twig, and I'm trying to parse a PubMed XML 2.0 esummary final to place into a mySQL database. I've gotten this far:
#!/bin/perl -w
use strict;
use DBI;
use XML::Twig;
my $uid = "";
my $title = "";
my $sortpubdate = "";
my $sortfirstauthor = "";
my $dbh = DBI->connect ("DBI:mysql:medline:localhost:80",
"root", "mysql");
my $t= new XML::Twig( twig_roots => { 'DocumentSummary' => $uid => \&submit },
twig_handlers => { 'DocumentSummary/Title' => $title, 'DocumentSummary/SortPubDate' => $sortpubdate, 'DocumentSummary/SortFirstAuthor' => $sortfirstauthor});
$t->parsefile('20112.xml');
$dbh->disconnect();
exit;
sub submit
{ my $insert= $dbh->prepare( "INSERT INTO medline_citation (uid, title, sortpubdate, sortfirstauthor) VALUES (?, ?, ?, ?);");
$insert->bind_param( 1, $uid);
$insert->bind_param( 2, $title);
$insert->bind_param( 3, $sortpubdate);
$insert->bind_param( 4, $sortfirstauthor);
$insert->execute();
$t->purge;
}
But Perl seems to stall for some reason. Am I doing this right? I'm trying to use twig_roots to decrease the amount of parsing since I'm only interested in a few fields (these are large files).
Here is an example of the XML:
<DocumentSummary uid="22641317">
<PubDate>2012 Jun 1</PubDate>
<EPubDate></EPubDate>
<Source>Clin J Oncol Nurs</Source>
<Authors>
<Author>
<Name>Park SH</Name>
<AuthType>
Author
</AuthType>
<ClusterID>0</ClusterID>
</Author>
<Author>
<Name>Knobf MT</Name>
<AuthType>
Author
</AuthType>
<ClusterID>0</ClusterID>
</Author>
<Author>
<Name>Sutton KM</Name>
<AuthType>
Author
</AuthType>
<ClusterID>0</ClusterID>
</Author>
</Authors>
<LastAuthor>Sutton KM</LastAuthor>
<Title>Etiology, assessment, and management of aromatase inhibitor-related musculoskeletal symptoms.</Title>
<SortTitle>etiology assessment and management of aromatase inhibitor related musculoskeletal symptoms </SortTitle>
<Volume>16</Volume>
<Issue>3</Issue>
<Pages>260-6</Pages>
<Lang>
<string>eng</string>
</Lang>
<NlmUniqueID>9705336</NlmUniqueID>
<ISSN>1092-1095</ISSN>
<ESSN>1538-067X</ESSN>
<PubType>
<flag>Journal Article</flag>
</PubType>
<RecordStatus>
PubMed - in process
</RecordStatus>
<PubStatus>4</PubStatus>
<ArticleIds>
<ArticleId>
<IdType>pii</IdType>
<IdTypeN>4</IdTypeN>
<Value>N1750TW804546361</Value>
</ArticleId>
<ArticleId>
<IdType>doi</IdType>
<IdTypeN>3</IdTypeN>
<Value>10.1188/12.CJON.260-266</Value>
</ArticleId>
<ArticleId>
<IdType>pubmed</IdType>
<IdTypeN>1</IdTypeN>
<Value>22641317</Value>
</ArticleId>
<ArticleId>
<IdType>rid</IdType>
<IdTypeN>8</IdTypeN>
<Value>22641317</Value>
</ArticleId>
<ArticleId>
<IdType>eid</IdType>
<IdTypeN>8</IdTypeN>
<Value>22641317</Value>
</ArticleId>
</ArticleIds>
<History>
<PubMedPubDate>
<PubStatus>entrez</PubStatus>
<Date>2012/05/30 06:00</Date>
</PubMedPubDate>
<PubMedPubDate>
<PubStatus>pubmed</PubStatus>
<Date>2012/05/30 06:00</Date>
</PubMedPubDate>
<PubMedPubDate>
<PubStatus>medline</PubStatus>
<Date>2012/05/30 06:00</Date>
</PubMedPubDate>
</History>
<References>
</References>
<Attributes>
<flag>Has Abstract</flag>
</Attributes>
<PmcRefCount>0</PmcRefCount>
<FullJournalName>Clinical journal of oncology nursing</FullJournalName>
<ELocationID></ELocationID>
<ViewCount>0</ViewCount>
<DocType>citation</DocType>
<SrcContribList>
</SrcContribList>
<BookTitle></BookTitle>
<Medium></Medium>
<Edition></Edition>
<PublisherLocation></PublisherLocation>
<PublisherName></PublisherName>
<SrcDate></SrcDate>
<ReportNumber></ReportNumber>
<AvailableFromURL></AvailableFromURL>
<LocationLabel></LocationLabel>
<DocContribList>
</DocContribList>
<DocDate></DocDate>
<BookName></BookName>
<Chapter></Chapter>
<SortPubDate>2012/06/01 00:00</SortPubDate>
<SortFirstAuthor>Park SH</SortFirstAuthor>
</DocumentSummary>
Thanks!
The way I'd do this is to have a single handler, for the DocumentSummary, that feeds the DB, then purges the record. There is no need to get fancier than this.
Also, I find DBIx::Simple, well, simpler to use than raw DBI, it takes care of preparing and caching statements for me:
#!/bin/perl
use strict;
use warnings;
use DBIx::Simple;
use XML::Twig;
my $db = DBIx::Simple->connect ("dbi:SQLite:dbname=t.db"); # replace by your DSN
my $t= XML::Twig->new( twig_roots => { DocumentSummary => \&submit },)
->parsefile('20112.xml');
$db->disconnect();
exit;
sub submit
{ my( $t, $summary)= #_;
my $insert= $db->query( "INSERT INTO medline_citation (uid, title, sortpubdate, sortfirstauthor) VALUES (?, ?, ?, ?);",
$summary->att( 'uid'),
map { $summary->field( $_) } ( qw( Title SortPubDate SortFirstAuthor))
);
$t->purge;
}
If you're wondering about map { $summary->field( $_) } ( qw( Title SortPubDate SortFirstAuthor)), it's just a fancier (and IMHO more maintainable) way to write $summary->field( 'Title'), $summary->field( 'SortPubDate'), $summary->field( 'SortFirstAuthor' )
Your syntax of handlers is wrong. See the documentation for examples:
my $twig=XML::Twig->new(
twig_handlers =>
{ title => sub { $_->set_tag( 'h2') }, # change title tags to h2
para => sub { $_->set_tag( 'p') }, # change para to p
hidden => sub { $_->delete; }, # remove hidden elements
list => \&my_list_process, # process list elements
div => sub { $_[0]->flush; }, # output and free memory
},
pretty_print => 'indented', # output will be nicely formatted
empty_tags => 'html', # outputs <empty_tag />
);

Codeigniter database issue

Having a spot of bother trying to grab some data out of my database.
I have the following model:
function GetRestaurants($options = array())
{
// Qualification
if(isset($options['restaurantID']))
$this->db->where('restaurantID', $options['restaurantID']);
if(isset($options['restaurantRegionID']))
$this->db->where('restaurantRegionID', $options['restaurantRegionID']);
if(isset($options['restaurantName']))
$this->db->where('restaurantName', $options['restaurantName']);
if(isset($options['restaurantAddress1']))
$this->db->where('restaurantAddress1', $options['restaurantAddress1']);
if(isset($options['restaurantAddress2']))
$this->db->where('restaurantAddress2', $options['restaurantAddress2']);
if(isset($options['restaurantSuburb']))
$this->db->where('restaurantSuburb', $options['restaurantSuburb']);
if(isset($options['restaurantCity']))
$this->db->where('restaurantCity', $options['restaurantCity']);
if(isset($options['restaurantInformation']))
$this->db->where('restaurantInformation', $options['restaurantInformation']);
// limit / offset
if(isset($options['limit']) && isset($options['offset']))
$this->db->limit($options['limit'], $options['offset']);
else if(isset($options['limit']))
$this->db->limit($options['limit']);
// sort
if(isset($options['sortBy']) && isset($options['sortDirection']))
$this->db->order_by($options['sortBy'], $options['sortDirection']);
$query = $this->db->get("tblRestaurants");
if(isset($options['count'])) return $query->num_rows();
if(isset($options['restaurantID']))
return $query->row(0);
if(isset($options['limit']) && $options['limit'] == '1')
return $query->row(0);
return $query->result();
}
Now the following code works fine:
$this->load->model('Restaurants_model');
$data['restaurant'] = $this->Restaurants_model->GetRestaurants(array(
'restaurantName' => 'shed 5',
'limit' => '1'
));
However the following does not work:
$this->load->model('Restaurants_model');
$data['restaurant'] = $this->Restaurants_model->GetRestaurants(array(
'restaurantName' => str_replace('-', ' ', $this->uri->segment(2)),
'limit' => '1'
));
Even though the result of
str_replace('-', ' ', $this->uri->segment(2))
is in this instance: ‘shed 5’.
I have compared var_dumps of the output of the str_replace and the string itself and determined them to be identical. So why does the straight string return a result yet the string generated from the uri segment doesn’t? Some kind of encoding issue? My database holds data in ‘utf8_general_ci’.
Thanks for any suggestions!
$restaurant=str_replace('-', ' ', $this->uri->segment(2));
get value outside array and try array_push
$data['restaurant'] = $this->Restaurants_model->GetRestaurants(array(
'restaurantName' => $restaurant,
'limit' => '1'
));