Using the same variable in two functions

Hi everyone,

I am currently in the process of making some upgrades to a CMS and website that somebody else built. I understand PHP moderately well, but I don’t do OOP - which this website is - so it’s been a bit struggletown. I’ve managed to make most of the changes I want, but there’s one particular bit I just can’t figure out.

Basically, the website is a catalogue sort of thing which gets a list of products from a database (Page A, using function A), and when the user clicks on a product, gets further details about the product (Page B, using function B), also from the database. It’s pretty straightforward stuff.

Now, what I want to do is display a list of the 5 most recently viewed items, on both Page A and Page B. My idea of how to do this was to use sessions and an array, with array_push and array_shift to keep track of the product IDs as the user clicks on more products. I would then use this array in a function (function C) that outputs the thumbnails and stock number of the recently viewed products.

My problem is, I need to get the product ID into the array in function B, and then use the array in function C - and I just can’t seem to make this happen, or even work out if it’s possible.

I hope that’s not confusing. I’m just wondering if anyone can tell me whether what I want is possible - or even if it is completely stupid to try and do the recently viewed items in this way.

I don’t have any code that is remotely working, all I was doing was trying to use:

$GLOBALS['recentItems'] = $arrayOfRecentItems;

in function B. To my knowledge, this should output “Array” when I then use:

echo $GLOBALS['recentItems'];

in function C, if it was working - which it’s not.

Thanks in advance for any help!

Are you sure the $arrayOfRecentItems is actually an array?

If you’re storing it in the session, then you should be able to do something like:



function B() {

  array_push( $_SESSION[ 'recentItems' ], $item_id );

}
// B


function C() {

  foreach ( $_SESSION[ 'recentItems' ] as $item_id ) {

    ...

  }
  // foreach

}
// C


For debugging in function C, try var_dump() instead of echo.

Other than that, if B and C are object methods and you need to share data between them, you can store the data in an object property in B and access it in C, e.g.



class Products {

  function B() {

    array_push( $this->recentItems, $item_id );

  }
  // B


  function C() {

    foreach ( $this->recentItems as $item_id ) {

      ...

    }
    // foreach

  }
  // C

}
// Products


HTH

Thanks for that! I have no idea what you mean by “object methods” but that same syntax (with the ->, which I also don’t really quite understand) is used elsewhere in the code, so this sounds like we’re on the right track. Haven’t had time to try and implement it yet, I’ll give it a bash and see how I get on.

And yes, $arrayOfRecentItems is an array, but only in Function B - in Function C it is completely unknown.

OK, I’ve given that a go and no success. Not sure if I’m quite doing it properly though. I have made a stripped back version of the code (Functions B and C, not Function A), if anyone has any suggestions as to what I’m doing wrong.

class products {
		
private $sqlResult = false;
public $product_code = "";
public $product_pagetitle = "";
public $product_pagedescription = "";
public $category_name = "";
public $category_url = "";
public $category_img = "";
public $recentItems = array();
				
				
function load_product( $id ) {
				
	if ( !is_numeric( $id ) ) 
	die("Fatal error: The product id supplied was not a numeric value");
								
	array_push( $this->recentItems, $id );
								
	$mysql = new mysql();
						
	// get product details
	$mysql->execute("Select * from productsNew where ProductId = $id");
	$this->sqlResult = $mysql->getRow();
						
						
	//get product cateogry details
	$mysql->execute("Select CategoryName, url, cat_img from category where CategoryID = " . $this->sqlResult["CategoryID"]);
	$row = $mysql->getRow();
	$this->category_name = $row["CategoryName"];
	$this->category_url = $row["url"];
	$this->category_img = $row["cat_img"];
						
	$this->product_pagetitle = $this->sqlResult["Metal_Type"] . " " . $this->category_name . " - Kimberley Fine Diamonds";
	$this->product_pagedescription = $this->sqlResult["Metal_Type"];
	$this->product_code = $this->sqlResult["Stock_No"];
}
				
				
function recentlyViewed() {

	foreach ($this->recentItems as $item_id ) {      
					
	echo "id is: " . $item_id;
					
	} 
					
					
}
}

