php: variable scope within a class - php

I am getting started with classes and have a variable scope question. I am defining a variable $query in one function and need to use it in a second function. However, the second function is not seeing it.
I guess I could pass $query to outside the class and then pass it along ($instance->QueryExecute($query);). But that seems messy, there is no need for $query to exist outside the class.
What is the correct way of solving this?
Thank you,
Louis.
<?php
class MyProduct {
public function QueryBuild() {
$query = "SELECT * FROM my_product";
}
public function QueryExecute() {
$result = mysql_query($query);
while ($record = mysql_fetch_assoc($result)) {
foreach ($record AS $key => $value) {
$this->product[$record["pro_id"]][$key] = $value;
}
}
}
}
?>

There are two options to solve your problem and the first is (in my opinion) better than the other:
Option 1: Return value
Just tell your build method to return the value and then use it on your other method:
<?php
class MyProduct {
public function QueryBuild() {
$query = "SELECT * FROM my_product";
return $query;
}
public function QueryExecute() {
$result = mysql_query($this->QueryBuild());
while ($record = mysql_fetch_assoc($result)) {
foreach ($record AS $key => $value) {
$this->product[$record["pro_id"]][$key] = $value;
}
}
}
}
Option 2: Object field
You define a field in your class that holds the query. This, however, means that the method QueryBuild() always has to be called before you can call QueryExecute(), which is not particularly reasonable.
<?php
class MyProduct {
private $query;
public function QueryBuild() {
$this->query = "SELECT * FROM my_product";
}
public function QueryExecute() {
$result = mysql_query($this->query);
while ($record = mysql_fetch_assoc($result)) {
foreach ($record AS $key => $value) {
$this->product[$record["pro_id"]][$key] = $value;
}
}
}
}
Some things to note:
Don't use mysql_* functions. They are deprecated and have been replaced with MySQLi and PDO.
Take a look at coding conventions. Method names should start with a small letter, which makes the code easier to read for everybody used to these standards.

You define a property in the class, that said I would like to add that mysql_* functions are deprecated.
<?php
class MyProduct {
private $query;
public function QueryBuild() {
$this->query= "SELECT * FROM my_product";
}
public function QueryExecute() {
$result = mysql_query($this->query);
while ($record = mysql_fetch_assoc($result)) {
foreach ($record AS $key => $value) {
$this->product[$record["pro_id"]][$key] = $value;
}
}
}
}
?>

Related

Functions with `$this` don't work in Base class PHP

I have recently started working with OO PHP and I've come across an error.
I have a base class BaseController.php
and a class DatabaseController.php which extends BaseController.php
At the moment these classes are pretty basic but I want a few reusable functions in Base and overall this has been successful.
However, I am trying to use functions in the Base Controller together and it seems functions with $this->functionName(); don't return anything.
Here is my code to further explain:
Base Controller
public function connectDB() {
$conn = mysqli_connect("localhost", "root", "", "db_name");
return $conn;
}
public function getSource($id) {
$conn = $this->connectDB();
$sql = "SELECT * FROM sources WHERE id = '$id'";
$query = mysqli_query($conn, $sql);
while($row = mysqli_fetch_assoc($query)) {
$name = $row['slug'];
}
return $name;
}
public function mapColumnsToFunctions($row) {
foreach($row as $key => $value) {
if($key == "source") {
$result = $this->getSource($value);
$row["source_slug"] = $result;
}
return $row;
}
}
Database Controller
class DatabaseController extends BaseController {
public function getDataItem($type, $id) {
$conn = $this->connectDB();
$id = $this->checkField($id, "");
$sql = "SELECT * FROM $type WHERE id = '$id'";
$query = mysqli_query($conn, $sql);
$response = array();
while($row = mysqli_fetch_assoc($query)) {
$response[$type][] = $this->mapColumnsToFunctions($row);
}
$response = json_encode($response);
return $response;
}
}
I should be seeing a JSON response with source_slug as a field but this isn't coming through to the feed.
{
"id": "213023",
"name": "Source Name",
"url": "http://sample.url",
"source": "1"
// NO source_slug: "english equiv of 1"
},
mapColumnsToFunctions has a return statement inside the foreach loop. So it returns immediately during the first iteration, even if it hasn't updated anything in $row.
The return statement should be after the loop.
public function mapColumnsToFunctions($row) {
foreach($row as $key => $value) {
if($key == "source") {
$result = $this->getSource($value);
$row["source_slug"] = $result;
}
}
return $row;
}
The loop seems unnecessary (unless it's an abbreviation of what you're really doing). It could be rewritten as:
public function mapColumnsToFunctions($row) {
if (isset($row["source"])) {
$row["slug_source"] = $this->getSource($row["source"]);
}
return $row;
}

