I have an insert query, and I want to get the ID from the table. I have been searching, and I found lastInsertId() for PDO. When I want to use it, I get PHP errors.
This is my code:
$db = new database();
$naam = $db->quoteQuery($_POST['naam']);
$barcode = $db->quoteQuery($_POST['barcode']);
$sql = "INSERT INTO products(name, barcode) VALUES (".$name.",".$barcode.")";
$results = $db->executeQuery($sql);
$lastid = $results->lastInsertId();
But this gives an error, this one:
Fatal error: Call to undefined method PDOStatement::lastInsertId() in /home/onlineweuh/domains/onlinewebapps.nl/public_html/vsb/admin/add-product.class.php on line 297
My database class:
class database
{
private $handleDB;
public function __construct()
{
$host = ;
$user = ;
$database = ;
$password = ;
try
{
$this->handleDB = new PDO('mysql:host='.$host.';dbname='.$database, $user, $password);
}
catch (PDOException $e)
{
print_r($e);
}
$this->handleDB->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
}
I hope someone can help me solve it, I want the ID which is given at the insert Query.
You get the lastinsertid from the PDO object and not your results object.
Try $db->lastInsertId()
edit below.
Your database class is encapsulating your handleDB / PDO object. Since the handleDB variable is private, you cannot access this outside your class. You would need to either make it public like so;
class database
{
public $handleDB;
public function __construct()
{
$host = 'removed';
$user = 'removed';
$database = 'removed';
$password = 'removed';
try
{
$this->handleDB = new PDO('mysql:host='.$host.';dbname='.$database, $user, $password);
}
catch (PDOException $e)
{
print_r($e);
}
$this->handleDB->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
}
}
Now you can call $db->handleDB->lastInsertId();
Or you could expose the handleDB->lastInsertId() as a function like:
class database
{
private $handleDB;
public function __construct()
{
$host = 'remove';
$user = 'removed';
$database = 'removed';
$password = 'removed';
try
{
$this->handleDB = new PDO('mysql:host='.$host.';dbname='.$database, $user, $password);
}
catch (PDOException $e)
{
print_r($e);
}
$this->handleDB->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
}
public function lastInsertId(){
return $this->handleDB->lastInsertId();
}
}
You would call using $db->lastInsertId();
lastInsertId is a method of PDO, not PDOStatement. Therefore:
$db->lastInsertId();
your database class needs to be a subclass of PDO by extending PDO
class database extends PDO
that way all the methods in PDO are available to your subclass.
Related
So what I want to do is to show who's in a team. I've created a function called getTeam().
class admin
{
private $db;
public function __construct($conn)
{
return $this->db;
}
public function getTeam($teamname)
{
try
{
$sql = "SELECT * FROM `tbl_players` WHERE EXISTS (SELECT id FROM `tbl_teams` WHERE team_name=:team_name)";
$stmt = $this->db->prepare($sql);
$stmt->bindparam(":team_name", $teamname);
$stmt->execute();
return $stmt;
}
catch(PDOException $e)
{
echo $e->getMessage();
}
}
}
Here is my dbconnect I'm using
session_start();
$DB_host = "localhost";
$DB_user = "root";
$DB_pass = "";
$DB_name = "project_fifa";
try
{
$conn = new PDO("mysql:host={$DB_host};dbname={$DB_name}",$DB_user,$DB_pass);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch(PDOException $e)
{
echo $e->getMessage();
}
include ('assets/classes/admin.php');
$user = new admin($conn);
So now I'm trying to use the function here
require('../dbconnect.php');
if(isset($_POST['findteam'])){
$teamname = $_POST['teamname'];
getTeam($teamname);
}
It can't find the function and I don't know why.
If you are doing code with OOPS, First you have to learn some basics about it Read it
Object(new) :
To create an instance of a class, the new keyword must be used. An object will always be created unless the object has a constructor defined that throws an exception on error. Classes should be defined before instantiation (and in some cases this is a requirement).
If a string containing the name of a class is used with new, a new instance of that class will be created. If the class is in a namespace, its fully qualified name must be used when doing this.
$adminObject = new admin();
$adminObject->getTeam($teamname);
This question already has an answer here:
Fatal error Call to a member function prepare() on null [closed]
(1 answer)
Closed 5 years ago.
I know there were a lot of answers related to this error, but I still don't know how to solve it... I'm trying to make the database connection, which would connect to the database and insert user's entered values in it and i got this error. I've created 2 files (with different classes):
Here is a connection file:
<?php
class Connection {
// Setting Database Source Name (DSN)
public function __construct() {
$dsn = 'mysql:host=localhost;dbname=employees';
// Setting options
$options = array (PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION);
// Making the connection to the database
try {
$this->dbh = new PDO($dsn, 'root', '', $options);
}
catch (PDOException $e) {
$this->error = $e->getMessage();
}
}
}
$connection = new connection();
?>
And here is users.php file:
<?php
include 'connection.php';
class Users {
public $name;
public $surname;
public $employmentDate;
public function __construct()
{
if(isset($_POST['Submit'])) {
$this->name = $_POST['name'];
$this->surname = $_POST['surname'];
$this->employmentDate = $_POST['employmentDate'];
}
}
// Inserting users values to the database table
public function insertUserValues() {
$stmt= 'INSERT INTO employee (name,surname,employment_date) VALUES (:name,:surname,:employmentDate)';
$stmt = $this->dbh->prepare();
$stmt->bindValue(':name',$name, PDO::PARAM_STR);
$stmt->bindValue(':surname',$surname, PDO::PARAM_STR);
$stmt->bindValue(':employmenDate',$employmentDate, PDO::PARAM_STR);
$stmt->execute([$this->name,$this->surname,$this->employmentDate]);
}
}
$users = new Users();
$users->insertUserValues();
?>
I guess there are some mistakes in code structure, but I'm just learning, so. The code line which throws the error 18 line in users.php file:
$stmt = $this->dbh->prepare();
Please someone tell me where I am doing a mistake, thank you for any help.
You just have somes mistakes in your code. Try to use this lines :
Connection file :
<?php
class Connection {
public $dbh;
// Setting Database Source Name (DSN)
public function __construct() {
$dsn = 'mysql:host=localhost;dbname=employees';
// Setting options
$options = array (PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION);
// Making the connection to the database
try {
$this->dbh = new PDO($dsn, 'root', '', $options);
}
catch (PDOException $e) {
$this->error = $e->getMessage();
}
}
}
$connection = new connection();
users.php file :
<?php
include 'connection.php';
class Users {
public $name;
public $surname;
public $employmentDate;
public $connection;
public function __construct($connection)
{
$this->connection = $connection;
if(isset($_POST['Submit'])) {
$this->name = $_POST['name'];
$this->surname = $_POST['surname'];
$this->employmentDate = $_POST['employmentDate'];
}
}
// Inserting users values to the database table
public function insertUserValues() {
$query = 'INSERT INTO employee (name,surname,employment_date) VALUES (:name,:surname,:employmentDate)';
$stmt = $this->connection->dbh->prepare($query);
$stmt->bindValue(':name',$this->name, PDO::PARAM_STR);
$stmt->bindValue(':surname',$this->surname, PDO::PARAM_STR);
$stmt->bindValue(':employmentDate',$this->employmentDate, PDO::PARAM_STR);
$stmt->execute();
}
}
$users = new Users($connection);
$users->insertUserValues();
Explanations :
You have to pass the $connection variable to your users class (or import it with global $connection;)
Your connection file has to make visible the dbh property, otherwise you will not be able to make any query on your database
PDO prepare() method is waiting for a query in first argument
You don't need to pass an array to execute() method if you already have binded your values before
You are referring to $this from outside the class scope. You probably want
$connection->dbh->prepare();
You could make your connection class to a singleton:
class Connection {
private static $instance = null;
// Setting Database Source Name (DSN)
public function __construct() {
$dsn = 'mysql:host=localhost;dbname=employees';
// Setting options
$options = array (PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION);
// Making the connection to the database
try {
$this->dbh = new PDO($dsn, 'root', '', $options);
} catch (PDOException $e) {
$this->error = $e->getMessage();
}
}
public static function __callStatic($name, $args) {
if (self::$instance == null) {
self::$instance = new self();
}
call_user_func_array([ self::$instance->dbh, $name], $args);
}
}
Then use it as follows:
Connection::prepare(); //or connection::any_pdo_function
Here's our class so far:
class DB {
private $DBUser = 'xxx';
private $DBPass = 'xxx';
private $DBServer = 'xxx';
private $DBName = 'xxx';
public $sql;
public $id;
public function __construct($sql,$id){
$this->sql = $sql;
$this->id = $id;
} //end variables
public function select() {
try {
$strDSN = "mysql:host=$this->DBServer;dbname=$this->DBName;";
$username = $this->DBUser;
$pass = $this->DBPass;
$conn = new PDO($strDSN, $username, $pass);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
/*return $conn;*/
$stmt = $conn->prepare($this->sql);
$id = $this->id;
$stmt->execute(array('id'=>$id));
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
return $result;
}
catch (PDOException $e) {
echo 'Error: ' . $e->getMessage();
}
} //end method
} //end class
We call it using this:
$db = new DB;
$result = $db->select('SELECT * FROM tbl_xxx WHERE myid = :id',$_GET['id']);
But I'm getting the following error:
Warning: Missing argument 1 for DB::__construct() Warning: Missing
argument 2 for DB::__construct()
I'm sure the answer is a simple one, but I can't see it. What am I missing here??
I usually extend the PDO class like
class DB extends PDO {...}
Then make sure your constructor calls the parent (PDO) one with the connection string. However, once I needed to connect to the database using a separate function. This was doing:
// Establish the connection.
try {
$this->str="";
switch ($this->proto){
case "mysql":
$this->str = "mysql:host=$this->host;dbname=$this->db";
break;
default:
throw new PDOException("Wrong protocol '$proto'");
}
parent::__construct($this->str,
$this->user, $this->pw,$opts);
}catch (PDOException $e) {
$this->last_error = $e->getMessage();
error_log($e->getMessage());
return false;
}
Also, make sure though that you do not connect every time you select! So probably you should make separate select and connect functions. Finally, instead of select, delete, etc functions I usually make a generic/base (but a bit unsafe) member which will return any query results:
public function send_query($query){
$result = $this->query($query);
if ($result === false){
$this->last_error = $this->errorInfo();
return false;
}
$ret = $result->fetchAll();
$result->closeCursor();
return $ret;
}
The above is "unsafe" because anything in $query string is going to run on the database. Wrapper functions should ensure that the string is properly escaped and contains no malicious code. I would suggest that you use prepared statements for all your queries but the above method should do what you ask.
I have a PHP class with two methods. One connects to a MySQL database for output, and the other connects to a MySQL database for input.
My question is, for both functions, I repeated the code for connecting to the database. What would be a better way to maybe have a third function in the class to connect to the DB and have the other two call the function to establish the connection, rather than repeat the code twice? I'm a PHP n00b trying to improve my OOP coding. Notice how I connected to the DB twice--using the exact same code:
class output_mysql {
var $db_name = 'database';
var $db_username = 'name';
var $db_password = 'mypassword';
function print_table_cell($tbl_name, $colm_name, $array_index_num) {
try {
$pdo = new PDO("mysql:host=localhost;dbname=$this->db_name", $this->db_username, $this->db_password);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch (PDOException $e) {
$error = 'Unable to connect to the database server.';
include 'output_mysql_error.php';
exit();
}
try {
$sql = "SELECT $colm_name FROM $tbl_name";
$result = $pdo->query($sql);
}
catch (PDOException $e) {
$error = 'Error fetching content: ' . $e->getMessage();
include 'output_mysql_error.php';
exit();
}
while ($row = $result->fetch()) {
$all_content[] = $row["$colm_name"];
}
echo $all_content[$array_index_num];
}
function update_content($tbl_name, $colm_name, $error_message_text, $id_num) {
try {
$pdo = new PDO("mysql:host=localhost;dbname=$this->db_name", $this->db_username, $this->db_password);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch (PDOException $e) {
$error = 'Unable to connect to the database server.';
include 'output_mysql_error.php';
exit();
}
try {
$sql = 'UPDATE website_content SET
content = :content,
date_added = CURDATE()
WHERE id = :id';
$s = $pdo->prepare($sql);
$s->bindValue(':content', $error_message_text);
$s->bindValue(':id', $id_num);
$s->execute();
}
catch (PDOException $e) {
$error = 'Error: ' . $e->getMessage();
include 'output_mysql_error.php';
exit();
}
}
}
This question is tagged [oop], but the code in it is far from OOP.
Your methods are doing waaaaaaaaaaaaay too much. What you should do is inject the database connection into the constructor of the output_mysql class (which is a terrible name btw).
namespace App\Page;
class Content
{
private $dbConnection;
public function __construct(\PDO $dbConnection)
{
$this->dbConnection = $dbConnection
}
public update($id, $content)
{
$stmt = $this->dbConnection->prepare('UPDATE website_content SET content = :content, date_added = CURDATE() WHERE id = :id');
$stmt->execute([
'id' => $id,
'content' => $content,
]);
}
}
$dbConnection = new \PDO("mysql:host=localhost;dbname=$this->db_name", $this->db_username, $this->db_password);
$dbConnection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$dbConnection->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$pageContent = new \App\Page\Content($dbConnection);
$pageContent->update(1, 'new content');
If you have a method called print_table_cell you are probably doing OOP wrong, because it probably means you code is doing too much and probably violates the Single Responsibility Principle. I mean a class in almost all circumstances would never need to be able to access any column of just any table.
class Model
{
protected $pdo;
/**
* Inject the pdo driver in the model.
*/
public function __construct(PDO $pdo)
{
$this->pdo = $pdo;
}
public function print_table_cell($tbl_name, $colm_name, $array_index_num)
{
// Use the pdo object $this->pdo
}
}
// Create the connection
$dbName = '';
$dbUsername = '';
$dbPassword = '';
$pdo = new PDO("mysql:host=localhost;dbname=$dbName", $dbUsername, $dbPassword);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// Create your model and inject the pdo object.
$model = new Model($pdo);
$model->print_table_cell() ...
As said above you need to use prepared statements, because PDO will escape the values which prevents SQL injections. But anyway all input data must be filtered : you have some basic filters http://php.net/manual/fr/function.filter-var.php.
The model class should only interact with the database, and doesn't print anything.
For priting output you can use a so called View class that get data from the model and displays it.
class View
{
protected $model;
public function __construct(Model $model)
{
$this->model = $model;
}
public function render()
{
echo $this->model->getData();
}
}
class Model
{
protected $pdo;
public function __construct(PDO $pdo)
{
$this->pdo = $pdo;
}
public function getData()
{
// Do your query here with $this->pdo and prepared statement.
// and return the data
}
}
$pdo = new PDO(...);
$model = new Model($pdo);
$view = new View($model);
$view->render();
Hi guys I am having problem with my code. with __construct() I am getting Fatal error: Call to a member function prepare() on a non-object but without it my code is working.
class Animals{
public $db_fields;
public function __construct(){
$this->db_fields = $this->get_fields();
foreach($this->db_fields as $field){
$this->$field = "";
}
public function get_fields(){
global $dbh;
$q = $dbh->prepare("DESCRIBE animals");
$q->execute();
$db_fields = $q->fetchAll(PDO::FETCH_COLUMN);
return $db_fields;
}
}
$f = new Animals();
/*** mysql hostname ***/
$hostname = 'localhost';
/*** mysql username ***/
$username = 'root';
/*** mysql password ***/
$password = '';
/*** mysql database***/
$dbname = 'animals';
try {
$dbh = new PDO("mysql:host=$hostname;dbname=$dbname", $username, $password);
/*** echo a message saying we have connected ***/
echo 'Connected to database <br />';
$dbh = null;
}
catch(PDOException $e)
{
echo $e->getMessage();
}
I just want to make my fields(animal_id,animal_type,animal_name) work as same as
public $animal_id;
public $animal_type;
public $animal_name;
You have to instantiate the Animals object after you create $dbh, otherwise it's not defined in the get_fields() function.
$dbh = new PDO("mysql:host=$hostname;dbname=$dbname", $username, $password);
$f = new Animals();
That being said, a better design is to use dependency injection, and send the $dbh object to the class, like this:
$dbh = new PDO("mysql:host=$hostname;dbname=$dbname", $username, $password);
$f = new Animals( $dbh);
So, your updated class would look like:
class Animals{
private $dbh;
public function __construct( $dbh){
$this->dbh = $dbh;
}
public function get_fields(){
$q = $this->dbh->prepare("DESCRIBE animals");
}
}
The benefit? You get rid of the global variable. Typically, requiring a global variable is a bad design, and you want to avoid it. You can see why just based on the problem you're having - It requires a global state to be set in order to function.