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;
}
}
Related
Hi i am using foreach in php oops to output data from the mysqlbut each data outputs twice please check my code and help it i have tried but no correct result
Here is the code below i have used
class getdata extends db{
public function getdata(){
$sql = "SELECT * FROM users";
$results = $this->connect()->query($sql);
$numrows = $results->num_rows;
if($numrows > 0){
while($row = $results->fetch_assoc()){
$data[] = $row;
}
return $data;
}
else{
echo 'no values';
}
}
}
class showusers extends getdata{
//show users
public function showusers(){
$datas = $this->getdata();
foreach($datas as $data){
echo $data['id'].'<br>';
echo $data['name'].'<br>';
}
}
}
$showusers = new showusers();
$showusers->showusers();
Don't give your function the same name as your class.
With $showusers = new showusers(); you are already executing the showusers function.
To cite php.net:
For backwards compatibility with PHP 3 and 4, if PHP cannot find a __construct() function for a given class, it will search for the old-style constructor function, by the name of the class.
Source:https://www.php.net/manual/en/language.oop5.decon.php
So your function showusers() is treated as a constructor for your showusers class and therefore is executed twice. Once when you create an object of the class and once when you call the method.
your code is a bit convoluted I'd suggest passing the database connection object rather than extending continiously.
In this case your constructor showUsers() outputs a list of users. therefore it repeats because you are calling this function twice.
$showusers = new showusers(); // prints users
$showusers->showusers(); // prints users again
move your display function
class showusers extends getdata{
$data;
//initialize
public function showusers(){
$this->data = $this->getdata();
}
//show users
public function displayUsers(){
foreach($this->data as $data){
echo $data['id'].'<br>';
echo $data['name'].'<br>';
}
}
}
$showusers = new showusers();
$showusers->displayUsers();
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 am working with lemonade-php. My code is at https://github.com/sofadesign/limonade.
The issue I am having is when I try to run
class syscore {
public function hello(){
set('post_url', params(0));
include("./templates/{$this->temp}/fullwidth.tpl");
return render('fullwidth');
}
}
which then loads the fullwidth.tpl and runs function fullwidth
fullwidth.tpl
<?php
global $post;
function fullwidth($vars){
extract($vars);
$post = h($post_url);
}
print_r($this->post($post));
?>
it seems to pass the $post_url but I can not pass it again to the print_r($this->post($post));
However when I try to run print_r($this->post($post)) inside the fullwidth function it says it can not find the post() function
I have tried a number of things like below
function fullwidth($vars){
extract($vars);
$post = h($post_url);
print_r(post($post));
}
I tried re connecting to the syscore by
$redi = new syscore();
$redi->connection() <-- this works
$redi->post($post) <-- this does not
Here is my full class syscore
class syscore {
// connect
public function connect($siteDBUserName,$siteDBPass,$siteDBURL,$siteDBPort, $siteDB,$siteTemp){
for ($i=0; $i<1000; $i++) {
$m = new Mongo("mongodb://{$siteDBUserName}:{$siteDBPass}#{$siteDBURL}:{$siteDBPort}", array("persist" => "x", "db"=>$siteDB));
}
// select a database
$this->db = $m->$siteDB;
$this->temp = $siteTemp;
}
public function hello(){
set('post_url', params(0));
include("./templates/{$this->temp}/fullwidth.tpl");
return render('fullwidth');
}
public function menu($data)
{
$this->data = $data;
$collection = $this->db->redi_link;
// find everything in the collection
//print $PASSWORD;
$cursor = $collection->find(array("link_active"=> "1"));
if ($cursor->count() > 0)
{
$fetchmenu = array();
// iterate through the results
while( $cursor->hasNext() ) {
$fetchmenu[] = ($cursor->getNext());
}
return $fetchmenu;
}
else
{
var_dump($this->db->lastError());
}
}
public function post($data)
{
$this->data = $data;
$collection = $this->db->redi_posts;
// find everything in the collection
//print $PASSWORD;
$cursor = $collection->find(array("post_link"=> $data));
if ($cursor->count() > 0)
{
$posts = array();
// iterate through the results
while( $cursor->hasNext() ) {
$posts[] = ($cursor->getNext());
}
return $posts;
}
else
{
var_dump($this->db->lastError());
}
}
}
It looks like you are having some issues understanding the execution path that PHP is taking when trying to render your template. Let's take a more in-depth look, shall we?
// We're going to call "syscore::hello" which will include a template and try to render it
public function hello(){
set('post_url', params(0)); // set locals for template
include("./templates/{$this->temp}/fullwidth.tpl"); // include the template
return render('fullwidth'); // Call fullwidth(array('post_url' => 'http://example.com/path'))
}
The trick to solving this one is to understand how PHP include works. When you call include("./templates/{$this->temp}/fullwidth.tpl") some of your code is executing in the scope of the syscore object, namely:
global $post;
and
print_r($this->post($post));
fullwidth is created in the global scope at this point, but has not yet been called. When render calls fullwidth you're no longer in the syscore scope, which is why you cannot put $this->post($post) inside without triggering an error.
Ok, so how do we solve it? Glad you asked.
We could probably refactor syscore::post to be a static method, but that would then require syscore::db to be static, and always return the SAME mongodb instance (singleton pattern). You definitely do not want to be creating 1000 Mongo instances for each syscore instance.
We could just abuse the framework. A much poorer solution, but it will get the job done.
fullwidth.tpl
<?php
function fullwidth($vars){
$post_url = ''; // put the variables you expect into the symbol table
extract($vars, EXTR_IF_EXISTS); // set EXTR_IF_EXISTS so you control what is added.
$syscore_inst = new syscore;
$post = h($post_url);
print_r($syscore->post($post)); // I think a puppy just died.
}
Look the second way is a complete hack, and writing code like that will probably mean you won't get promoted. But it should work.
But let's say you wanted to get promoted, you would make good, shiny code.
// Note: Capitalized class name
class Syscore {
protected static $_db;
public static function db () {
if (! static::$_db) {
static::$_db = new Mongo(...);
}
return static::$_db;
}
// #FIXME rename to something more useful like "find_posts_with_link"
public static post($url) {
$collection = static::db()->redi_posts;
// find everything in the collection
$cursor = $collection->find(array("post_link"=> $url));
// Changed to a try-catch, since we shouldn't presume an empty find is
// an error.
try {
$posts = array();
// iterate through the results
while( $cursor->hasNext() ) {
$posts[] = ($cursor->getNext());
}
return $posts;
} catch (Exception $e) {
var_dump($this->db->lastError());
}
}
}
Then in your fullwidth function, we don't have to do any of that stupid nonsense of treating an instance method like it were a static method.
function fullwidth($vars){
$post_url = ''; // put the variables you expect into the symbol table
extract($vars, EXTR_IF_EXISTS); // set EXTR_IF_EXISTS so you control what is added.
$post = h($post_url);
print_r(Syscore::post($post)); // static method. \O/ Rainbows and unicorns.
}
I have seen these codes:
$result = $db->result($query);
$rows = $result->fetchAll();
how can I do similar effect? ($result contains methods?)
I think this is what you are looking for:
<?php
class test{
private $value = 0;
function foo(){
$this->value = 1;
return $this;
}
function bar(){
$this->value = 2;
echo $this->value;
}
}
$test = new test();
$result = $test->foo();
$result->bar();
?>
By having the method return itself, you can chain them together in this fashion.
Strictly speaking, you're asking about OOP in PHP, in which case, this is a reasonable example:
class HasResultMethod
{
public function result( $query )
{
return new HasFetchAllMethod();
}
}
class HasFetchAllMethod
{
public function fetchAll(){}
}
// you have a variable with a result method that has one parameter.
$result = $db->result($query);
// that returns an object which has a fetchAll method.
$rows = $result->fetchAll();
You probably are dealing with some wrapper around PDO, a library to interface with databases. Their query methods will return a PDOStatement which has methods which will allow you to get results from the DB. result is either a typo, or it behaves in a very similar way.
I got it already. What a great hint Headspin
http://sandbox.phpcode.eu/g/147bd.php
<?php
class foo{
function bar(){
return $this;
}
function fetch(){
echo "yeah";
}
}
$foo = new foo();
$result = $foo->bar();
$result->fetch();
That is easy
$db is instance of class that returnes class, so when you say
$db->result($query);
$db will return object
e.g.
//this method is inside $db class
function result($query)
{
$result = new Result();
$result->rows = mysql_query...
return $result;
}
and when you say
$result->fetchAll();
that is method inside class Result that will fetch all rows saved inside $result->rows;
e.g.
//method inside Result class
function fetchAll()
{
//fetch rows inside variable $this->rows
}
So basically what you can do with ORM (object relational mapping), you can return Array of objects, each object will represent one record from db
e.g.
Class User
{
var $ID;
var $Name;
var $LastName;
var $Email;
function load($row)
{
$this->ID = $row["ID"];
... etc
}
function save()
{
$sql = "update tbl_users set Name=:Name, LastName=:LastName, Email=:Email where ID=:ID";
//then execute your query
}
}
so how to get list of objects, its easy
select all records and add them into array
$ar = new Array();
for($i = 0; $i < count($rows); $i++)
{
$r = new User();
$r->load($rows[$i]);
}
return $ar;
simple as that...
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