right now i'm working with and new project and while I'm creating a Class which has a namespace called User and when i try to make a query with the PDO::prepare i get an error. Here is my code:
public function Exists() {
$Query = "SELECT * FROM Users WHERE Email = :newEmail";
$sqlQuery = $this->Connection->PDO::preapre($Query);
$sqlQuery->bindValue(":newEmail", $this->Email);
$sqlQuery->execute();
if (!$sqlQuery->rowCount()) {
return true;
} else {
throw new \Exception("Email already registered.");
}
}
I know i can sole this using use \PDO at the beginning of the file, but my question is if where i have in my code PDO::prepare, which is wrong, there is another way of typing it or whatelse. Thanks!
$this->Connection->PDO::preapre($Query);
Should be
$this->Connection->PDO::prepare($Query);
Related
I'm writing a code in PHP OOP and I'm trying to send $_POST data
filtered by one Class function to another Class function that will add
the data to database. Specifically login and password in registration
form.
I have 3 Classes that will do that:
Is simple Class that handles connection to database (I think it is not necessary to put code here)
Is the Class that filters the coming $_POST-s:
class Filter extends Dbconnect {
protected $login;
protected $haslo;
public function regFilter() {
if (isset($_POST))
{
foreach($_POST as $key => $val)
{
$filterVal = strip_tags($val);
$filterVal = htmlspecialchars($filterVal);
$filterVal = stripslashes($filterVal);
$filterVal = str_replace("\\", "", $filterVal);
$filter = array(
$key => $filterVal
);
foreach($filter as $key => $val)
{
echo "[$$key]";
echo "$val";
$
{
$key
} = $val;
}
}
return $filter = array(
'login' => $login,
'haslo' => $haslo
);
}
else
{
echo "Proszę podać login i hasło!";
}
}
}
Class that will get login and password and send it to DB:
class Dbinsert extends regFilter{
//protected $login;
//protected $haslo;
protected $query;
protected $dbo;
public function insert(){
//$this->extract = extract($filter);
//$this->login = $login;
//$this->haslo = $haslo;
$this->connect();
$this->query = "INSERT INTO uzytkownik (id, nazwa, haslo) VALUES ('', :login, OLD_PASSWORD(:haslo))";
if(!$result = $this->connect()->prepare($this->query)){
echo 'Zapytanie nie powiodło się';
}
else{
$result->bindParam(':login', $login);
$result->bindParam(':haslo', $haslo);
$login = $_POST['login'];
$haslo = $_POST['haslo'];
$result->execute();
}
$dbo = null;
}
}
Now when I try to send data from form with objects:
$rejestruj = new Dbinsert();
$filtruj = $rejestruj->regFilter();
var_dump($filtruj);
$dodaj = $filtruj->insert();
I get the following result:
[$login]login
[$haslo]password123
array(2) { ["login"]= string(5) "login" ["haslo"]= string(11) "password123" }
Fatal error: Call to a member function insert() on array in `E:\Xampp\htdocs\php\bazy_danych\obiektowe\my\register.php` on line 78
Which doesn't surprises me since: login and haslo is returned from
"foreach" loop in class Filter (which is just for testing) "array(2)"
is returned from "var_dump($filtruj);"(to check if it is actually
working) and error is returned since I send an array to Class
Dbinsert - but in the function I put "extract" to get the variables.
How can I send just the variables from this filtered array to class
Dbinsert?
Edit: As #Twinfriends suggested I corrected function insert in class Dbinsert to actually use prepared statement, thats why (for now) login and haslo variables are reffering to $_POST. Now I need answer to my question.
(First time posting, thanks for edit suggestions, also any advice is appreciated since I'm quite the beginner
in PHP)
Sorry that it took so long to answer, I totally forgot your question. Well, lets take a look at your problem, hope to solve it.
I try to explain it as good as I can, so that you understand whats going on. First of all, lets look at your error message
Fatal error: Call to a member function insert() on array in
E:\Xampp\htdocs\php\bazy_danych\obiektowe\my\register.php on line 78
Okay. Call to a function on array... lets have a look at how you actually call the function:
$rejestruj = new Dbinsert();
$filtruj = $rejestruj->regFilter();
var_dump($filtruj);
$dodaj = $filtruj->insert();
And exactly here is your error. You have to understand that you call methods on objects and pass your data to this methods, not to call the methods on your data. What do I mean with that?
$rejestruj is your Dbinsert object. You create it in your first line of code here. Then, you call the regFilter function on it. Still anything is fine. As you see, var_dump gives you the expected results. So the error has to be on your last lane of code. And indeed, you try to call the method insert() on your array. And that won't work, since your array don't know any method called insert().
The right call to the method would be (Not the final one!!!):
$dodaj = $rejestruj->insert();
Now the method call should work. But in fact, it won't insert anything. Why? Because your insert() method try to bind the variables $login and $haslo - two variables the method don't know. So we need to pass the data in your method. To do that, you have to do the following changes:
Method call:
$rejestruj->insert($filtruj); // $filtruj contains your array
And your Dbinsert should look like:
class Dbinsert extends Dbconnect{
protected $query;
protected $dbo;
public function insert($data){
$this->connect();
$this->query = "INSERT INTO uzytkownik (id, nazwa, haslo) VALUES ('', :login, OLD_PASSWORD(:haslo))";
if(!$result = $this->connect()->prepare($this->query)){
echo 'Zapytanie nie powiodło się';
}
else {
$result->bindParam(':login', $data["login"]);
$result->bindParam(':haslo', $data["haslo"]);
$result->execute();
}
$dbo = null;
}
}
I hope your code works with this changes. So, while in my opinion the code should work now, I want to mention that there are many things you could improve. For example, you're not programming real "object-oriented" ... its more some pseudo OOP you're writing here. Some things are quite bad practice (could be done much easier). I don't want to dive to deep into details, since I don't know if you're interested in it. If you wish I can give you some more advises, but only if you wish.
Otherwise I really hope my answer help you. If the whole thing still doesn't work, please let me know so I can look at it again.
Have a nice day ;)
Edit:
Since it seems I haven't been clear enough, here the code how it should look like now:
$rejestruj = new Dbinsert();
$filtruj = $rejestruj->regFilter();
$dodaj = $rejestruj->insert($filtruj);
I'm new learner in php OOP, I want to create a class function to get register users info, how can I do that?
class Functions{
public static function getUserInfo($user_id){
$sql = mysql_query("SELECT * FROM members WHERE user_id='".$user_id."'");
$rows = mysql_fetch_array($sql);
if(mysql_num_rows($sql) >= 1){
return $rows;
}
}
}
to echo user's info:
$user = new Functions();
$user->getUserInfo($_SESSION['user_id']);
echo $user->user_email;
I got nuthing output with 'undefined property' message, what is the proper way to create function to retrieve user's info? thanks.
Maybe that?
class Functions{
public static function getUserInfo($user_id){
if(empty($user_id)) {
return null;
}
// connect to db
$sql = mysql_query("SELECT * FROM members WHERE user_id='".$user_id."' LIMIT 1");
if(mysql_num_rows($sql) > 0){
$row = mysql_fetch_array($sql, MYSQL_ASSOC);
// close connection to db
return $row;
}
// close connection to db
return null;
}
}
$userID = !empty($_SESSION['user_id']) ? (int)$_SESSION['user_id'] : null;
$user = Functions::getUserInfo($userID);
if($user !== null) {
echo $user['user_email'];
}
This is ony example, use mysqli_* or PDO to manage data in database.
mysql_fetch_array returns array, not object.
$user['user_email'] should work.
In general as you mentioned OOP I would say your code is using classes, but it is not OOP (if I understand correctly how you're going to structure it). What you do is simply wrapping procedural code into a class.
With OOP you need to structure code such a way that it has self-contained objects, so creating "Functions" class containing various utility methods is generally a bad idea. Consider e.g. creating User object instead.
For database abstraction I would recommend checking PDO (http://www.php.net/manual/en/class.pdo.php).
I am trying to learn OOP and decided to make a class which uses PDO.Here some codes from my class.
class DB extends PDO {
public function _construct($dsn,$user,$pass,$options=""){
$options = array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION);
try {
parent::__construct($dsn, $user,$pass,$options);
$this->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
}
catch(PDOException $e)
{
echo $e->getMessage();
}
}
public function run($query,$all="",$secure=""){
if(empty($secure)){
$qry=$this->query($query);
}else{
$qry=$this->prepare($query);
$qry->execute($this->cleanup($secure));
}
if($all=="all"){
return $qry->fetchAll(PDO::FETCH_ASSOC);
}else{
return $qry->fetch(PDO::FETCH_ASSOC);
}
}
private function cleanup($secure) {
if(!is_array($secure)) {
if(!empty($secure))
$secure = array($secure);
else
$secure = array();
}
return $secure;
}
public function rowCount($table,$extra=""){
$query="Select count(*) from ".$table;
if(!empty($extra)){
$query="Select count(*) from ".$table." ".$extra;
}
$qry=$this->query($query)->fetchColumn();
return $qry;
}
public function select($table,$extra=""){
$query="Select * from ".$table;
if(!empty($extra)){
$query="Select * from ".$table." ".$extra;
}
return $this->query($query);
}
}
What is difference between following codes why i don't get the same result ?
//usage 1 (it doesnt work that way)
$return =$qry->fetchAll(PDO::FETCH_ASSOC);
return $return;
//usage 2 (it is exactly what i need but i want to learn the difference)
return $qry->fetchAll(PDO::FETCH_ASSOC);
Edit : I realy don't know what I was doing wrong but it seems there is no difference between these usages.They both work now.
This is how I use my method
$result=$db->run("my query","all");
foreach($result as $r){
//
}
In the construct method i use PDO's query method to set character to utf-8 but it does not work. If I use after created a DB object it works.
try {
parent::__construct($dsn, $user,$pass,$options);
$this->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$this->query("SET NAMES 'UTF8'");
$this->query("SET CHARACTER SET UTF8");
}
last question
//what do u think about this usage.I didnt run accross some thing like this
//all the pdo classes i checked use it just
// return $qry->fetchAll(PDO::FETCH_ASSOC);
//do you think i need to separate "fetchAll" and "fetch"
if($all=="all"){
return $qry->fetchAll(PDO::FETCH_ASSOC);
}else{
return $qry->fetch(PDO::FETCH_ASSOC);
}
Don't extend PDO it's just wrong in so many ways. You should instead use it like your title suggests
class Database
{
protected $pdoInstance;
public function __construct($pdoInstance)
{
$this->pdoInstance = $pdoInstance;
}
public function query($query)
{
$preparedStatement = $this->pdoInstance->prepare();
/* bla bla bla */
}
}
This code makes a lot more sense, and is a much better example of good object oriented programming. (It still makes me cringe however, but it's a good start)
First of all, such a good questions can be rarely seen here.
Very few people understand the need of an abstraction class upon PDO.
So, here are some suggestions.
Don't make run into single function. it is much more convenient to have separate methods for different result types. Compare
$data = $db->getAll($sql);
$data = $db->run($sql,"all");
$data = $db->getOne($sql);
$data = $db->run($sql,"one");
$data = $db->getCol($sql);
$data = $db->run($sql,"col");
You need to think of the function names. Your "cleanup" function doesn't do any cleanup.
I would use func_get_args() instead.
What is difference between following codes why i don't get the same result ?
There is no difference
$return = $qry->fetchAll(PDO::FETCH_ASSOC);
return $return;
should work. Define "it doesnt work".
In the construct method i use PDO's query method to set character to utf-8 but it does not work.
Although you should set charset in DSN, this one should be working too. Define "not working"
Also I would suggest to create DSN in the constructor, making config file more familiar.
You may wish also to get some ideas from my mysql helper class. Though it is using different approach from prepared statements, it is way more secure than PDO
I have a function which is using recursion to call itself and I need to know the correct syntax for calling itself.
Note: I am using Object oriented programming technique and the function is coming from a class file.
Below is my function
// Generate Unique Activation Code
//*********************************************************************************
public function generateUniqueActivationCode()
{
$mysql = new Mysql();
$string = new String();
$activation_code = $string->generateActivationCode();
// Is Activation Code Unique Check
$sql = "SELECT activation_id FROM ". TABLE_ACTIVATION_CODES ." WHERE activation_code='$activation_code' LIMIT 1";
$query = $mysql->query($sql);
if($mysql->rowCount($query) > 0)
{
// This function is calling itself recursively
return generateUniqueActivationCode(); // <- Is this syntax correct in Oops
}
else
{
return $activation_code;
}
}
Should the code to call it recursively be
return generateUniqueActivationCode();
OR
return $this->generateUniqueActivationCode();
or if something else other than these 2 ways.
Please let me know.
You would need to call it with the $this variable since your function is part of the instance. So:
return $this->generateUniqueActivationCode();
PS: Why not just try both methods and see if it generates any errors?
Recursion is the COMPLETELY WRONG WAY TO SOLVE THIS PROBLEM
Unlike iteration you're filling up the stack, and generating new objects needlessly.
The right way to solve the problem is to generate a random value within a scope which makes duplicates very unlikely, however without some external quantifier (such as a username) to define the scope then iteration is the way to go.
There are further issues with your code - really you should be adding records in the same place where you check for records.
I am using Object oriented programming technique and the function is coming from a class file
Then it's not a function, it's a method.
And your code is susceptibale to SQL injection.
A better solution would be:
class xxxx {
....
public function generateUniqueActivationCode($id)
{
if (!$this->mysql) $this->mysql = new Mysql();
if (!$this->string) $this->string = new String();
$limit=10;
do {
$activation_code = $string->generateActivationCode();
$ins=mysql_escape_string($activation_code);
$sql="INSERT INTO ". TABLE_ACTIVATION_CODES ." (activation_id, activation_code)"
. "VALUES ($id, '$ins)";
$query = $mysql->query($sql);
if (stristr($query->error(), 'duplicate')) {
continue;
}
return $query->error() ? false : $activation_code;
} while (limit--);
return false;
}
} // end class
I'm trying to create a PHP class extending mysqli that is capable of connecting with another user if the connection fails. It is probably easier to explain with code:
public function __construct() {
$users = new ArrayObject(self::$user);
$passwords = new ArrayObject(self::$pass);
$itUser = $users->getIterator();
$itPass = $passwords->getIterator();
parent::__construct(self::$host, $itUser->current(), $itPass->current(), self::$prefix.self::$db);
while($this->connect_errno && $itUser->valid()){
$itUser->next();
$itPass->next();
$this->change_user($itUser->current(), $itPass->current(), self::$prefix.self::$db);
}
if($this->connect_errno)
throw new Exception("Error", $this->connect_errno);
}
$user and $pass are static variables containing arrays of users and passwords.
If the first user fails to connect, I try with the next one.
The problem here is with $this->connect_errno. It says it cannot find Mysqli.
Is there any solution to this or should I create a Factory class?
Not sure why it doesn't find the object (hint, anybody?), however you can still use mysqli_error() for error handling, as shown in this article.
while(!mysqli_error($this) && $itUser->valid()) {
// (...)
}
and
if(mysqli_error($this)) {
throw new Exception(mysqli_error($this), mysqli_errno($this));
}