Any furhter help appreciated!

Also just an update to say, I did a little bit further testing, by adding the foreach loop in load_product like so:

function load_product( $id ) {
				
	if ( !is_numeric( $id ) ) 
	die("Fatal error: The product id supplied was not a numeric value");
								
	array_push( $this->recentItems, $id );
						
	foreach ($this->recentItems as $id ) {      
					
		echo "id is: " . $id;
					
	} 
								
	$mysql = new mysql();
						
	// get product details
	$mysql->execute("Select * from productsNew where ProductId = $id");
	$this->sqlResult = $mysql->getRow();
						
						
	//get product cateogry details
	$mysql->execute("Select CategoryName, url, cat_img from category where CategoryID = " . $this->sqlResult["CategoryID"]);
	$row = $mysql->getRow();
	$this->category_name = $row["CategoryName"];
	$this->category_url = $row["url"];
	$this->category_img = $row["cat_img"];
						
	$this->product_pagetitle = $this->sqlResult["Metal_Type"] . " " . $this->category_name;
	$this->product_pagedescription = $this->sqlResult["Metal_Type"];
	$this->product_code = $this->sqlResult["Stock_No"];
}

This outputs only the id of the product I am currently on, which is maybe what one would expect from that code? What I am really after for it to do though, is show all the ids of the products I have recently clicked on. I also tried the code which uses $_SESSION, as it seems closest to what I am trying to do, but unfortunately this also did not work.

Do you mean the 5 items most recently viewed by a user in just their current session or the 5 items most recently viewed by all users in all sessions.

if it’s the former, then all you need is a session array storing the last 5 prod_id’s that were clicked.

  1. use array_push() until you have 5 elements in the session array

  2. after 5 elements are reached, then on subsequent product clicks use array_slice() to remove the 1st element (the oldest element) then array_push() the new prod_id to the session array to maintain 5 elements.

  3. you can then use the session array in a for or foreach loop to display images, info or whatever for the 5 prod_id’s in the array.

hopefully the logic in this demo code will help.

it displays the last 5 product links clicked and ignores duplicates if the product_id is already in the array.

 
<?php
session_start();
 
if (isset($_GET['txtProdId'])) {
    $prodId = $_GET['txtProdId'];
}
 
if (!isset($_SESSION['visitedProds'])) {
    $_SESSION['visitedProds'] = array();
}
 
if (count($_SESSION['visitedProds']) < 5) {
    if (!in_array($prodId, $_SESSION['visitedProds'])) {
        array_push($_SESSION['visitedProds'], $prodId);
    }
} else {
    if (!in_array($prodId, $_SESSION['visitedProds'])) {
        $_SESSION['visitedProds'] = array_slice($_SESSION['visitedProds'], 1);
        array_push($_SESSION['visitedProds'], $prodId);
    }
}
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <title></title>
        <style type="text/css">
            a {display: block}
        </style>
    </head>
    <body>
 
        <div>
            <a href="<?php echo $_SERVER['PHP_SELF'] ?>?txtProdId=1">prod 1</a>
            <a href="<?php echo $_SERVER['PHP_SELF'] ?>?txtProdId=2">prod 2</a>
            <a href="<?php echo $_SERVER['PHP_SELF'] ?>?txtProdId=3">prod 3</a>
            <a href="<?php echo $_SERVER['PHP_SELF'] ?>?txtProdId=4">prod 4</a>
            <a href="<?php echo $_SERVER['PHP_SELF'] ?>?txtProdId=5">prod 5</a>
            <a href="<?php echo $_SERVER['PHP_SELF'] ?>?txtProdId=6">prod 6</a>
            <a href="<?php echo $_SERVER['PHP_SELF'] ?>?txtProdId=7">prod 7</a>
            <a href="<?php echo $_SERVER['PHP_SELF'] ?>?txtProdId=8">prod 8</a>
            <a href="<?php echo $_SERVER['PHP_SELF'] ?>?txtProdId=9">prod 9</a>
            <a href="<?php echo $_SERVER['PHP_SELF'] ?>?txtProdId=10">prod 10</a>
        </div>
 
        <div>
            <h3> Most Recent Visited Products</h3>
            <?php
            foreach ($_SESSION['visitedProds'] as $prodId) {
                echo '<p>' . $prodId . '</p>';
            }
            ?>
        </div>
 
    </body>