Is it possible to make a names of the tables in the database as a methods of my class?

I am very like to use PDO, so it might be on.
Usage could be as:
$m = new MDB();
$m->Users()->GetRec($param);
Users() is a name of table in the database, GetRec($param) is my function.
A way I go looking like this:
class MDB extends DB {
function __construct(){
parent::__construct();
if ($result = $this->pdo->query("SHOW TABLES"))
{
while ($row = $result->fetch(PDO::FETCH_NUM))
{
// this is only my imagination (not working at all)
__set($row[0],true);
}
}
}
// set
public function __set($name, $value)
{
// here could be a method (not properties)
$this->$name = $value;
}
Sure it's all seems not exactly what I want. So I am able to get some suggestions and advices in this question.
upd 1.
Thanks for the magic method __call and now I'm trying to make it within. Watch my updated code:
class MDB extends DB {
function __construct(){
parent::__construct();
}
public function __call( $method, $param )
{
$tables = array();
if ($result = $this->pdo->query("SHOW TABLES"))
{
while ($row = $result->fetch(PDO::FETCH_NUM))
{
$tables[] = $row[0];
}
}
if (in_array($method,$tables))
{
return $this;
}
else
{
return FALSE;
}
}
Well, seems it works for me!
Yes it's possible! The wrong row in your code is:
__set($row[0],true);
There you should call:
$this->$row[0] = true;
Take a look a the simple example below and at the overloading documentation of PHP http://www.php.net/manual/en/language.oop5.overloading.php.
class A{
//The array which will contain your data
private $tables;
function __construct($array){
$counter = 1;
foreach($array as $value){
//That's the right call!
$this->$value = $counter++;
}
}
function __set($name, $value){
$this->tables[$name] = $value;
}
function __get($name){
if (array_key_exists($name, $this->tables)) {
return $this->tables[$name];
}
}
}
$array = array('a1', 'a2', 'a3', 'a4', 'a5');
$a = new A($array);
foreach($array as $key){
echo $a->$key;
}
Hope this help!

PHP - mysql_fetch_object with class name not working

I am trying to build a custom ActiveRecord class and am trying to return MySQL results in an object. The object will be the model.
Here's what I'm doing:
while($object = mysql_fetch_object($result, $this->_model)) {
foreach($object as $key => $val) {
if($this->is_serialized($val)) $object->$key = unserialize($val);
}
$return_value[] = $object;
}
If I do a print_r() on the result, I get an empty class (no variables have been set or anything).
Here is my model:
class User extends ActiveRecord {
public $_hasOne = "Profile";
public $_required = array('full_name', 'user_name', 'password', 'country');
public $_unique = array('full_name', 'user_name');
}
I can't figure out what I'm doing wrong!
EDIT: Fixed it in the end. At the beginning of my Activerecord class I had this:
$fields = $this->query("SHOW COLUMNS FROM " . $this->_table);
while($field = mysql_fetch_assoc($fields)) {
$this->_columns[] = $field['Field'];
$this->$field['Field'] = null;
}
Which was setting all the values to NULL!
Bit of a silly mistake. It's now:
$fields = $this->query("SHOW COLUMNS FROM " . $this->_table);
while($field = mysql_fetch_assoc($fields)) {
$this->_columns[] = $field['Field'];
if(!isset($this->$field['Field'])) $this->$field['Field'] = null;
}
Stupid question, but $this->_model is "User" right (I'd echo that value, it might have gotten unset somehow).
After that, your class should have fields by the same names as the columns which you want to represent. So:
class Foo
{
private $id;
public $val;
public function __toString(){ return "$this->id => $this->val"; }
}
mysql_connect('localhost','root','');
$q = mysql_query('SELECT 1 as id, 2 as val FROM DUAL');
$foo = mysql_fetch_object( $q, 'Foo' );
echo $foo; // 1 => 2
Next, you can't iterate over an object. You need to iterate over object properties:
foreach(get_object_vars($object) as $key => $val) {
if($this->is_serialized($val)) $object->$key = unserialize($val);
}

PHP class: Unable to access array in another function

I tried a lot of search but unable to figure out why array $wordlinks in function DoWordLink is not carrying values from function __construct. PHP class code as below:
<?php
class autolinkkeyword
{
public $wordlinks = array();
public function __construct(){
$query = mysql_query("SELECT keyword FROM library");
while ($row = mysql_fetch_array($query))
{
$this->wordlinks [$row["keyword"]] = $row["keyword"];
}
}
public function linkkeywords ($posts)
{
function DoWordLink($match)
{
$rpl=$match[1];
if(isset($wordlinks[$rpl]))
{
$kword = $this->wordlinks[$rpl];
$rpl="<a class=\"keyword_link\" href=\"#\" onclick=\"popup('popUpDiv');
ajax_loadContent('kword', 'library.php?keyword=$kword')\">$kword</a>";
unset($this->wordlinks[$match[1]]);
}
return $rpl;
}
$wl=array_keys($this->wordlinks);
$pm="/((?<=\s|^)(?:" . implode('|',$wl) .")(?=\.|\!|\?|\,|\'|\s|$))/im";
foreach($posts as $key => $mainbody)
{
$mainbody=preg_replace_callback($pm, 'DoWordLink', $mainbody) ;
echo $mainbody;
}
}
}
?>
You can make it an actual method of that class and call it using this method:
http://www.php.net/manual/en/language.pseudo-types.php#language.types.callback
like:
preg_replace_callback($pm, array($this, 'DoWordLink'), $mainbody);
Change DoWordLink function so it is part of the class like:
class autolinkkeyword
{
function DoWordLink($match)
{
$rpl=$match[1];
if(isset($this->wordlinks[$rpl]))
{
$kword = $this->wordlinks[$rpl];
$rpl="<a class=\"keyword_link\" href=\"#\" onclick=\"popup('popUpDiv');
ajax_loadContent('kword', 'library.php?keyword=$kword')\">$kword</a>";
unset($this->wordlinks[$match[1]]);
}
return $rpl;
}
}
aren't you missing a "this->" construct here? if(isset($this->wordlinks[$rpl]))
Use the $this everywhere you refer to $wordlinks.
$this->wordlinks
You need to access the property in your linkkeywords-method with the object-accessor, too!
public function linkkeywords ($posts)
{
// Here use $this->wordlinks not $wordlinks
}

Object Oriented PHP Arrays

I've never tried OO PHP before so I decided to make a simple CMS to learn more. I am having a problem loading values into a multi-dimensional array.
class Article {
private $index = 0;
private $article;
public function Article() {
$get_articles = mysql_query("SELECT * FROM `articles`");
while ($result = mysql_fetch_array($get_articles)) {
echo $result["article"];
$this->article[$index]["Tags"] = $result["tags"];
$this->article[$index]["Categories"] = $result["categories"];
$this->article[$index]["Date"] = $result["date"];
$this->article[$index]["Article"] = $result["article"];
$this->article[$index]["URL"] = $result["url"];
$index++;
}
}
public function getArticle($articleID) {
return $this->article[$articleID]["Article"];
}
public function getTags($articleNumber) {
}
public function getCategories($articleNumber) {
}
public function getDate($articleNumber) {
}
}
The line echo $result["article"] outputs the one and only article value just fine, but apparently doesn't put it into the array?
$art = new Article();
echo $art->getArticle(0);
This doesn't output the article however. Would someone so kindly point out my noob mistake?
You didn't initialize your array.
$this->article = array();
while ($result = mysql_fetch_array($get_articles)) {
$this->article[$index] = array();
You probably should define your $index variable before using it in the loop. Maybe set it to the primary key field you retrieved from your query.
<?php
$index = $result['id'];
$this->article[$index]['tags'] = ...
You also need to initialize the $article member variable.
<?php
class Article {
private $article = array();
Remember that you define member variables within a class to be referenced via $this-> so you also don't need to define private $index = 0; in your class definition. Just define it inside the method.
You'll notice you used $this->article but not $this->index if you want to keep track of the length for the life of the object you'll need to replace $index with $this->index

Categories