My current code:
public function countThreads() {
$count = $this->threads->count();
if ($this->hasSubforum()) {
foreach ($this->subforums as $subforum) {
$count += $this->countThreads($subforum);
}
}
return $count;
}
I am currently accessing the "thread" as $this inside my model. I need to pass in the $subforum to itself but how can I do that in a class?
In my controller, I'm simply doing:
$forum = Forum::where('id', $id)->first();
$forum->countThreads();
How can I do recursion with this? thanks!
You don't need to pass any arguments*, you can call the countThreads method on the subforum $subforum->countThreads()
public function countThreads()
{
$count = $this->threads->count();
if ($this->hasSubforum()) {
foreach ($this->subforums as $subforum) {
$count += $subforum->countThreads();
}
}
return $count;
}
If you really want to pass it in as an argument, the correct way would be to write it as a service outside of the model
Related
I have the controller:
class Comments extends Controller
{
public function GenerateComments($id)
{
$theme = DB::table('New_Themes')
->where('id', $id)
->get();
$Comments = NewTheme_Comment::where('id_theme', $id)->get();
$array = $this->tree($Comments);
function tree($Comments, $parent_id = 0, $level=0, $c=0)
{
global $var;
global $array;
global $m;
foreach($Comments as $Comment)
{
if ($Comment['parent_id'] == $parent_id) {
$m++;
$array[$m][0]=$Comment['id'];
If ($level > $var) {$var++; $array[$m][1]=0;} else {
if ($c < 0) $array[$m][1]=$var-$level+1; else {$c--; $array[$m][1]=0;};
$var=$level;
};
tree($Comments, $Comment['id'], $level+1,$c);
}
};
return $this->$array;
};
return view('comments', ['Themes'=> $theme, 'Comments'=> $Comments, 'Array' => $array]);
}
The problem is
Method [tree] does not exist.
but I don't understand why it appears, if I am calling a function within a function (like that below)
$array = $this->tree($Comments);
function tree($Comments, $parent_id = 0, $level=0, $c=0)
{
return $this->$array;
}
Are there any ideas why this isn't working?
You are calling your function tree with $this which means PHP will look tree as a method inside Comments class instead of your GenerateComments method.
Change
$array = $this->tree($Comments);
To this
$array = tree($Comments);
Note: You are also defining your function after you are calling it. PHP will look tree as it is in the namespace so it'll either won't work. Instead just define your function before you call it. Like so
function tree($Comments, $parent_id = 0, $level = 0, $c = 0) {
// ...
}
$array = tree($Comments);
It is also not recommended to define your function inside of a function. Instead doing that, just make your tree function a method inside your controller and use that instead. Like so
class Comments extends Controller
{
public function GenerateComments()
{
// ...
$array = $this->tree($comments);
}
public function tree($tree)
{
// ...
}
}
Your tree function is inside the controller GenerateComments function.
It appears you want to use it as a class method.
Try calling the function with call_user_func this way:
$array = call_user_func('tree', $Comments);
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'm having hard time accomplishing one simple task. I have a method that would generate random number and depending on the outcome assign specific outcome to an array variable. What i want to do is get that array variable through instance method which would be called from the other class.
<?php
class MyClass
{
public $results = array(array());
public function simulated_games()
{
$game_series1=array(23,34,56);
$game_series2=array(31,42,67);
$iter_wins=array(array());
for($i=0; $i<10;$i++)
{
$random = rand(0,100);
for($b=0; $b<1;$b++)
{
if($random <= $game_series1[0])
{
$iter_wins[$i][$b]=3;
}
else if($random <= $game_series2[0]+$game_series2[1])
{
$iter_wins[$i][$b]=1;
}
}
}
$results=$iter_wins;
}
>here i create method just to return variable
public function get_simulated_games()
{
return $this->results;
}
}
<?php
$a= new MyClass();
$a->simulated_games();
$array = array();
>here is the issue, it return just 1, but supposed to return range numbers
$array=$a->get_simulated_games();
for($f=0; $f<sizeof($array);$f++)
{
for($g=0; $g<5;$g++)
{
echo $array[$f][$g];
}
echo '<br>';
}
?>
You have the error in results.
You modify interal function variable which is not set instead of class variable
change
$results=$iter_wins;
to
$this->results=$iter_wins;
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'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