i have problem in MYSQL select in OOP PHP. i do not know how to write it correct.
my code is:
$sql = "SELECT name_mcategory
FROM web_main_category WHERE userid=('".$userid."')";
$result = mysql_query($sql);
$e=0;
$maincat=array ();
while($data=mysql_fetch_array($result))
{
$maincat[$e]=$data['name_mcategory'];
$e++;
}
how to write it in the OOP? i have tried this but it was not working.
class nweb {
var $userid;
var $mcategory;
function Getmain_category () {
$rs = mysql_query("SELECT name_mcategory
FROM web_main_category WHERE userid=$this->userid");
}
$this->tab=mysql_fetch_object($rs);
}
}
in the print page
$mcat = new nweb();
$mcat->getmain_category ();
$mcat->mcategory=$this->name_mcategory;
how to get data like a $maincat[$e]=$data['name_mcategory'];
If you want to use OOP, then use an OOP DB Layer like PDO:
class nweb extends PDO {
public $userid, $mcategory;
public function __construct($hostname, $dbname, $username, $password) {
parent::__construct($hostname,$dbname,$username,$password);
}
public function getmain_category() {
return $this->query("SELECT name_mcategory FROM web_main_category WHERE userid = {$this->userid}")->fetch();
}
}
$mcat = new nweb('hostname', 'dbname', 'username', 'password');
var_dump($mcat->getmain_category());
Note: You add some error handing, see pdo::query.
In OOP we usually make a separate class to handle the database operation . For example Database.php
so it executes the query and return the result to Category.php or make Category inherit Database.php.
If you want a better way use the PHP Activerecord.
check like this
class nweb {
var $userid;
var $mcategory;
function getmain_category () {
$rs = mysql_query("SELECT name_mcategory
FROM web_main_category WHERE userid = {$this->userid}");
return mysql_fetch_object($rs);
}
}
//print page
$mcat = new nweb();
$data = $mcat->getmain_category ();
$e=0;
$maincat=array ();
while($data=mysql_fetch_array($result))
{
$maincat[$e]=$data['name_mcategory'];
$e++;
}
Related
I'm working on a Content Management System for My wife who wants to create a website, and I have a way I've always done things within the past, but I want to deliver better coding procedures, so this is my dilemma.
This is Code I've used in the past that I know works.
class accounts {
public function CheckAccountLogin() {
global $db;
$query = <<<SQL
SELECT id,gaToken
FROM accounts
WHERE password_hash = :hashedpw
SQL;
$resource = $db->sitedb->prepare( $query );
try {
$resource->execute( array (
':hashedpw' => sha1($_POST['user-name'].':'.$_POST['user-pass']),
));
if($resource->rowCount() == 0 ) { echo false;}
else {
foreach($resource as $row) {
$this->authkey = $row['gaToken'];
if($this->authkey == "") {
self::SetSession();
}
else {
self::CheckAuth();
}
}
}
catch(PDOException $e) {
echo $e->getMessage();
}
}
}
Now every function would need global $db at the start of the function in order to utilize $db->sitedb or else we would have an error thrown our way, so what I want to do instead is
class accounts {
public $db = new db();
public function CheckAccountLogin() {
$query = <<<SQL
SELECT id,gaToken
FROM accounts
WHERE password_hash = :hashedpw
SQL;
$resource = $this->sitedb->prepare( $query );
try {
$resource->execute( array (
':hashedpw' => sha1($_POST['user-name'].':'.$_POST['user-pass']),
));
if($resource->rowCount() == 0 ) { echo false;}
else {
foreach($resource as $row) {
$this->authkey = $row['gaToken'];
if($this->authkey == "") {
self::SetSession();
}
else {
self::CheckAuth();
}
}
}
catch(PDOException $e) {
echo $e->getMessage();
}
}
}
This way within all my new functions I'm able to simply declare $this->sitedb whenever I need to connect to the database. With the above code I'm given
Parse error: syntax error, unexpected 'new' (T_NEW) in /var/www/html/functions.d/accounts.class.php on line 3. I know where the issue is, I'm just looking for a cleaner way than my first code block. Any help in getting this to work correctly would be greatly appreciated.
You can't initialize a variable there unless it can be evaluated at compile time. So you can't call new there. See the docs. Do it in the constructor.
class accounts {
public $db;
public function __construct() {
$this->db = new db();
}
}
You can create a global class DbConnect where you statically define the database object db and connect it to your database, in this way you will keep a single database connection object throughout your application.
Include this class at the beginning before any code, then you can access this object anywhere through :: operator in any class that follows.
I am using PHP with OOP to select rows from the database (MySQL).
When I execute the query, it returns an empty row.
Here is the classe I am using:
<?php
class EmploiManager
{
private $_db;
public function __construct($db)
{
$this->setDb($db);
}
public function category($category)
{
$q = $this->_db->prepare('SELECT * FROM DemandeEmploi WHERE category = :category');
$q->execute(array('category' =>$category));
$donnees = $q->fetch(PDO::FETCH_ASSOC);
return new Emploi($donnees);
}
public function setDb(PDO $db)
{
$this->_db = $db;
}
}
$type = $_GET['category'];
$manager = new EmploiManager($db);
$row = $manager->category($type);
foreach ($row as $demandeE)
{
?>
<div class="list"><h4><? echo $demandeE->title();?></h4> </div>
<?php
}
?>
Can any one tell me what's wrong with that code?
Thanks!
It's my bad, I didn't use a loop to select all the rows.
I corrected the code and it works fine now, here is what it looks like:
public function category($category)
{
$datas = array();
$q = $this->_db->prepare('SELECT * FROM DemandeEmploi WHERE category = :category');
$q->execute(array('category' =>$category));
while ($donnees = $q->fetch(PDO::FETCH_ASSOC))
{
$datas[] = new Emploi($donnees);
}
return $datas;
}
$q->fetch() just returns one row of the results. If you want all the results, you must use $q->fetchAll().
Since you specified PDO::FETCH_ASSOC, the elements of $row will be associative arrays, not objects; aren't you getting errors saying that you're trying to call a method on a non-object? So $demandeE->id() should be $demandeE['id'], and $demandeE->title() should be $demandeE['title'].
Alternatively, you could specify PDO::FETCH_OBJ. Then, the values will be properties, not methods, so it should be $demandeE->id and $demandeE->title (no parentheses).
I am trying to make a 1 on 1 chat website by learning as I progress, but I've come to a hault.
I can't write to the database.
I have four php files linked below.
Index
Init:
session_start();
define('LOGGED_IN', true);
require 'classes/Core.php';
require 'classes/Chat.php';
?>
Chat
Core:
class Core {
protected $db, $result;
private $rows;
public function __construct() {
$this->db = new mysqli("localhost","root","");
}
public function query($sql) {
$this->result = $this->db->query($sql);
}
public function rows() {
for($x = 1; $x <= $this->db->affected_rows; $x++) {
$this->rows[] = $this->result->fetch_assoc();
}
return $this->rows;
}
}
?>
I have a MySql database set with WAMP.
P.S. Yes, I have opened the "< ? php"
but it doesn't get displayed here.
From what I have seen you do not select a default database. You must either give a default database in
$this->db = new mysqli("localhost","root","", "mydatabase");
or select one later with
$this->db->select_db("mydatabase");
You also don't check the return values of the mysql calls. For example, add
public function query($sql) {
$this->result = $this->db->query($sql);
if ($this->result === false) {
echo $this->db->error;
}
}
after your mysql statements, in order to see whether the statements succeed or fail.
For debugging purposes you can display the sql and corresponding result
public function query($sql) {
var_dump($sql);
$this->result = $this->db->query($sql);
var_dump($this->result);
echo $this->db->error;
}
Code snippet for class lnemail_fetch
<?php Part of heritage_classes.php
// Declare classes
class lnemail_fetch {
// return string in format "title | factoid"
public $result;
public function get_ln_info()
{
include ("./includes/LOheritage-config.php");
mysql_connect("$dbhost", "$dbuser", "$dbpass") or die(mysql_error());
mysql_select_db("$dbname") or die(mysql_error());
$query = "SELECT * FROM lnemail";
$result = mysql_query($query);
$this->result = $result;
}
}
?>
Code Snippet from larger program It lists a MySQL table
require_once('./includes/heritage_classes.php');
$newlnemail_fetch = new lnemail_fetch;
$newlnemail_fetch->get_ln_info();
$newresult = $newlnemail_fetch->result;
echo "lnemail File display <br />";
while($row = mysql_fetch_array($newresult))
{
echo $row['ln_email']. " | " . $row['ln_date'] . " | " . $row['ln_week'] ;
echo "<br />";
}
Is this use of PHP OOP considered good practice even though it works nicely for now?
I would say no, it's no good use of OOP.
Areas for improvement:
Separate the db connection and query stuff.
Separate the db result handling. Implementing a result object that is iterable will be a good idea.
Not using the mysql extension and switching to mysqli is a very good idea. It will also give you an OOP interface to MySQL for free.
Probably aspects of escaping input inside SQL strings should be considered, but this is undecidable because no such code has been shown.
Will some future release break it?
Yes, because you are using the old and (now) deprecated mysql_* functions.
Code snippet for class lnemail_fetch
The name lnemail is not really a good name for a class, because when I look at it I have no idea what ln means. Also class names are often UpperCamelCased and methods camelCased.
Now to actually look at your code:
When looking at your class it is just a class and currently has nothing to do with OOP. What I would have done is make the $result property private, because currently your is simply some container for data. Also I would introduce another class which will be reponsible for accessing the data from the database (or whatever storage you have). I would also introduce another class to represent a single email and an factory class to build these mail objects. This would look something like the following:
// not sure whether inbox is the correct name, because I don't really have a good idea of what the class represents
class Inbox
{
private $storage;
private $mailFactory;
public function __construct($storage, $mailFactory)
{
$this->storage = $storage;
$this->mailFactory = $mailFactory;
}
public function fetchAllMails()
{
$mailRecordset = $this->storage->fetchAll();
$mails = array();
foreach ($mailRecordset as $mailRecord) {
$mails[] = $this->mailFactory->create($mailRecord);
}
return $mails;
}
}
class InboxStorage
{
private $dbConnection;
public function __construct(\PDO $dbConnection)
{
$this->dbConnection = $dbConnection;
}
public function fetchAll()
{
$stmt = $this->dbConnection->query('SELECT * FROM lnemail');
return $stmt->fetchAll(\PDO::FETCH_ASSOC);
}
}
class Email
{
private $email;
private $date;
private $week;
public function __construct($email, $date, $week)
{
$this->email = $email;
$this->date = $date;
$this->week = $week;
}
public function getEmail()
{
return $this->email;
}
public function getDate()
{
return $this->date;
}
public function getWeek()
{
return $this->week;
}
}
class EmailFactory
{
public function create($record)
{
return new Email($record['email'], $record['date'], $record['week']);
}
}
And you can run it like following:
// initialize all the objects we are going to need
$emailFactory = new EmailFactory();
$dbConnection = new \PDO('mysql:dbname=dbtest;host=127.0.0.1;charset=utf8', 'user', 'pass');
$dbConnection->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$dbConnection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$inboxStorage = new InboxStorage($dbConnection);
$inbox = new Inbox($inboxStorage, $mailFactory);
// run the code
foreach($inbox->fetchAllMails() as $email) {
echo $mail->email . ' | ' . $mail->date . ' | ' . $mail->week . '<br>';
}
It's not really a true class because lnemail_fetch isn't an object. All you are doing is making a container and having to make the container merely to call a function that could be static and return the result rather than assign it.
A better class might include the newer mysqli rather than the dated mysql and work as follows. It makes the rows into objects with the columns being properties (variables;
<?php
class lnemail {
public $ln_emai;
public $ln_date;
public $ln_week;
public static function Fetch($dbhost,$dbuser,$dbpass,$dbname) {
$db = new mysqli($dbhost, $dbuser, $dbpass,$dbname) or die(mysql_error());
$query = "SELECT * FROM lnemail";
$result = $db->query($query);
$returnArr = array();
while($obj = $result->fetch_object('lnemail') {
$returnArr[] = $obj;
}
return $returnArr;
}
}
Then
<?php
require_once("./includes/LOheritage-config.php");
require_once('./includes/heritage_classes.php');
$lnemails = lnemail::Fetch($dbhost,$dbuser,$dbpass,$dbname);
echo "lnemail File display <br />";
foreach($obj as $lnemail) {
echo $obj->ln_email. " | " . $obj->ln_date . " | " . $obj->ln_week;
echo "<br />";
}
I can do this when selecting a single row fine but cant quite get my head around doing this for multiple rows of data.
For the single row I simply instantiate a new object that does a number of operations behind the scenes that bascially produces a row from the database as our object.
Example:
$object = new Classname($param);
foreach($object->row as $key=>$value) {
echo $key.":".$value."\n";
}
//output
id:1
firstname:steve
lastname:took
etc...
Any clever people here able to point me in the right direction please?
NOTE: just want to be able to create an object for each row rather than the one object with nested arrays
EDIT: sorry $object->row is a member of the class that stores selected row from the database
If I got you the answer is pretty simple mysql_fetch_object
Example:
while ($row = mysql_fetch_object($result)) {
echo $row->user_id;
echo $row->fullname;
}
Why don't you consider to use an ORM (Object Relational Mapper), like Doctrine or Propel?
I prefer Doctrine: http://www.doctrine-project.org/
Enjoy! :)
Here is an example
class users extends db {
public $users_id = 0;
public $users_group = 0;
public $users_firstname = 0;
public $users_lastname = 0;
public function open($id) {
if (is_numeric($id)) {
$sql = "SELECT * FROM users WHERE users_id = '$id'";
$res = parent::DB_SELECT($sql);
if (mysql_num_rows($res) <> 1) {
return 0;
}
} else {
$sql = "SELECT * FROM users " . $id;
$res = parent::DB_SELECT($sql);
if (mysql_num_rows($res) <= 0) {
return 0;
}
}
$data = array();
while ($row = mysql_fetch_array($res)) {
$this->users_id = $row['users_id'];
$this->users_group = $row['users_group'];
$this->users_firstname = $row['users_firstname'];
$this->users_lastname = $row['users_lastname'];
$data[] = (array) $this;
}
return $data;
}
public function setUsersId($users_id) { $this->users_id = addslashes($users_id); }
public function getUsersId() { return stripslashes($this->users_id); }
public function setUsersGroup($users_group) { $this->users_group = addslashes($users_group); }
public function getUsersGroup() { return stripslashes($this->users_group); }
public function setUsersFirstname($users_firstname) { $this->users_firstname = addslashes($users_firstname); }
public function getUsersFirstname() { return stripslashes($this->users_firstname); }
public function setUsersLastname($users_lastname) { $this->users_lastname = addslashes($users_lastname); }
public function getUsersLastname() { return stripslashes($this->users_lastname); }
}
You could use MySQLi.
// Connect
$db = new mysqli('host', 'user', 'password', 'db');
// Query
$users = $db->query('SELECT * from users');
// Loop
while($user = $users->fetch_object()) {
echo $users->field;
}
// Close
$users->close();
$db->close();
More info here: http://php.net/manual/en/book.mysqli.php