"Meta-objects"? - php

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();

Related

PHP How do I add an object to an array?

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.

Cant return from a function to my html

this is my html file index.php
<?php
require_once(realpath(dirname(__FILE__)).'/../environments/include/ShowDataClass.php');
$Show = new ShowDataClass();
foreach ($Show->getAllUserPayments() as $key => $v) {
if($v->date_reg != 0){
$date_reg = $v->date_reg;
}else{
$date_reg = $Show->getInsertDate($v->metadata);
}
echo $date_reg;/*here the problem*/
}
this is my ShowDataClass.php
class ShowDataClass extends DbClass{
public function getInsertDate($id){
$query = "SELECT * FROM metadata WHERE id = $id";
$this->rs = $this->loadObjectList($query);
if($this->rs[0]->prev_metadata == 0){
$date = $this->rs[0]->date.' '.$this->rs[0]->time;
}else{
$this->getInsertDate($this->rs[0]->prev_metadata);
}
return strval($date);
}
}
expected result 2017-09-18 19:22:49 but i got empty, getInsertData($v->metadata) all times send an id.
if i do an echo inside ShowDataClass in line 6 it return me the desired data.
could you please help me with this, need to use return but not working?
You have to return in the recursive call:
return $this->getInsertDate($this->rs[0]->prev_metadata);
Full code:
class ShowDataClass extends DbClass{
public function getInsertDate($id){
$query = "SELECT * FROM metadata WHERE id = $id";
$this->rs = $this->loadObjectList($query);
if($this->rs[0]->prev_metadata == 0){
$date = $this->rs[0]->date.' '.$this->rs[0]->time;
}else{
return $this->getInsertDate($this->rs[0]->prev_metadata);
}
return strval($date);
}
}

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 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.

How to change the number of specifiers with count of providing array in php

My code is given bellow
Controller code:
class statController extends baseController {
public function index() {
$this->registry->template->projectsWise = $this->selectProjectWise();
$this->registry->template->show("stat");
}
private static function selectStat($query, $values) {
$statMapper = new statMapper();
$select = new common();
$select->setItems($query);
$select->setValues($values);
return $statMapper->select($select);
}
private function selectProjectWise() {
$date = date("Y-m-d");
$values = array($date, $date);
return self::selectStat("project_wise", $values);
}
private function selectLocationWise(){
$date = date("Y-m-d");
$values = array($date, $date, 1);
return self::selectStat("location_wise", $values);
}
Mapper code:
class statMapper extends baseMapper {
private $query = array(
"project_wise" => "SELECT p.proj_Name, p.proj_Type, p.proj_Category, COUNT(ra.emp_Id) as allocation FROM project AS p, resource_assignment AS ra WHERE p.proj_Start_Date <= '%s' AND p.proj_End_Date >= '%s' AND p.proj_Status = 1 AND ra.proj_Id = p.proj_Id GROUP BY p.proj_Name ",
"location_wise" => "SELECT e.user_Location, p.proj_Name, p.proj_Type, p.proj_Category, COUNT(ra.emp_Id) as allocation FROM project AS p, resource_assignment AS ra, employee as e WHERE p.proj_Start_Date <= '%s' AND p.proj_End_Date >= '%s' AND p.proj_Status = %d AND ra.proj_Id = p.proj_Id GROUP BY p.proj_Name "
);
public function select($select) {
$connect = parent::connect();
$query = sprintf($this->query[$select->getItems()], $select->getValues()[0], $select->getValues()[1]);
try {
$result = $connect->query($query);
if ($result) {
$table = array();
while ($row = $result->fetch_object()) {
$table[] = $row;
}
return $table;
parent::disconnect();
} else {
throw (new Exception($connect->error . "<br/>" . $query . "<br/>"));
}
} catch (Exception $exp) {
require_once 'views/error.php';
exit();
}
}
}
I have added 3 specifiers ($query->"location_wise") In statController->selectLocationWise() function.
When I use it how do I add $select->getValues()[2] value in statMapper->select(), instead of add it manually.
You can use http://www.php.net/manual/ru/function.vsprintf.php instead of sprintf to pass whole array as argument.
But anyway your code looks bad. From the outside view of StatMapper there is no way to identify neither types of arguments, nor their count. Code will be hard to be maintained.
I advise to use Data Access Objects pattern or learn framework.

Categories