PHP How do I add an object to an array? - php

Expected Result:
I have several echo statements and I should be getting something like this:
index1
Question->addChoice1
Choice1
Choice2
Question->addChoice2
index2
Actual Results:
index1
Question->addChoice1
Choice1
Choice2
Its failing at:
$this.$choices[] = new Choice($obj);
I have no idea why its doing this, but its almost 3AM here so maybe I'm just too brain-dead to see it. please help.
index.php
$QUESTIONS = array();
for ($chapter=1; $chapter<=count($max_chapter); $chapter++) {
$question_qry = "SELECT * FROM $tbl_questions WHERE chapter=$chapter ORDER BY RAND() LIMIT $max_chapter[$chapter]";
$question_req = mysql_query($question_qry);
while ($question_obj = mysql_fetch_object($question_req)) {
$newQuestion = new Question($question_obj);
$choice_qry = "SELECT * FROM $tbl_choices WHERE question=$question_obj->reference ORDER BY choice ASC;";
$choice_req = mysql_query($choice_qry);
while ($choice_obj = mysql_fetch_object($choice_req)) {
echo "index1<br>";
$newQuestion->addChoice($choice_obj);
echo "index2<br>";
}
$QUESTIONS[] = $newQuestion;
echo '<pre>'; print_r($newQuestion); echo '</pre>';
}
}
shuffle($QUESTIONS);
echo '<pre>'; print_r($QUESTIONS); echo '</pre>';
question.php
class Question {
private $chapter;
private $topic;
private $reference;
private $question_name;
private $question_correct;
private $special;
private $pic;
private $choices = array();
function __construct($obj) {
$this->chapter = $obj->chapter;
$this->topic = $obj->topic;
$this->reference = $obj->reference;
$this->question_name = $obj->question_name;
$this->question_correct = $obj->question_correct;
$this->special = $obj->special;
$this->pic = $obj->pic;
}
public function addChoice($obj){
echo "Question->addChoice1<br>";
$this.$choices[] = new Choice($obj);
echo "Question->addChoice2<br>";
}
...
choice.php
class Choice {
private $chapter;
private $question;
private $choice;
private $choice_name;
private $choice_explanation;
function __construct($obj) {
echo "Choice1<br>";
$this->chapter = $obj->chapter;
$this->question = $obj->question;
$this->choice = $obj->choice;
$this->choice_name = $obj->choice_name;
$this->choice_explanation = $obj->choice_explanation;
echo "Choice2<br>";
}
...
Results

In PHP you have to use -> to call object properties, not .. . is concatenation.
So just replace $this.$choices[] with $this->choices[]
Typical typo for people who haven't worked much with PHP, but have experience in other languages.

Related

failure with find() function using PHP with Silex

Here is the failure message I get in Terminal running 'phpunit tests':
1) StylistTest::test_find
null does not match expected type "object".
/Users/evanbutler/Desktop/hairSalonApp/tests/StylistTest.php:163
Here's my test method:
function test_find()
{
//Arrange
$name = "Stylist Jane";
$id = 1;
$name2 = "Stylist Bob";
$id2 = 2;
$test_stylist = new Stylist($name, $id);
$test_stylist->save();
$test_stylist2 = new Stylist($name2, $id2);
$test_stylist2->save();
//Act
$result = Stylist::find($test_stylist->getId());
//Assert
$this->assertEquals($test_stylist, $result);
}
And here's my method:
static function find($search_id)
{
$found_stylist = null;
$stylists = Stylist::getAll();
foreach($stylists as $stylist) {
$stylist_id = $stylist->getId();
if ($stylist_id == $search_id) {
$found_styist = $stylist;
}
}
return $found_stylist;
}
Here's my getAll method:
static function getAll()
{
$returned_stylists = $GLOBALS['DB']->query("SELECT * FROM stylists;");
$stylists = array();
foreach($returned_stylists as $stylist) {
$name = $stylist['name'];
$id = $stylist['id'];
$new_stylist = new Stylist($name, $id);
array_push($stylists, $new_stylist);
}
return $stylists;
}
If you'd like to see all my files here's the link to the git repository:
https://github.com/evanb2/hairSalonApp.git
I've been staring at this for way too long and I'm totally stumped.
Change
$found_styist = $stylist;
to
$found_stylist = $stylist;
You need a better IDE man. Simple static analysis could tell you about the unused variable.

How do I access successive rows from mysql_fetch_assoc() in a different file and array variable?

I'm trying to implement a simple "list-out" functionality from a table of places/spots of a city.
To do this, I created a Place class and returned a mysql_fetch_assoc() array from a "get" function. This code is in a PHP file called "placeops.php", containing only OO logic.
Now moving to another file called "displayplaces.php", I call the same "get" function here to get the mysql_fetch_assoc() array into another variable. Then I use the next() and current() functions to retrieve the records.
This doesn't work. If I use current() to get a specific column/attribute value, it says "current() expects array, string passed" error. By NOT using current(), I can only access the first element, as expected. I understand why that error comes. But is there any workaround for this? I have to use OO approach. Here's the code:
//This is the class and the function I use to return the mysql array. The file name is
// placeops.php
<?php
//include '../../../myclass.php';
#mysql_connect("localhost","root","") or die(mysql_error());
mysql_select_db("wom") or die(mysql_error());
global $plcname, $plcaddr, $plccity, $plcstate, $plcpic, $plcrating, $plclat, $plclong, $plccat, $plcid;
class Place
{
private $pname;
private $paddr;
private $pcity;
private $pstate;
private $plat;
private $plong;
private $prating;
function getAllPlaces()
{
$plcqry = "SELECT * FROM place,state,city where place.st_id = state.st_id AND place.ct_id = city.ct_id";
$rows = mysql_query($plcqry);
return mysql_fetch_assoc($rows);
/*
while($res = mysql_fetch_assoc($rows))
{
$GLOBALS["plcname"] = $res["plc_nm"];
$GLOBALS["plcstate"] = $res["st_nm"];
$GLOBALS["plccity"] = $res["ct_nm"];
echo $GLOBALS["plcname"]." -- ".$GLOBALS["plccity"]." -- ".$GLOBALS["plcstate"]."<br><br>";
}
* */
}
function getPlace($name, $city, $state)
{
$this->pname = $name;
$this->pcity = $city;
$this->pstate = $state;
$row = mysql_query($plcqry);
$plcqry = "SELECT place.plc_nm, place.plc_photo, place.plc_addr, place.ct_id, place.plc_lat, place.plc_long, city.ct_nm, state.st_nm FROM place,state,city WHERE place.plc_nm = '".$this->pname."' AND place.st_id = state.st_id AND state.st_nm = '".$this->pstate."' AND place.ct_id = city.ct_id AND city.ct_nm = '".$this->pcity."'";
#$row = mysql_query($plcqry);
$res = mysql_fetch_assoc($row);
$GLOBALS["plcname"] = $res["plc_nm"];
$GLOBALS["plcaddr"] = $res["plc_addr"];
$GLOBALS["plccity"] = $res["ct_nm"];
$GLOBALS["plcstate"] = $res["st_nm"];
$GLOBALS["plcpic"] = $res["plc_photo"];
$GLOBALS["plclat"] = $res["plc_lat"];
$GLOBALS["plclong"] = $res["plc_long"];
//echo "".$GLOBALS["plcname"]."<br>";// <img src=\"".$GLOBALS["plcpic"]."\"/>";
}
function ratePlace($name,$city,$state,$rating)
{
$this->pname = $name;
$this->pcity = $city;
$this->pstate = $state;
$this->prating = $rating;
$plcqry = "SELECT place.plc_id, place.plc_rating FROM place,state,city WHERE place.plc_nm = '".$this->pname."' AND place.st_id = state.st_id AND state.st_nm = '".$this->pstate."' AND place.ct_id = city.ct_id AND city.ct_nm = '".$this->pcity."'";
$row = mysql_query($plcqry);
$res = mysql_fetch_assoc($row);
$GLOBALS["plcrating"] = $res["plc_rating"];
$GLOBALS["plcid"] = $res["plc_id"];
$rating += $GLOBALS["plcrating"];
$ratingqry = "UPDATE place SET plc_rating = ".$this->prating." WHERE plc_id = ".$GLOBALS["plcid"]."";
mysql_query($ratingqry);
$plcqry = "SELECT plc_rating FROM place WHERE plc_id = ".$GLOBALS["plcid"]."";
$row2 = mysql_query($plcqry);
$res2 = mysql_fetch_assoc($row2);
$GLOBALS["plcrating"] = $res2["plc_rating"];
}
function getPlaceByRegion($city, $state)
{
$this->pcity = $city;
$this->pstate = $state;
$plcqry = "SELECT place.plc_id, place.plc_nm, state.st_nm, city.ct_nm FROM place,state,city WHERE place.st_id = state.st_id AND state.st_nm = '".$this->pstate."' AND place.ct_id = city.ct_id AND city.ct_nm = '".$this->pcity."'";
$rows = mysql_query($plcqry);
while($res = mysql_fetch_assoc($rows))
{
$GLOBALS["plcname"] = $res["plc_nm"];
$GLOBALS["plcstate"] = $res["st_nm"];
$GLOBALS["plccity"] = $res["ct_nm"];
//echo $GLOBALS["plcname"]." -- ".$GLOBALS["plccity"]." -- ".$GLOBALS["plcstate"]."<br><br>";
}
}
}
?>
//And this is the other part of the code, which I use in another PHP file that
//contains the HTML code ("view layer"). File name is "displayplaces.php"
<?php
include './placeops.php';
$obj = new Place;
$res = $obj->getAllPlaces();
while (next($res))
{
//expected string parameter errors for all these assignments
$GLOBALS["plcname"] = current($res["plc_nm"]);
$GLOBALS["plcstate"] = current($res["st_nm"]);
$GLOBALS["plccity"] = current($res["ct_nm"]);
$GLOBALS["plcrating"] = current($res["plc_rating"]);
$GLOBALS["plclat"] = current($res["plc_lat"]);
echo "<tr>
<td>" . $GLOBALS["plcname"] . "</td>
<td>" . $GLOBALS["plcrating"] . "</td>
<td>" . $GLOBALS["plccity"] . "</td>
<td>" . $GLOBALS["plcstate"] . "</td>
<td>" . $GLOBALS["plclat"] . "</td>
</tr>";
}
?>
Currently there are 14 records in the table. And I know I can workaround this by writing the sql handling code in the "displayplaces.php" file itself. But is it possible to keep the function and display logic different? May be use an extra index in $res array? Or do I have to write the fetching code in the same PHP page that displays the content?
There are some problems with the use of objects here. Primarily, this is not actually object oriented. You can do this without the use of globals at all - objects should contain their data internally.
I would expect a class called Place to contain just one place, but you are offering a method called getPlaces which does not seem to fit with that purpose. I'd suggest you create another class called PlaceSet (or similar pluralisation) that contains a number of Place objects in an array.
Something like this:
class Place {
// I've stored some example properties here, you can
// change these if you wish
protected $id;
protected $name;
protected $state;
protected $city;
// I've used a constructor here, but you could use a setter function
// instead, so that a Place can have its properties changed during its
// lifetime
public function __construct($id, $name, $state, $city) {
$this->id = $id;
$this->name = $name;
$this->state = $state;
$this->city = $city;
}
public function ratePlace($rating) {
// You can access $this->id to set a rating
}
// Offer getters in this format
public function getName() {
return $this->name;
}
}
class PlaceSet {
// This function just returns an array of Places, but you could
// also store that result in this class if you wish, so as to
// reuse it without having to rerun the query every time
public function getAllPlaces() {
// Word-wrap your long lines!
$plcqry = "
SELECT *
FROM place,state,city
WHERE
place.st_id = state.st_id
AND place.ct_id = city.ct_id
";
// #todo This legacy library needs to be swapped out
$rows = mysql_query($plcqry);
$places = array();
while($res = mysql_fetch_assoc($rows))
{
$places[] = new $Place(
$res["plc_id"]
$res["plc_nm"],
$res["st_nm"],
$res["ct_nm"]
);
}
return $places;
}
// Maybe this should be getPlacesByRegion?
//
// Always declare your access level
public function getPlaceByRegion($city, $state)
{
// Add code here
}
}
You can access the full list of places thus:
<?php
// Do your connection here
include './placeops.php';
$placeSet = new PlaceSet();
$places = $placeSet->getAllPlaces();
foreach ($places as $place) {
// Add these getters into the Place class
echo "<tr>
<td>" . $place->getName() . "</td>
<td>" . $place->getRating() . "</td>
<td>" . $place->getCity() . "</td>
<td>" . $place->getState() . "</td>
<td>" . $place->getLat() . "</td>
</tr>";
}
?>

Decryption: Using a loop to go through a function using mysql

I'm trying to make some code that displays a user's passwords for transfer to a new website.
I have this right now.
function decryptPassword($users)
{
global $sql_tbl;
$userData=func_query_first("select * from $sql_tbl[customers] where login='".$users."'");
if ($userData["password"]!="") $password = text_decrypt($userData["password"]);
else return false;
return $password;
}
echo "master = ".decryptPassword('master')."<br>";
$a = decryptPassword('tester');
if ($a===false) { echo "User not found...";exit();}
echo "tester = ".decryptPassword('tester')."<br>";
?>
and it works, but I wanted to use a for each query and I have been having trouble trying to get it into a a loop. Should I be doing this differently?
function decryptPassword($users)
{
global $sql_tbl;
$userData=func_query_first("select * from $sql_tbl[customers] where login='".$users."'");
if ($userData["password"]!="") $password = text_decrypt($userData["password"]);
else return false;
return $password;
}
$email=msql_query("SELECT email
FROM $sql_tbl[address_book]
join xcart_customers on xcart_prod.xcart_address_book.userid=xcart_prod.xcart_customers.id
where (default_s = 'Y' and default_b='Y'and membershipid=2) or (default_s='N' and default_b='Y' and membershipid=2)");
while ($row = mysql_fetch_assoc($email)) {
foreach($row as $field) {
echo " = ".decryptPassword($field)."<br>";
$a = decryptPassword($field);
if ($a===false) { echo "User not found...";exit();}
echo "it#claramente.com = ".decryptPassword($field)."<br>";
}
}
Thanks for any help.

How can I create a new php object from dynamic database record sets

I am working on a php job calendar project. This is what I am trying to do: Query the database and get the scheduled information (that part I got), take that information and create a job object based on each record set, then I need to sort the objects by department and start date/time and then display them in a dynamic table based on the department and time. I have gotten this far:
<?php
session_start();
include_once("functions.php");
class jobs
{
//a job has a:
private $eachJob;
private $group;
private $jID;
private $num;
private $jStatus;
private $description;
private $startDate;
private $endDate;
private $startTime;
private $endTime;
private $rSpan;
private $department;
public function __construct()
{
$this->buildJob($_SESSION['dept']);
}
public function buildJob($depatment)
{
$captionHeading = 'Traditional Print';
$conn = connect();
$tsql = "select + 'Job# ' + CAST (JobNum AS VARCHAR(10)) as JobNum, Description, datediff(MI,StartTime, EndTime) / 15 as 'RowSpan', AssetName,
AssetID, Status.ColorCode as tdCC, JobID, StartTime, EndTime, datediff(day,getDate(),StartTime)*24*60/15 as 'Blank', getdate() as now
from Calendar_View, Departments, Status, Assets
where Departments.DepartmentName = '$depatment' and Calendar_View.Department = Departments.DepartmentID and AssetStatus = Status.StatusID and
Calendar_View.Asset = Assets.AssetID
order by AssetID asc";
$stmt = sqlsrv_query($conn, $tsql);
if ($stmt)
{
while( $row = sqlsrv_fetch_array( $stmt, SQLSRV_FETCH_ASSOC) )
{
/*******************************
$this->jobDetails = array(
$this->group = $row{'AssetName'},
$this->jID = $row['JobID'],
$this->num = $row['JobNum'],
$this->jStatus = $row['tdCC'],
$this->description = "now =" . date_format($row['now'],'Y-m-d'),
$this->startDate = date_format($row['StartTime'],'Y-m-d'),
$this->endDate = date_format($row['EndTime'],'Y-m-d'),
$this->startTime = date_format($row['StartTime'],'g:i'),
$this->endTime = date_format($row['EndTime'],'g:i'),
$this->rspan = "Time needed: " . $row['RowSpan']);
$this->jobInfo($this->jobDetails);
**********************************/
$this->group = $row{'AssetName'};
$this->jID = $row['JobID'];
$this->num = $row['JobNum'];
$this->jStatus = $row['tdCC'];
$this->description = "now =" . date_format($row['now'],'Y-m-d');
$this->startDate = date_format($row['StartTime'],'Y-m-d');
$this->endDate = date_format($row['EndTime'],'Y-m-d');
$this->startTime = date_format($row['StartTime'],'g:i');
$this->endTime = date_format($row['EndTime'],'g:i');
$this->rspan = "Time needed: " . $row['RowSpan'];
//$this->jobInfo();
}
}
else
{
die( print_r(sqlsrv_errors(), true));
}
}
public function jobInfo()
{
}
}
/******************************
class job
{
}
******************************/
?>
I can access the job and do so from another page with:
include_once("../php/job_class.php");
$obj=new job("Traditional Print");
echo "<pre>";
echo print_r($obj);
echo "</pre>";
That only gives me the object created from the sql call. I have tried putting it into an array and passing it to the jobinfo function, but that gives me an array of arrays and makes a mess to deal with. How can I accomplish what I am trying to do?
Your sorting issue
The easiest way to sort is to do it in your SQL query. So could change the order to be ORDER BY DepartmentName, StartTime.
Your object issue
Instead of having a jobs class that holds all the data you should create a job class and the jobs class has many job instances. Maybe something like this:
class job
{
//a job has a:
private $eachJob;
private $group;
private $jID;
private $num;
private $jStatus;
private $description;
private $startDate;
private $endDate;
private $startTime;
private $endTime;
private $rSpan;
private $department;
public __construct($row) {
$this->group = $row{'AssetName'};
$this->jID = $row['JobID'];
$this->num = $row['JobNum'];
$this->jStatus = $row['tdCC'];
$this->description = "now =" . date_format($row['now'],'Y-m-d');
$this->startDate = date_format($row['StartTime'],'Y-m-d');
$this->endDate = date_format($row['EndTime'],'Y-m-d');
$this->startTime = date_format($row['StartTime'],'g:i');
$this->endTime = date_format($row['EndTime'],'g:i');
$this->rspan = "Time needed: " . $row['RowSpan'];
}
}
class jobs
{
private $jobs = array();
public function __construct()
{
$this->buildJob($_SESSION['dept']);
}
public function buildJob($depatment)
{
$captionHeading = 'Traditional Print';
$conn = connect();
$tsql = "select + 'Job# ' + CAST (JobNum AS VARCHAR(10)) as JobNum, Description, datediff(MI,StartTime, EndTime) / 15 as 'RowSpan', AssetName,
AssetID, Status.ColorCode as tdCC, JobID, StartTime, EndTime, datediff(day,getDate(),StartTime)*24*60/15 as 'Blank', getdate() as now
from Calendar_View, Departments, Status, Assets
where Departments.DepartmentName = '$depatment' and Calendar_View.Department = Departments.DepartmentID and AssetStatus = Status.StatusID and
Calendar_View.Asset = Assets.AssetID
order by AssetID asc";
$stmt = sqlsrv_query($conn, $tsql);
if ($stmt)
{
while( $row = sqlsrv_fetch_array( $stmt, SQLSRV_FETCH_ASSOC) )
{
$this->jobs[] = new job($row);
}
}
else
{
die( print_r(sqlsrv_errors(), true));
}
}
public function jobInfo()
{
$jobArray = array();
echo "<pre>";
echo print_r("$jobArray[1]");
echo "</pre>";
}
}
All your properties are private. Plus the object name is jobs and you are initiating a object called job. Plus your construct function doesn't take an incoming variable and you are trying to send it a string. Same goes for jobInfo() it doesn't have any incoming parameters and you are trying to send it a bunch of values.
To do what you are trying to do you could create a static function that returns an array of jobs objects.

"Meta-objects"?

I want to do something like this:
class StrangeClass {
public function somethingLikeAMethod($var) {
/* ... */
}
public function awesomeTest() {
/* ... */
}
}
$obj = new StrangeClass;
$ex1 = $obj->somethingLikeAMethod(1);
$ex2 = $obj->somethingLikeAMethod(2);
$ex1 -> awesomeTest(); // This will output "1"
$ex2 -> awesomeTest(); // This will output "2"
Other words, I want that object change its behavior.
In Lua language I can make this with 'metatables', but I doesn't know how to make this in OO-PHP.
Thank you.
Added:
I did something like this in Lua:
local query = Database.query(...) -- now this variable has a query id
local query2 = Database.query(...) -- this is a other query id
local result = query.fetchAssoc() -- read below
local result2 = query.fetchAssoc() -- I called the same object with same method twice, but it will return other results
Added #2:
What I want to do:
$db = new Database();
$firstResult = $db->query('SELECT * FROM `table`')->fetch_assoc();
$firstExample = $db->query("SELECT * FROM `table` WHERE `id` = '1'");
$secondExample = $db->query("SELECT * FROM `table` WHERE `id` = '2'");
$secondResult = $firstExample -> fetch_assoc();
$thirdResult = $secondExample -> fetch_assoc();
God knows why you want it, but this will work for you:
class StrangeClass {
public function somethingLikeAMethod($var) {
$this->test_var = $var;
return clone $this;
}
public function awesomeTest() {
echo $this->test_var;
}
}
$obj = new StrangeClass;
$ex1 = $obj->somethingLikeAMethod(1);
$ex2 = $obj->somethingLikeAMethod(2);
$ex1->awesomeTest(); // This will output "1"
$ex2->awesomeTest(); // This will output "2"
Edit: If you're looking for a queuing system, you can push each query into an array, something like:
class StrangeClass {
private $queries = array();
public function somethingLikeAMethod($var) {
$this->queries[] = $var;
return $this;
}
public function awesomeTest() {
if(count($this->queries) === 0){
echo 'no queries left';
}
echo $this->queries[0];
array_splice($this->queries,0,1);
}
}
$obj = new StrangeClass;
$ex1 = $obj->somethingLikeAMethod("select * from hello");
$ex2 = $obj->somethingLikeAMethod("select * from me");
$ex2 = $obj->somethingLikeAMethod("select * from you");
$ex2 = $obj->somethingLikeAMethod("select * from my_friend");
$ex1->awesomeTest();
$ex2->awesomeTest();
$ex2->awesomeTest();
$ex2->awesomeTest();
$ex2->awesomeTest();

Categories