</html>

ignore my previous post.

this is a better version of the demo.

 
<?php
session_start();
 
if (isset($_GET['txtProdId'])) {
    $prodId = $_GET['txtProdId'];
    if (!isset($_SESSION['visitedProds'])) {
        $_SESSION['visitedProds'] = array();
    }
 
    if (!in_array($prodId, $_SESSION['visitedProds'])) {
        if (count($_SESSION['visitedProds']) < 5) {
            array_push($_SESSION['visitedProds'], $prodId);
        } else {
            $_SESSION['visitedProds'] = array_slice($_SESSION['visitedProds'], 1);
            array_push($_SESSION['visitedProds'], $prodId);
        }
    }
}
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <title></title>
        <style type="text/css">
            a {display: block}
        </style>
    </head>
    <body>
 
        <div>
            <a href="<?php echo $_SERVER['PHP_SELF'] ?>?txtProdId=1">prod 1</a>
            <a href="<?php echo $_SERVER['PHP_SELF'] ?>?txtProdId=2">prod 2</a>
            <a href="<?php echo $_SERVER['PHP_SELF'] ?>?txtProdId=3">prod 3</a>
            <a href="<?php echo $_SERVER['PHP_SELF'] ?>?txtProdId=4">prod 4</a>
            <a href="<?php echo $_SERVER['PHP_SELF'] ?>?txtProdId=5">prod 5</a>
            <a href="<?php echo $_SERVER['PHP_SELF'] ?>?txtProdId=6">prod 6</a>
            <a href="<?php echo $_SERVER['PHP_SELF'] ?>?txtProdId=7">prod 7</a>
            <a href="<?php echo $_SERVER['PHP_SELF'] ?>?txtProdId=8">prod 8</a>
            <a href="<?php echo $_SERVER['PHP_SELF'] ?>?txtProdId=9">prod 9</a>
            <a href="<?php echo $_SERVER['PHP_SELF'] ?>?txtProdId=10">prod 10</a>
        </div>
 
        <div>
            <h3> Most Recent Visited Products</h3>
<?php
if (isset($_SESSION['visitedProds'])) {
    foreach ($_SESSION['visitedProds'] as $prodId) {
        echo '<p>' . $prodId . '</p>';
    }
}
?>
        </div>
    </body>
</html>

Yeah, you’d definitely need to use that version to accomplish what you were talking about. My second code example was just showing how to share data between 2 object methods in general. I’d suggest posting your code using $_SESSION. Have you verified that you’re successfully able to store any data in the session? In the code using $_SESSION, have you tried var_dump( $_SESSION[ ‘recentItems’ ] ) in recentlyViewed()?

OK, so I tried the $_SESSION version again, which still doesn’t work for me. The problem I’m having with it doesn’t even relate to the recentlyViewed() function - I’m not even getting it happening within load_product().

THis is the code:

