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
Related
So I have this controller that passes an associative array called $pagedata to the view. Inside this array are 3 more associative arrays, and the view renders 3 select elements with the array data as options. I want to sort the 3 arrays but I don't want to write sort 3 times here or add order_by into the query methods, because there are dozens of similar pages and I don't want to write hundreds of sort method calls. I was told I could solve this in the constructor. I was wondering if there's an OOP solution that lets me automatically sort all child arrays inside $pagedata.
class Sku extends CI_Controller {
protected $pagedata = array();
public function __construct()
{
parent::__construct();
$this->load->model('mc');
}
public function inventory()
{
$this->pagedata['class_ids'] = $this->mc->get_class_ids();
$this->pagedata['retail_readys'] = $this->mc->get_all_retail_ready();
$this->pagedata['statuses'] = $this->mc->get_all_status();
}
}
Edit:
I'm exploring using an ArrayObject or wrapping $pagedata in an object and watch for changes.
ok this will be painfull for codeigniter but yes a kind of solution
public function __construct()
{
parent::__construct();
$this->load->model('mc');
$class_ids = $this->mc->get_class_ids();
$class_ids = $this->sortAscending($class_ids, $key);
$this->pagedata['class_ids'] = $class_ids;
$retail_readys = $this->mc->get_all_retail_ready();
$class_ids = $this->sortAscending($class_ids, $key);
$this->pagedata['class_ids'] = $class_ids;
$statuses = $this->mc->get_all_status();
$statuses = $this->sortAscending($class_ids, $key);
$this->pagedata['statuses'] = $statuses;
}
function sortAscending($accounts, $key)
{
$ascending = function($accountA, $accountB) use ($key) {
if ($accountA[$key] == $accountB[$key]) {
return 0;
}
return ($accountA[$key] < $accountB[$key]) ? -1 : 1;
};
usort($accounts, $ascending);
return $accounts;
}
public function inventory()
{
// already get values
//$this->pagedata['class_ids'] = $this->mc->get_class_ids();
//$this->pagedata['retail_readys'] = $this->mc->get_all_retail_ready();
//$this->pagedata['statuses'] = $this->mc->get_all_status();
$this->load->view('index',$this->pagedata);
}
public function another_function()
{
// already get values
//$this->pagedata['class_ids'] = $this->mc->get_class_ids();
//$this->pagedata['retail_readys'] = $this->mc->get_all_retail_ready();
//$this->pagedata['statuses'] = $this->mc->get_all_status();
$this->load->view('another page',$this->pagedata);
}
I am aware that a class cannot be defined within a class in php, however I'm curious if there's another way to achieve the desired effect.
I currently have a set of 3 objects used to conduct a search. The first is called $search_request. It contains properties like $keywords (string), $search_results_per_page (int), $page_requested (int), $owner_id (int)
I also have an object called $search_result, it contains properties like $total_matches (int), $result_set (array of objects)
Finally I have the $search_handler object which contains the $search_request and $search_result, along with functions that build the $search_result based on the $search_request.
Usage goes like so:
$search_handler = new search_handler();
$search_handler->search_request->keywords = "cats, dogs";
$search_handler->search_request->search_results_per_page = 10;
$search_handler->search_request->page_search_requested = 1;
$search_handler->get_search_result();
echo $search_handler->search_result->total_matches;
foreach($search_handler->search_result->result_set)
{
//do something
}
All of this works fine. The problem is I want to repeat this model for different objects, so currently I'm forced to use the hackey solution of the "search_" prefix on each class.
I'd like to have something like:
class search
{
public class request
{
$keywords = "";
$search_results_per_page = 5;
$page_requested = 1;
}
public class result
{
$total_matches = null;
$result_set = array();
}
public get_results()
{
//check cache first
$cached = look_in_cache(md5(serialize($this->request)));
if($cached)
{
$this->result->result_set = $cached;
$count = count($cached);
$this->result->total_matches = $count;
}
else
{
//look in db
$results = get_results_from_database($this->request->keywords); //db call goes here
$this->result->result_set = $results;
$count = count($results);
$this->result->total_matches = $count;
}
}
}
//usage
$search = new search();
$search->request->keywords = "cats, dogs";
$search->request->search_results_per_page = 10;
$search->request->page_search_requested = 1;
$search->get_results();
echo $search->results->total_matches;
foreach($search->results->result_set as $result)
{
//do something
}
If for whatever reason you don't want to have those classes you need in different files you can do the following
<?php
class search
{
var $request;
var $result;
public function __construct()
{
$this->request = new StdClass();
$this->request->keywords = "";
$this->request->search_results_per_page = 5;
$this->request->page_requested = 1;
$this->result = new StdClass();
$this->result->total_matches = null;
$this->result->result_set = array();
}
// ...
}
$search = new search();
var_dump($search->request, $search->result);
?>
There's several things to suggest here
First, if you're using PHP 5.3 or later, consider using namespaces and autoloading. That would allow you to make classes like \Cat\Search and \Dog\Search.
Second, I would avoid setting object properties directly. I would highly suggest you make your variables protected and use getters and setters instead. Limit your object interaction to methods and you can control the process much more easily.
$search_handler = new search_handler();
$search_handler->setKeywords(array("cats", "dogs"));
You could define your request and result classes as separately, and then have variables in your main class be assigned to instances of those.
Something like:
class result{
...
}
class request{
...
}
class search{
var results;
var request;
function __construct(){
$results = new ArrayObject();
$request = new stdClass();
}
...
}
Then you can assign/append to the list of results in your search function
and you can just assign a request object to your 'request' variable
$this->results[] = $newresult;
and loop through them when displaying
I'm working on a class that will count twitter reactions to a link and also display them.
Currently I'm working on the counting portion and my count always equals 0 even though the array created in the constructor has multiple elements.
Any help would be appreciated. Thanks.
<?php
class TwitterReactions{
function __construct($url){
if($url){
$output=array();
$query = 'http://search.twitter.com/search.json?q='.$url;
$reactions=file_get_contents($query);
$reactions_array=json_decode($reactions, TRUE);
foreach($reactions_array as $results){
foreach($results as $result){
$output['user'][]=$result['from_user'];
$output['image'][]=$result['profile_image_url'];
$output['message'][]=$result['text'];
$output['date'][]=$result['created_at'];
}
}
return $output['user'];
} else {
echo "<p>Please provide a url...</p>";
}
}
function count_reactions($output){
//print_r($output);
$count = count($output['user']);
return $count;
}
}
?>
I agree with some of what Aliaksandr Astashenkau has in his answer but there are still some problems with the class.
It looks to me as if your initial problem was that you were expecting the __construct to return $output and you were then passing the object that you created into the count_reactions() method. Something like this...
$twitter = new TwitterReactions($url);
$count = $twitter->count_reactions($twitter);
You don't have your call to the count_reactions() method posted so this is just a hunch. If that's how you were using it the constructor it isn't meant to be used that way. Constructors always return a new instance of the class. You cannot return any other type of value from a constructor. You cannot use the return keyword in the __construct method.
As Aliaksandr Astashenkau points out $output should be a class member. I would also make $count a class member. In this case there's not much of a point of making either private so you don't really need accessor methods either but you can include them if you want.
I would make the class something like this...
<?php
class TwitterReactions
{
public $url = '';
public $output = array();
public $count = 0;
function __construct($url)
{
$this->url = $url;
$query = 'http://search.twitter.com/search.json?q='.$url;
$reactions=file_get_contents($query);
$reactions_array=json_decode($reactions, TRUE);
foreach($reactions_array as $results)
{
foreach($results as $key => $result)
{
// I find it easier if the data is arranged by each tweet but you can keep the array structure how you have it.
$this->output[$key]['user'] = $result['from_user'];
$this->output[$key]['image'] = $result['profile_image_url'];
$this->output[$key]['message'] = $result['text'];
$this->output[$key]['date'] = $result['created_at'];
}
}
$this->count = count($this->output);
}
}
You could then use the class like this
$twitter = new TwitterReactions($url);
// you now have access to output directly
$twitter->output;
// and count
$twitter->count;
Anyhow there are many ways to accomplish the same thing but I hop this helps give you some ideas.
You probably want to make an $output array to be a property of your class. Then $this->output would be availbale in count_reactions method.
<?php
class TwitterReactions {
public $output;
function __construct($url){
if($url){
$output=array();
$query = 'http://search.twitter.com/search.json?q='.$url;
$reactions=file_get_contents($query);
$reactions_array=json_decode($reactions, TRUE);
foreach($reactions_array as $results){
foreach($results as $result){
$output['user'][]=$result['from_user'];
$output['image'][]=$result['profile_image_url'];
$output['message'][]=$result['text'];
$output['date'][]=$result['created_at'];
}
}
$this->output = $output;
return $output['user'];
} else {
echo "<p>Please provide a url...</p>";
}
}
function count_reactions($output){
//print_r($this->output);
$count = count($this->output['user']);
return $count;
}
}
I have a array like this in a function:
$value = array("name"=>"test", "age"=>"00");
I made this $value as public inside the class abc.
Now in my other file, I want to access the values from this array, so I create an instance by:
$getValue = new <classname>;
$getValue->value..
I'm not sure how to proceed so that then I can access each element from that array.
You mentioned that $value is in a function, but is public. Can you post the function, or clarify whether you meant declaring or instantiating within a function?
If you're instantiating it that's perfectly fine, and you can use the array keys to index $value just like any other array:
$object = new classname;
$name = $object->value["name"];
$age = $object->value["age"];
// Or you can use foreach, getting both key and value
foreach ($object->value as $key => $value) {
echo $key . ": " . $value;
}
However, if you're talking about declaring public $value in a function then that's a syntax error.
Furthermore if you declare $value (within a function) without the public modifier then its scope is limited to that function and it cannot be public. The array will go out of scope at the end of the function and for all intents and purposes cease to exist.
If this part seems confusing I recommend reading up on visibility in PHP.
The same as you would normally use an array.
$getValue = new yourClass();
$getValue->value['name'];
Use code
foreach($getValue->value as $key=>$value)
<?php
interface Nameable {
public function getName($i);
public function setName($a,$name);
}
class Book implements Nameable {
private $name=array();
public function getName($i) {
return $this->name[$i];
}
public function setName($i, $name) {
return $this->name[$i] = $name;
}
}
$interfaces = class_implements('Book');
if (isset($interfaces['Nameable'])) {
$bk1 = new Book;
$books = array('bk1', 'bk2', 'bk3', 'bk4', 'bk5');
for ($i = 0; $i < count($books); $i++)
$bk1->setName($i, $books[$i]);
for ($i = 0; $i < count($books); $i++)
echo '// Book implements Nameable: ' . $bk1->getName($i) . nl();
}
?>
class Assignation {
private $VVal_1 = 1;
private $VNam_1 = "One";
//....Multiple Items
private $VVal_2000 = 2000; //For Example
private $VNam_2000 = "Two Thousands"; //For Example
private static $Hash = array(); //How to initialize???
private static function Assigning(){
//This function for to assign the array elements (initialize)
global $Hash;
$this->Hash = array(); //to empty Hash variable and not add more data than it should.
$this->Hash[$this->VVal_1] = $this->VNam_1;
//....Multiple Items
$this->Hash[$this->VVal_2000] = $this->VNam_2000;
}
public static function GetVal($Nam) {
$this->Assigning(); //or use self::Assigning(); //I want to avoid this call
if (array_search($Nam, $this->Hash))
return array_search($Nam, $this->Hash);
return -1;//error
}
public static function GetNam($Val) {
$this->Assigning(); //or use self::Assigning(); //I want to avoid this call
if (array_key_exists($Val, $this->Hash))
return $this->Hash[$Val];
return "Error";
}
}
Class Testing {
static $OtherVal = Assignation::GetVal("BLABLA"); //for example
static $OtherNam = Assignation::GetNam(20); //for example
//Other functions...
}
Hi, you can see my script or code php...
I need to initialize the Hash array, this have static word because I need to use it in other static function. And this "other function" need to use it for other static variable...
I need to know how to implement it the right way..
Thanks chep.-.
<?php
echo "pre-Class Assignation<br/>";
class Assignation {
private $VVal_1 = 1;
private $VNam_1 = "One";
private $VVal_2K = 2000;
private $VNam_2K = "Two Thousands";
private static $Hash = array();
private static function Assigning(){
if(!empty(self::$Hash)) return;
self::$Hash[$this->VVal_1] = $this->VNam_1;
self::$Hash[$this->VVal_2K] = $this->VNam_2K;
}
public static function GetVal($Nam) {
self::Assigning();
if (array_search($Nam, self::$Hash)) return array_search($Nam, self::$Hash);
return -1;//error
}
public static function GetNam($Val) {
self::Assigning();
if (array_key_exists($Val, self::$Hash)) return self::$Hash[$Val];
return "Error";
}
}
echo "post-Class Testing<br/>";
echo Assignation::GetVal("BLABLA");
echo "post-Class Mid<br/>";
echo Assignation::GetNam(20);
echo "post-Class Sample<br/>";
//Testing::MyPrint();
?>
This code is not running, somebody help me testing the code...
result:
pre-Class Assignation
post-Class Assignation
post-Class Testing
that mean:
" echo Assignation::GetVal("BLABLA");"
have error...
In Assigning(), try using self::$Hash rather than $this->Hash and remove the global $Hash. Same applies for calling Assigning(): self::Assigning() as your comments suggest.
$this references the current object, so you must use self:: for all static functions and member data when inside the class.
Also, if this is your real code and not just a sample, you may want to check whether you have already done initialization, otherwise you will be doing it for every call to GetVal() and GetNam(). You could do this by adding something like if(!empty(self::$Hash)) return at the beginning of Assigning()
EDIT
private static function Assigning() {
if(!empty(self::$Hash)) return; // already populated
self::$Hash = array();
self::$Hash[$this->VVal_1] = $this->VNam_1;
//....Multiple Items
self::$Hash[$this->VVal_2K] = $this->VNam_2K;
}