Hey guys I am learning OOP in php. I come across some issue, when I try to customize PDO in my own class. Basically I have tried to return the row and fetch it outside my class. Unfortunately I would not work. I get this error "Call to a member function fetch() on a non-object". Have a look and give me some tips if You can. Many thanks.
$connection = new MySql(DBUSER, DBPASS);
$row = $connection->query("select * from users", "name");
while($row->fetch(PDO::FETCH_ASSOC)){
echo "<p>". $row["name"] ."</p>";
}
And here is how the MySql class look like:
class MySql{
private $dbc;
private $user;
private $pass;
function __construct($user="root", $pass=""){
$this->user = $user;
$this->pass = $pass;
try{
$this->dbc = new PDO("mysql:host=localhost; dbname=DBNAME;charset=utf8", $user, $pass);
}
catch(PDOException $e){
echo $e->getMessage();
echo "Problem z Połączeniem do MySql sprawdź haslo i uzytkownika";
}
}
public function query($query, $c1=""){
$mysqlquery = $this->dbc->prepare($query);
$mysqlquery->execute();
return $row = $mysqlquery->fetch(PDO::FETCH_ASSOC);
/* I WANT TO PERFORM COMENTED CODE OUTSIDE THE CLASS
while($row = $mysqlquery->fetch(PDO::FETCH_ASSOC)){
if($c1!=""){
echo "<p>". $row[$c1] ."</p>";
}
}
*/
}
If you want to return $mysqlquery to iterate over it, you have to return $mysqlquery, not just one row.
Here is a better version of your class, with dramatically improved error handling and security. But still awful configurability though.
class MySql{
private $dbc;
function __construct($user="root", $pass=""){
$dsn = "mysql:host=localhost; dbname=DBNAME;charset=utf8";
$opt = array(
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
);
$this->dbc = new PDO($dsn, $user, $pass, $opt);
}
public function query($query, $data = array()){
$stm = $this->dbc->prepare($query);
$stm->execute($data);
return $stm;
}
}
$connection = new MySql(DBUSER, DBPASS);
$stm = $connection->query("select * from users WHERE name = ?", array("name"));
while($row = $stm->fetch()){
echo "<p>". $row["name"] ."</p>";
}
Related
I think I've a problem in understanding how OOP works. I already changed the code that it works, but it isn't the propper way I think. Following scenario (No, I'm not creating a userlogin by myself, its really just for local dev. to understand OOP better):
I've a database.php file:
class Database {
/* Properties */
private $conn;
private $dsn = 'mysql:dbname=test;host=127.0.0.1';
private $user = 'root';
private $password = '';
/* Creates database connection */
public function __construct() {
try {
$this->conn = new PDO($this->dsn, $this->user, $this->password);
} catch (PDOException $e) {
print "Error!: " . $e->getMessage() . "";
die();
}
return $this->conn;
}
}
So in this class I'm creating a database connection and I return the connection (object?)
Then I have a second class, the famous User class (actually I'm not using autoload, but I know about it):
include "database.php";
class User {
/* Properties */
private $conn;
/* Get database access */
public function __construct() {
$this->conn = new Database();
}
/* Login a user */
public function login() {
$stmt = $this->conn->prepare("SELECT username, usermail FROM user");
if($stmt->execute()) {
while($rows = $stmt->fetch()) {
$fetch[] = $rows;
}
return $fetch;
}
else {
return false;
}
}
}
So thatare my two classes. Nothing big, as you see. Now, don't get confued about the function name login - Actually I just try to select some usernames and usermails from database and displaying them. I try to achieve this by:
$user = new User();
$list = $user->login();
foreach($list as $test) {
echo $test["username"];
}
And here comes the problem. When I execute this code, I get the following error message:
Uncaught Error: Call to undefined method Database::prepare()
And I'm not sure that I really understand what causes this error.
The code works well when I change the following things:
Change $conn in database.php to public instead of private (I think thats bad...? But when its private, I can only execute querys inside of the Database class, I'm right? So should I put all these querys in the Database class? I think that's bad, because in a big project it will get become really big..)
And the second change I've to do is:
Change $this->conn->prepare to $this->conn->conn->prepare in the user.php file. And here I've really no Idea why.
I mean, in the constructor of the user.php I've a $this->conn = new Database() and since new Database will return me the connection object from DB class, I really don't know why there have to be a second conn->
Do not create classes such as your Database class as it's rather useless. It would make sense to create a database wrapper if it adds some extra functionality to PDO. But given its current code, better to use vanilla PDO instead.
Create a single $db instance from either vanilla PDO or your database class.
Pass it as a constructor parameter into every class that needs a database connection
database.php:
<?php
$host = '127.0.0.1';
$db = 'test';
$user = 'root';
$pass = '';
$charset = 'utf8';
$dsn = "mysql:host=$host;dbname=$db;charset=$charset";
$opt = [
\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
\PDO::ATTR_DEFAULT_FETCH_MODE => \PDO::FETCH_ASSOC,
\PDO::ATTR_EMULATE_PREPARES => false,
];
$pdo = new \PDO($dsn, $user, $pass, $opt);
user.php
<?php
class User {
/* Properties */
private $conn;
/* Get database access */
public function __construct(\PDO $pdo) {
$this->conn = $pdo;
}
/* List all users */
public function getUsers() {
return $this->conn->query("SELECT username, usermail FROM user")->fetchAll();
}
}
app.php
include 'database.php';
$user = new User($pdo);
$list = $user->getUsers();
foreach($list as $test) {
echo $test["username"],"\n";
}
output:
username_foo
username_bar
username_baz
Check out my (The only proper) PDO tutorial for more PDO details.
I want to pass variables $name and $age from my controller to mpdf view page.
However, it gives me an error: Undefined variable: name.
I tried to pass data in three ways:
1) Created separate methods in Controller getName() and getAge() and call them in a view
2) Send the variables while rendering the page
3) trying to query the age and name from Database directly from view.
All three ways didn't give result. 1 and 3 leads to not loaded page and the second one shows Undefined variable: name error.
View:
<div><?= $name; ?></div>
P.S. I also tried to do like:
<div><?echo $name; ?></div>
<div><?php $name; ?></div>
Controller:
public function actionIndex(){
$this->actionCreateMPDF();
$a = Profile::find('age')->where(['user_id'=>\Yii::$app->user->id])->asArray()->one();
$age = $a['age'];
$n = Profile::find('name')->where(['user_id'=>\Yii::$app->user->id])->asArray()->one();
$name = $n['name'];
return $this->render('index',[
'age' => $age,
'name' => $name,
]);
}
public function actionCreateMPDF(){
$b = true;
$mpdf = new mPDF();
$mpdf->WriteHTML($this->renderPartial('index'));
$mpdf->showImageErrors = true;
$mpdf->Output();
exit;
}
If anyone knows what is my problem please help me :3
Need to pass variables to function actionCreatePdf()
public function actionIndex(){
$profileData = Profile::find()
->select(['age', 'name'])
->where(['user_id'=>\Yii::$app->user->id])
->one();
$age = $profileData->age;
$name = $profileData->name;
$this->actionCreateMPDF($age, $name);
return $this->render('index',[
'age' => $age,
'name' => $name,
]);
}
public function actionCreateMPDF($age, $name){
$b = true;
$content = $this->renderPartial('index',[
'age' => $age,
'name' => $name,
]);
$mpdf = new mPDF();
$mpdf->WriteHTML($content);
$mpdf->showImageErrors = true;
$mpdf->Output();
exit;
}
Basically I need to have a e-mail verification system. For clarity, I will post only needed chunks of code that have impact whatsoever. When user registers, a random 40 string token is generated and sent to them, that code is appended to the route like this:
Route::get('/user/verify/{token}', 'RegisterController#verifyUser');
So when user clicks on that link supposedly route should call this:
RegisterController:
public function verifyUser($token){
$verifyUser = new VerifyUser();
$verifyUser->token = $token;
$verifyUser->getByToken();
$user = new User();
$user->id = $verifyUser->user_id;
$user->get();
if(isset($verifyUser)){
if(!$user->verified){
$user->updateVerifiedStatus();
$status = "Uspešno ste verifikovali e-mail adresu. Sada se možete ulogovati";
} else{
$status = "Već ste se verifikovali.";
}
} else{
return redirect('/')->with('error', "Vaš e-mail ne postoji");
}
return redirect('/')->with('status', $status);
}
verify_user is table which has an id of the user, and the token field, and if user is not registered, there will be no instance of that user in the table, therefore -> if(isset($verifyUser)),
also, user table has an 'verified' field, which is a boolean and stores true and false values, therefore -> if(!$user->verified).
And here are models which are used in the above mentioned controller
VerifyUser:
class VerifyUser
{
public $user_id;
public $token;
public $created_at;
public $updated_at;
public function getByToken()
{
$result =
DB::table('verify_users')
->select('*')
->where('token', $this->token)
->first();
return $result;
}
public function create()
{
$result =
DB::table('verify_users')
->insert([
'user_id' => $this->user_id,
'token' => $this->token,
]);
return $result;
}
}
User
class User
{
public function get()
{
$result =
DB::table('users')
->select('*')
->where('id', $this->id)
->first();
return $result;
}
public function updateVerifiedStatus()
{
$data = [
'verified' => true,
];
$result =
DB::table('users')
->where('id', $this->id)
->update($data);
return $result;
}
}
So, when I click the link, everything passess, I get the success status, which tells me that $user->updateVerifiedStatus() funct is returned succesfully. But, when I check the table, the field is still false, and is not updated. Any ideas?
I am trying to construct an object from a stored procedure will yii.
http://www.yiiframework.com/doc/api/1.1/CDbDataReader
I am unsure how to use the function $dataReader->readObject('image', $image);
to construct an object- anyone any ideas if this is the correct way or if this is very slow way of constructing objects
function __construct($image) {
print "In BaseClass constructor\n";
}
public static function getImageFromAliasTitle($alias_title)
{
// $alias_title =Utils::checkEnteredData($alias_title);
$connection = Yii::app()->db;
$command = $connection->createCommand("CALL get_associated_image_detail(:in_image_alias_title, :in_image_visible, :in_image_approved, :in_album_visible, :in_album_approved)");
$command->bindParam(":in_image_alias_title",$alias_title,PDO::PARAM_STR);
$command->bindValue(":in_image_visible",'1',PDO::PARAM_STR);
$command->bindValue(":in_image_approved",'Yes',PDO::PARAM_STR);
$command->bindValue(":in_album_visible",'1',PDO::PARAM_STR);
$command->bindValue(":in_album_approved",'Yes',PDO::PARAM_STR);
try{
$dataReader = $command->query();
if($dataReader->count() >0)
{
$image = $dataReader->read();
}
$dataReader->readObject('image', $image);
// $image = $dataReader->read();
$dataReader->nextResult();
$album = $dataReader->readAll();
$dataReader->nextResult();
$tag = $dataReader->readAll();
$dataReader->nextResult();
$user_image = $dataReader->readAll();
$dataReader->close();
}
catch(Exception $e){
Yii::log('', CLogger::LEVEL_ERROR, 'Message Here...');
}
return $image;
}
What about this:
foreach($row as $dataReader->readAll()){
echo $row["image"];
}
if It does not help then try to print:
print_r($dataReader->readAll());
I am using PDO for MySQL database connection, selecting, updating and deleting.
But I have a problem with selecting rows with special characters, for instance, I want to select a page title with 'Judge-Fürstová Mila',
Table page,
id title content
1 Judge-Fürstová Mila xxx
SQL,
SELECT *
FROM page
WHERE title = 'Judge-Fürstová Mila'
Returns result if I query via phpmyadmin.
But it return 0 with PDO,
$sql = ' SELECT *
FROM page
WHERE title = ?';
$items = $connection->fetch_assoc($sql,'Judge-Fürstová Mila');
Below is my db class,
class database_pdo
{
# database handler
protected $connection = null;
# make a connection
public function __construct($dsn,$username,$password)
{
try
{
# MySQL with PDO_MYSQL
$this->connection = new PDO($dsn, $username, $password);
$this->connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch (PDOException $e)
{
# call the get_error function
$this->get_error($e);
}
}
# don't forget to add getter method to get $this->connection, it's just a good practice.
public function get_connection()
{
return $this->connection;
}
public function fetch_assoc($query, $params = array())
{
try
{
# prepare the query
$stmt = $this->connection->prepare($query);
# if $params is not an array, let's make it array with one value of former $params
if (!is_array($params)) $params = array($params);
# execute the query
$stmt->execute($params);
# return the result
return $stmt->fetch();
}
catch (PDOException $e)
{
# call the get_error function
$this->get_error($e);
}
}
Have I missed something in my db class or something else?
Try to add charset=UTF-8 in your $dsn, and change
$this->connection = new PDO($dsn, $username, $password);
to
$this->connection = new PDO($dsn, $username, $password, array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"));
I believe it is that SET NAMES utf8 thingie, at least it was in my case