class products {          

private $sqlResult = false; 
public $product_code = ""; 
public $product_pagetitle = ""; 
public $product_pagedescription = ""; 
public $category_name = ""; 
public $category_url = ""; 
public $category_img = ""; 
public $recentItems = array();                                   

function load_product( $id ) {
				
	if ( !is_numeric( $id ) ) 
	die("Fatal error: The product id supplied was not a numeric value");
								
	array_push($_SESSION['recentItems'], $id);
						
	echo var_dump($_SESSION['recentItems']); 
								
	$mysql = new mysql();
						
	// get product details
	$mysql->execute("Select * from productsNew where ProductId = $id");
	$this->sqlResult = $mysql->getRow();
						
						
	//get product cateogry details
	$mysql->execute("Select CategoryName, url, cat_img from category where CategoryID = " . $this->sqlResult["CategoryID"]);
	$row = $mysql->getRow();
	$this->category_name = $row["CategoryName"];
	$this->category_url = $row["url"];
	$this->category_img = $row["cat_img"];
						
	$this->product_pagetitle = $this->sqlResult["Metal_Type"] . " " . $this->category_name . " - Kimberley Fine Diamonds";
	$this->product_pagedescription = $this->sqlResult["Metal_Type"];
	$this->product_code = $this->sqlResult["Stock_No"];
	}
}

Now my var_dump there gives me “NULL”, which to me would seem to be because it doesn’t know that $_SESSION[‘recentItems’] is an array.

So then I tried the same code as above with the addition of

$_SESSION['recentItems'] = array();

Great! Now it knows that variable is an array - but only ever stores one value i.e. the array_push() part is not actually working. I’m guessing this is because I’m declaring the variable type anew every time?

Also just to see, I tried var_dump in recentlyViewed() with this second version, and it came back with “NULL”, so no - I’m not able to store data in the variable in a manner that is visible to both the functions.

I just don’t get how or where one is supposed to declare a variable so that it is able to be used properly! I would have thought it was up the top with the other variables, but apparently not . . .

Oh and thanks again for the help, and thanks for your suggestions Kalon - that’s definitely what I’m after, and is in fact how I would do it myself - but unfortunately that doesn’t work with the classes.

I don’t see why it shouldn’t but it’s your call how you want to do it.

The code I posted is just a standalone demo, but you could add the code at the top of what I posted as a separate method in a products handling class, albeit with a couple of minor changes, or include it in an existing class method.

Another option is to put the code in a separte “include” file and include() it on pages where you have links to click products and the foreach loop at the bottom of my code could be also added as either a class method or in an include() file.

But it’s up to you if and/or how you use it.

That’s actually exactly what I’ve been trying to do, and what, so far, I’ve been unable to achieve.

My recentlyViewed() is a separate method in my products class, which if everything ever eventuates, will do more or less exactly what the code you have given does.

The problem is that I’m not able to collect and store data properly in order to make this method work, this is really the part that I’m needing help with.

var_dump() echoes content, so you don’t normally need to do “echo var_dump(…)”.

Are you successfully storing any session data currently? Is this the only data you’ve tried storing in the session so far? In addition to using $_SESSION, you need to have all of the session options configured properly and be starting the session.

To make sure you’re working with an array in load_product() you can use conditional logic or you can do this:


$_SESSION[ 'recentItems' ] = (array) $_SESSION[ 'recentItems' ];

That’s only relevant after you’re sure you have the session working though.

Assuming your session was working, that would be wiping out the value stored in the session by assigning an empty array to the variable.

That indicates some really fundamental problem, because even if you don’t have the session working, once you set $_SESSION[ ‘recentItems’ ] in load_product() you should be able to access it in recentlyViewed() during the same request.

I suggest creating a version of your code that is stripped down to the bare minimum related to this functionality and post the code and the output.

What version of PHP are you running, and what is the environment (OS, web server, etc.)?

Successsssss! Thanks for the hint there, I looked closer into the session and found that where I had put session_start(); was not working for me (not really sure why). I moved it to be on the top of each of the relevant pages - and like I say, success! - recentlyViewed() now gets the array data. For neatness I have moved it into the first class that gets included now, and it still works.

Your line

$_SESSION[ 'recentItems' ] = (array) $_SESSION[ 'recentItems' ];

is the other piece of the puzzle - I’m not familiar with that syntax but that’s what I was trying to do, so thanks for that!

Turns out this was a very simple problem, but I was distracted by the inherited code and my own lack of knowledge of it into thinking it was something much more complicated . . . there’s probably a lesson there for the future . . .

Thank you very much for all the help!