I'm trying to edit an class with an DB driven result.
I use ColorInterpreter by Our Code World, which is a PHP port of the JavaScript library NTC JS.
In this class is a public variable which is a array of hex/colorname pairs. This is hardcoded into the class. I want to make this dynamic with the use of an DB output.
I'm still struggeling with classes so I can't get my head around this.
colornames.inc.php:
Outputs something like this:
Array
(
[b0bf1a] => Acid Green
[7cb9e8] => Aero
[c9ffe5] => Aero Blue
[b284be] => African Violet
[00308f] => Air Force Blue (USAF)
[72a0c1] => Air superiority Blue
...
}
ColorInterpreter.php:
class ColorInterpreter
{
public function __construct()
{
$color = null;
$rgb = null;
$hsl = null;
$name = null;
for($i = 0; $i < count($this->names); $i++)
{
$color = "#".$this->names[$i][0];
$rgb = $this->rgb($color);
$hsl = $this->hsl($color);
array_push
(
$this->names[$i],
$rgb[0],
$rgb[1],
$rgb[2],
$hsl[0],
$hsl[1],
$hsl[2]
);
}
}
public function name($color)
{
...
}
// adopted from: Farbtastic 1.2
// http://acko.net/dev/farbtastic
public function hsl($color)
{
...
}
// adopted from: Farbtastic 1.2
// http://acko.net/dev/farbtastic
public function rgb($color)
{
...
}
public function color($name)
{
...
}
// Below is the part I need to replace with the output given from colornames.inc.php
public $names = array(
// Pink colors
array("FFC0CB", "Pink"),
array("FFB6C1", "Light Pink"),
array("FF69B4", "Hot Pink"),
array("FF1493", "Deep Pink"),
array("DB7093", "Pale Violet Red"),
array("C71585", "Medium Violet Red"),
array("E0115F", "Ruby"),
array("FF6FFF", "Ultra"),
...
);
}
I don't know how, if or where I could/should include the colornames.inc.php
And I don't know where to correctly declare the needed variables. Obviously, $this->names represent the hardcoded array, but how has this to be changed to reflect the DB output I have?
I'm completely lost here.
Your best option is to create a function that returns the values, and then pass that as the constructor when you create the class. e.g.
include 'file_with_function.php';
include 'file_with_class.php';
$initialColorValues = my_get_color_values();
$newObject = new ColorObject($initialColorValues);
Now you can process that array in the constructor, and you have an object that is seeded with the correct color values
class XYZ {
public $names;
public function __construct($names){
// ... do work
$this->names = $work;
}
}
Related
So, let's say I have this dummy code in one file:
<?php
class Dice
{
public $maxPossibleNo;
public $secretNumber;
function __construct($no_of_dice=1)
{
// how many possible dice number to enroll
$this->maxPossibleNo = $no_of_dice * 6;
// do shaking dice
$this->secretNumber = $this->getSecretNumber();
}
function getSecretNumber()
{
return rand(1, $this->maxPossibleNo);
}
function roll()
{
$found = false;
list($array1, $array2) = array_chunk(range(1, $this->maxPossibleNo), ceil($this->maxPossibleNo/2));
/*
Array
(
[0] => 1
[1] => 2
[2] => 3
)
Array
(
[0] => 4
[1] => 5
[2] => 6
)
*/
$guess = new Guess();
echo $this->secretNumber;
echo $guess->checkSecretNumber();
}
}
class Guess extends Dice
{
function checkSecretNumber()
{
return $this->secretNumber;
}
function isGreaterThan($x)
{
return $x > $this->secretNumber;
}
function isLessThan($x)
{
return $x < $this->secretNumber;
}
function isEqual($x)
{
return $x == $this->secretNumber;
}
}
$game = new Dice('1');
$game->roll();
Result:
65
43
54
Expected Result:
66
33
55
I want the Guess class to be able to access the secret number of the Dice class without having to roll it again. So I can manipulate the Guess class with other function.
EDIT:
Expectation flow: The main class will only called once (to generate
the secret number), while i will need to do loop checking for the
secret number for many times. (I guess the way is to create another
class of it, and it will be able to be called repeatly for auto
checking purpose, but i had did mistake here and dont have any idea
how to correct this part.)
Any suggested correction will be appreciated.
Thank you
when you create a new Guess(), it runs the constructor of Dice automatically, since Guess extends dice. The secret number in the Guess instance is not the secret number of the first Dice instance, it's a separate instance. I think your design is flawed. Why does Guess need to extend Dice? A guess is not logically a different implementation of a Dice (which is what you'd (logically) normally use subclasses for).
Here's how I would do it (without knowing anything further about what exactly you want to achieve):
<?php
class Dice
{
public $maxPossibleNo;
public $secretNumber;
function __construct($no_of_dice=1)
{
// how many possible dice number to enroll
$this->maxPossibleNo = $no_of_dice * 6;
// do shaking dice
$this->secretNumber = $this->getSecretNumber();
}
function getSecretNumber()
{
return rand(1, $this->maxPossibleNo);
}
function roll()
{
$found = false;
list($array1, $array2) = array_chunk(range(1, $this->maxPossibleNo), ceil($this->maxPossibleNo/2));
/*
Array
(
[0] => 1
[1] => 2
[2] => 3
)
Array
(
[0] => 4
[1] => 5
[2] => 6
)
*/
}
}
class Guess
{
private $dice;
function __construct(Dice $d)
{
$this->dice = $d;
}
function checkSecretNumber()
{
return $this->dice->secretNumber;
}
function isGreaterThan($x)
{
return $x > $this->dice->secretNumber;
}
function isLessThan($x)
{
return $x < $this->dice->secretNumber;
}
function isEqual($x)
{
return $x == $this->dice->secretNumber;
}
}
$dice = new Dice('1');
$dice->roll();
$guess = new Guess($dice);
echo $dice->secretNumber;
echo $guess->checkSecretNumber();
I'm new to PHP and I'm having trouble accessing some class variables.
I have this class:
class emptyClass
{
private $ladderWinsNoCoin = 0;
private $ladderWinsCoin = 0;
private $arenaWinsNoCoin = 0;
private $arenaWinsCoin = 0;
private $ladderLossesNoCoin = 0;
private $ladderLossesCoin = 0;
private $arenaLossesNoCoin = 0;
private $arenaLossesCoin = 0;
public function getProperty($property) {
if (property_exists($this, $property)) {
return $this->$property;
}
}
public function upOne($property) {
if (property_exists($this, $property)) {
$this->$property=($property+1);
}
}
public function setProperty($property, $value) {
if (property_exists($this, $property)) {
$this->$property = $value;
}
}
}
I then create 9 instances of it in an array
/* Create classes in an array so we can call
them with strings from the database*/
$classes = array(
'Druid' => new emptyClass,
'Hunter' => new emptyClass,
'Mage' => new emptyClass,
'Paladin'=> new emptyClass,
'Priest' => new emptyClass,
'Rogue' => new emptyClass,
'Shaman' => new emptyClass,
'Warlock'=> new emptyClass,
'Warrior'=> new emptyClass
);
Next I want to increment the values of the class variables to match data got from a database and this is what I've come up with
foreach ($games as $game){ // Go through the games array from the database
$gameID = current($game); // Unused (for now)
$heroClass = (string)next($game);
$villainClass = (string)next($game); // Unused (for now)
$win = (int)next($game);
$coin = (int)next($game);
$ladder = (int)next($game);
//Add up the values in the class objects
if ($ladder==1&&$coin==1&&$win==1){ // Ladder win with coin
$classes[$heroClass] -> {upOne($ladderWinsCoin)};
} else if ($ladder==1&&$coin==1&&$win==0){ // Ladder loss with coin
$classes[$heroClass] -> {upOne($ladderLossesCoin)};
} else if ($ladder==1&&$coin==0&&$win==1){ // Ladder win without coin
$classes[$heroClass] -> {upOne($ladderWinsNoCoin)};
} else if ($ladder==1&&$coin==0&&$win==0){ // Ladder loss without coin
$classes[$heroClass] -> {upOne($ladderLossesNoCoin)};
} else if ($ladder==0&&$coin==1&&$win==1){ // Arena win with coin
$classes[$heroClass] -> {upOne($arenaLossesCoin)};
} else if ($ladder==0&&$coin==1&&$win==0){ // Arena loss with coin
$classes[$heroClass] -> {upOne($arenaLossesCoin)};
} else if ($ladder==0&&$coin==0&&$win==1){ // Arena win without coin
$classes[$heroClass] -> {upOne($arenaWinsNoCoin)};
} else if ($ladder==0&&$coin==0&&$win==0){ // Arena loss without coin
$classes[$heroClass] -> {upOne($arenaLossesNoCoin)};
}
Where $game is an array from the database that looks something like this
[1, 'Mage', 'Druid', 1, 0, 1]
When it runs I get a fatal error
PHP Fatal error: Call to undefined function setProperty() in /home/vooders/public_html/gameReader.php on line 48
Edit:
So after trying renaming the getter/setter I'm still getting the fatal error, so now I'm sure its how I'm calling the objects.
I'll try to talk you through my thinking
$classes[$heroClass] -> {upOne($ladderWinsCoin)};
If we take this line above, $heroClass will be a string from the database in this example 'Mage'.
Now I want to use this string to call the right object from the $classes array then increment the appropriate variable by 1.
Categorically, I would advise you not to "write code external to a class that knows the class's business."
"I am a class. Therefore, I am alive. Tell me what has happened and I shall respond accordingly. Ask me what you want to know and I shall provide you with the answer. But: Do Not Meddle in the Affairs of Classes, for you are crunchy and taste good with worcestershire sauce!!"
(1) Don't put your sticky fingers on the class's variables "from outside." Tell the Class what has happened, that it may increment or decrement its own properties. (You did say they were private, didn't you? As they should be.)
(2) If you want to know "an answer," which may be based on the value of one or many properties, according to simple or complex logic, then the Class should contain that logic, as it pertains "to itself."
//it should work now
<?
class emptyClass {
private $ladderWinsNoCoin = 5; private $ladderWinsCoin = 0; private $arenaWinsNoCoin = 0; private $arenaWinsCoin = 0;
private $ladderLossesNoCoin = 0; private $ladderLossesCoin = 0; private $arenaLossesNoCoin = 0; private $arenaLossesCoin = 0;
public function getProperty($property) {
if (property_exists($this, $property)) {
return $this->$property;
}
}
public function setProperty($property, $value) {
if (property_exists($this, $property)) {
$this->$property = $value;
}
}
public function upOne($property) {
if (property_exists($this, $property)) {
$this->$property++;
}
}
}
$classes = array(
'Druids' => new emptyClass,
'Elfos' => new emptyClass
);
$classes["Druids"]->setProperty("ladderWinsNoCoin",50);
echo $classes["Druids"]->getProperty("ladderWinsNoCoin") . "<br>";
$classes["Druids"]->upOne("ladderWinsNoCoin");
echo $classes["Druids"]->getProperty("ladderWinsNoCoin"). "<br>";
$classes["Elfos"]->setProperty("ladderLossesCoin",25);
echo $classes["Elfos"]->getProperty("ladderLossesCoin"). "<br>";
$classes["Elfos"]->upOne("ladderLossesCoin");
echo $classes["Elfos"]->getProperty("ladderLossesCoin"). "<br>";
//50
//51
//25
//26
?>
I have some property $abc (type array) in object:
$this->abc = array(
'id' => 123,
'status' => 'close'
);
There is some solution to using this property as array or string? Like that:
echo $this->abc; // return first element of array: 123
echo $this->abc['status']; // return element by key: close
Maybe getter and setter or Reflection?
EDIT:
I prepare some like this, but all returns id value:
class Test {
private $abc;
public function __construct() {
$this->abc = array(
'id' => '123',
'status' => 'close'
);
}
public function __get($key) {
if ($key === 'abc') {
echo $this->abc['id'];
}
}
}
$t = new Test();
echo $t->abc['id']; // return 123 - correct!
echo $t->abc['status']; // return 123 - incorrect, should be return 'close' string
echo $t->abc; // return 123 - correct
Any suggestion?
Actually you can't do exactly what your example shows.
Magic methods (what a silly name, btw) simply allow you to get and set properties, so that some_object->a can be handled with custom code, but you cannot tell PHP to handle
some_object->a and some_object->a[0] differently.
You are free to have your custom getter return an int, an array or an elephant, but that's it.
EDIT: Your code does nothing but print abc['id'] each time the property is referenced.
abc is still handled as any plain old property.
Let's replace echo with return
public function __get($key) {
if ($key === 'abc') {
return$this->abc['id'];
}
}
Now whenever you reference abc, the getter gives you "123".
Demonstration:
echo $t->abc['id']; // 'id' evaluates to 0, so result is "1" ("123"[0])
echo $t->abc['status']; // same thing
echo $t->abc; // "123" - correct (of sorts)
echo $t->abc[1]; // "2" (2nd character of "123")
You are also free do do stupid things like that:
class fairytale {
private static $handsome =
array ("Prince Valliant", "Superman", "Flash Gordon");
private static $ugly =
array ("Michael Moore", "Condoleezza Rice", "Ronald McDonald");
function __get ($prop)
{
if ($prop=='frog')
return self::$handsome;
if (preg_match ('/^frog\\[([0-9]*)\\]$/', $prop, $res))
return self::$ugly[$res[1]];
}
}
function kiss ($prince)
{
echo "$prince appears in a puff of smoke...\n";
}
$pond = new fairytale();
$frog1 = $pond->frog[0]; // <-- array subscript parsed before getter is called
$frog2 = 'frog[0]';
$frog2 = $pond->$frog2; // <-- array subscript parsed inside getter
kiss ($frog1);
kiss ($frog2); // <--- surprise!
As a side note, abusing custom getters/setters to turn frogs into princes might be a lot of fun and a fine display of PHP expertise, but it's unlikely to produce readable and maintainable code.
Just my opinion, of course.
If you want to process the value when fetch or set the value, you can use __get / __set
You can use magic methods __set and __get, for example
class someClass{
private $_arr = array();
public function __set($key, $val){
if(!array_key_exists($key, $this->_arr)){
$this->_arr[$key] = array();
}
$this->_arr[$key] = array_merge($this->_arr[$key], (array)$val);
}
public function &__get($key) {
return $this->_arr[$key];
}
}
$obj = new someClass();
$obj->setvalue = array(5,6,7);
$obj->setvalue = 4;
You could also just do
reset($this->abc);
for the first element.
I'm finding it difficult to find a card ranking tutorial, or even some source code to read off to point me in the right direction.
I'm basically going in the direction of creating multiple functions with multiple in_array And writing them from scratch, as doing this will make it easy for three of a kind. Example
function is_trip($card1, $card2, $card3)
{
if (in_array($card1, $aces) && in_array($card2, $aces) && in_array($card3, $aces))
{
$score = 9500;
$rank = 'Three Aces';
}
if (in_array($card1, $kings) && in_array($card2, $kings) && in_array($card3, $kings))
{
$score = 9000;
$rank = 'Three Kings';
}
} And so on ...
So that would most likely work with trips, but then for a straight flush I would use a method of the way the cards are organized by number, as they're in the array in suit order.
So a straight flush would be hopefully as simple as $highcard + $lowcard / 2 == $midcard if that is true then you have a straight flush.
As for a straight, I'm stuck and would most likely have to use an array with my current mind set but writing that would seem like a lot of code when it is most likely simpler..
And for flushes it wouldn't be difficult to use the in_array as I'd only need to range 1-13 14-26 27-39 40-52 in an in_array to determine a flush, but then I'd need $highcard value $midcard value to also play a role to determine a flush against others.
You may of got to this point and thought, What's his question??
Well, my question is.. Am I going the right way about ranking the cards, should I use a bucket counting method to put the ranks into a bit-code and use a lookup table? Or have you any advice on where I should be heading if my methods of doing it are completely stupid..
Thanks in advance for any help.
It's very rough, and untested, but what about something like: -
<?php
$hand = new Hand;
$hand->addCard(new Card(RankInterface::ACE, SuitInterface::SPADE));
$hand->addCard(new Card(RankInterface::QUEEN, SuitInterface::HEART));
$hand->addCard(new Card(RankInterface::KING, SuitInterface::CLUB));
$isFlush = isFlush($hand);
Using something like: -
<?php
namespace Card;
interface SuitInterface {
const
SPADE = 'spade',
HEART = 'heart',
DIAMOND = 'diamond',
CLUB = 'club';
}
interface RankInterface {
const
JOKER = 0,
ACE = 1,
TWO = 2,
THREE = 3,
FOUR = 4,
FIVE = 5,
SIX = 6,
SEVEN = 7,
EIGHT = 8,
NINE = 9,
TEN = 10,
JACK = 11,
QUEEN = 12,
KING = 13;
}
class Card {
protected
$rank,
$suit;
public function __construct($rank, $suit) {
$this->rank = $rank;
$this->suit = $suit;
}
public function getRank() {
return $this->rank;
}
public function getSuit() {
return $this->suit;
}
public function isSameRank(Card $card) {
return $this->getRank() === $card->getRank();
}
public function isSameSuit(Card $card) {
return $this->getSuit() === $card->getSuit();
}
}
class Hand
{
protected
$storage = array();
public function addCard(Card $card) {
$this->storage[] = $card;
return $this;
}
public function asArray() {
return $this->storage;
}
}
function isFlush(Hand $hand) {
$cards = $hand->asArray();
$first = array_shift($cards);
foreach($cards as $card) {
if( ! $first->isSameSuit($card)) {
return false;
}
}
return true;
}
You would then just need to add some individual pieces of logic for the various valid hands/combos.
Well I've thought of having ArrayList in PHP because it was extremely useful in PHP, and saving a lot of time.
I thought it'd be cool to have in PHP, so I did make an arrayList class in PHP:
Class ArrayList
{
public $arrayList;
function __construct()
{
$this->arrayList = array();
}
public function add($element)
{
$this->arrayList[] = $element;
}
public function remove($index)
{
if (is_numeric($index)) {
unset($this->arrayList[$index]);
}
}
public function get($index)
{
return $this->arrayList[$index];
}
}
Now, I noticed I need an list type more of a hashmap, so I can get items by keys.
Let's say I need to get mysql db name, so Ill just do $data->hashmap->get("db_name").
This will return the database name value.
Is there a way to do this?
PHP has built-in data types that do what you want:
A "hashmap" is an associative array
An "ArrayList" is simply an array
Example:
$my_hash_map = array('x' => 5, 'y' => 10);
$my_hash_map['x'] + $my_hash_map['y'] // => 15
$my_array_list = array();
$my_array_list[] = 5;
$my_array_list[0] // => 5
See Arrays in the PHP documentation.
In PHP arrays can have string keys. Also you could use stdClass.