Parse Rss Feeds in php inside a class - php

It is not so bad rendering RSS feeds from an index.php page I have seen a lot of examples of it. But I am having problems doing it from a class. This is what I have and I am sure I have many errors... PHP is not my strong point so if you could let me know where i am going wrong i would apprecite it...
<?php
class RssDisplay {
protected $fromrss;
protected $allitemscollected_feed;
public function __construct($urllink, $total_items){
$this->fromrss = $urllink;
$this->allitemscollected_feed = $total_items;
}
public function getItems($allitemscollected_feed){
$feed = simplexml_load_file($this->fromrss, $this->allitemscollected_feed);
return $feed;
$collected_items[] =$feed;
$this->set('collected_items', $collected_items);
}
foreach('allitemscollected' as $feed){
$items->title;
$items->pubDate;
$items->description;
}
}
from my index this is what I am doing:
$feed = new RssDisplay('http://feeds.feedburner.com/insidethehall?format=xml');

For starters i would advice you to take a look at Foreach and PHP OPP Basics because
Your foreach is not in any method
foreach('allitemscollected' as $feed){ is not valid because foreach first argument needs to be array_expression
You class is wrong
You did not print or echo anything
return $feed; was called early which would make other codes invisible
$this->set( method those not exists yet it was called $this->set('collected_items', $collected_items);
simplexml_load_file second argument needs to be a valid class name that extends SimpleXMLElement yet an integer is passed
Your Simple Class you look like this
class RssDisplay {
protected $maxItems;
private $xml;
public function __construct($url, $maxItems = 0) {
$this->xml = simplexml_load_file($url, "SimpleXMLIterator");
$this->maxItems = $maxItems;
}
public function getItems() {
return $this->xml->channel->item;
}
public function simpleDisplay() {
$it = ($this->maxItems == 0) ? $this->xml->channel->item : new LimitIterator($this->xml->channel->item, 0, $this->maxItems);
foreach ( $this->xml->channel->item as $feed ) {
printf("<div><h2><a href='%s'>%s</a></h2><i>%s</i><p>%s</p></div><br />", $feed->link, $feed->title, $feed->pubDate, $feed->description);
}
}
}
$rss = new RssDisplay("http://feeds.feedburner.com/insidethehall?format=xml");
$rss->simpleDisplay();
Output
Grantland previews the HoosiersFri, 02 Nov 2012 19:22:21 +0000Grantland: College Basketball Team Previews: Indiana There’s no shortage of offensive firepower with the Hoosiers, and the great thing about Tom Crean is that he’s never afraid to use it. Indiana was well inside the top half of the country in tempo last season, and with an extra year of chemistry it’s a good bet [...]Notebook: Creek shines in return from injuryFri, 02 Nov 2012 02:57:32 +0000Maurice Creek got off the bench and walked toward the Assembly Hall scorer’s table with just over 11 minutes left in the first half of Thursday night’s exhibition game against Indiana Wesleyan. Creek checked in with the official scorer, then waited patiently for the moment he’s been thinking about for more than 20 months — [...]
....... So may more

Your construct takes two paremeter, but you
used it with single paremeter.

Related

PHP - Multi threading and pools

I am using Pool object in PHP pthread, and made the following test script, to see how the pooling should work. I tought, that what pooling should do, is to get a given number of tasks, open up a maximum x number of workers, and assign them the tasks, and as soon as a worker finishes with a task, if more tasks are available, assign to that worker a new task.
Given the below example, and the above assumption:
class Work extends Threaded {
public $id;
public function __construct($id) {
$this->id = $id;
}
public function run() {
if ($this->id == 0) {
sleep(3);
echo $this->id . " is ready\n";
return;
} else {
echo $this->id . " is ready\n";
return;
}
}
}
$pool = new Pool(2, 'Worker', []);
for ($i=0; $i<4; $i++) $pool->submit(new Work($i));
while ($pool->collect());
$pool->shutdown();
I was expecting this script to output the following information:
1 is ready
2 is ready
3 is ready
0 is ready
because, there are essentially 2 workers available, and because of the sleep operatin the first worker stumbles upon, task 1,2,3 must be completed by the second worker.
Instead of this, the output I am getting is:
1 is ready
3 is ready
0 is ready
2 is ready
It is clear, that worker 1, gets assigned job 0, and job 2 at the get go, thus worker 2, after finishing job 1 and 3, just waits, instead of taking over job 2 from worker 1.
Is this a bug? Or is this intended to work this way?
My PHP version:
PHP 7.2.14 (cli) (built: Jan 9 2019 22:23:26) ( ZTS MSVC15 (Visual C++ 2017) x64 )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.2.0, Copyright (c) 1998-2018 Zend Technologies
For some reason my Docker has crapped itself now that I've updated Windows to 1809, so posting untested. (So sorry, no output to give atm)
Modified existing code I use in a project with your counter + sleep.
$pool = new Pool(2);
foreach ([0,1,2,3] as $count) {
$pool->submit(
new class ($count) extends Threaded
{
private $count;
public function __construct(int $count)
{
$this->count= $count;
}
public function run()
{
if ($this->count== 0) {
sleep(3);
echo $this->count . " is ready\n";
} else {
echo $this->count . " is ready\n";
}
}
}
);
}
while ($pool->collect());
$pool->shutdown();
I use anonymous class (new class ($count) extends Threaded) as the submit() param.
On the server this runs perfectly, using a Docker instance running PHP ZTS 7.2.13 on Alpine 3.8
Let me answer: from what I know about pthreads in php, pool is like number of proccessing php.exe that can be run at the same times.
So in your case, you define two pool by using new Pool(2, 'Worker', []);
So let's make abstract explanation about it. There is 2 Pool, call it as PoolA and PoolB.
Loop from 0 to 3, each loop submit task to Pool.
There are 4 tasks from 0 to 3, lets call them by task0, task1, task2, task3.
When loop occur, from my perspective, it should be queue like this
PoolA -> submit task0
PoolB -> submit task1
PoolA -> submit task2
PoolB -> submit task3
But from class Work that will be task0, ... till task3.
Situation/Condition
You define some logic in run() => when parameter(in this case $id from constructor) is 0, then sleep(3).
From this situation, PoolA is which submit task0 that contains parameter($id) is value 0, PoolA will wait for 3 seconds. PoolA also submit task2.
On the other hand, PoolB submit task1 and task3, from this situation, doesn't need to wait for 3 seconds.
So when while($pool->collect()); is run, possible queue that's most likely happen
task1 (PoolB)
task3 (PoolB)
task0 (PoolA) ->>>> PoolA delayed because from task0 needs to sleep for 3 seconds
task2 (PoolA)
So I think it's correct when outputs are
1 is ready
3 is ready
0 is ready
2 is ready
There is a questions.
Why is only PoolA that delayed, even if PoolA delayed why task2 didn't submit to PoolB or why task1 or task3 not submit to PoolA??
Well, I don't understand too. I have task similar to yours, after many experiments, I'm not sure pthreads which use Pool & Threaded is multi-threading or multiprocessing.
Echoing from the individual threads can be deceiving.
I often find that they seem like they are executing before they are even called. I'd recommend avoiding echoing from inside threads, unless you don't care about the order, as it can be still be useful to test for specific circumstances, etc.
Below is some code which should resolve any questions of when the code is executing, as this code sorts the results by the actual time they executed. (It's also a nice example of how to get results back from a thread pool.)
<?php
class Work extends Threaded {
public $id;
public $data;
private $complete = false;
public function __construct($id) {
$this->id = $id;
}
public function run() {
$temp = array();
if ($this->id == 0) {
echo "<pre>".$this->id . " started (from inside threaded)";
$temp[] = array(microtime(true), $this->id . " started");
sleep(3);
}
echo "<pre>".$this->id . " is ready (from inside threaded)";
$temp[] = array(microtime(true), $this->id . " is ready");
$this->data = (array) $temp; // note: it's important to cast as array, otherwise you will get a volitile
$this->complete = true;
}
public function isDone() {
return $this->complete;
}
}
// we create a custom pool, to pass on our results
class ExamplePool extends Pool {
public $dataAr = array(); // used to return data after we're done
private $numTasks = 0; // counter used to know when we're done
private $numCompleted = 0; // keep track of how many threads finished
/**
* override the submit function from the parent
* to keep track of our jobs
*/
public function submit(Threaded $task) {
$this->numTasks++;
parent::submit($task);
}
/**
* used to wait until all workers are done
*/
public function process() {
// Run this loop as long as we have
// jobs in the pool
while ($this->numCompleted < $this->numTasks) {
$this->collect(function (Work $task) {
// If a task was marked as done, collect its results
if ($task->isDone()) {
//this is how you get your completed data back out [accessed by $pool->process()]
$this->dataAr = array_merge($this->dataAr, $task->data);
$this->numCompleted++;
}
return $task->isDone();
});
}
// All jobs are done
// we can shutdown the pool
$this->shutdown();
return $this->dataAr;
}
}
$pool = new ExamplePool(4);
for($i=0; $i<4; $i++) {
$pool->submit(new Work($i));
}
$retArr = $pool->process();
usort($retArr, 'sortResultsByTime'); // sort the results by time
// echo out the sorted results
echo "<br><br>";
for($i=0;$i<count($retArr);$i++){
echo number_format($retArr[$i][0], 4, ".", "").' '.$retArr[$i][1]."\n";
}
function sortResultsByTime($a, $b) {
return $a[0] > $b[0];
}
?>
Please note the code above yields this for me:
0 started (from inside threaded)
0 is ready (from inside threaded)
1 is ready (from inside threaded)
2 is ready (from inside threaded)
3 is ready (from inside threaded)
1609458117.8764 0 started
1609458117.8776 1 is ready
1609458117.8789 2 is ready
1609458117.8802 3 is ready
1609458120.8765 0 is ready
And as expected, the stuff echoed from inside the threads seems weird, however if you store the results, and sort them by the time they were executed, you can see it acts as expected.

Query returns content from previous functions

I have a Chat.php file containing everything query-related. Then there is a Core.php containing connection to database and basic functions used in Chat.php like "query" and "rows" which processes the "query" into array.
In Chat.php there are two functions, the second one printing content of the first when using print_r($this->rows());. checkForLastMessage() is supposed to check one table to see if there are new messages to be pulled from another table with function getNewMessages().
This is how it looks like:
Core.php
<?php
class Core
{
...
public function query($sql)
{
$this->result = $this->db->query($sql);
}
public function rows()
{
for($x = 1; $x <= $this->db->affected_rows; $x++)
{
$this->rows[] = $this->result->fetch_assoc();
}
return $this->rows;
}
}
Chat.php
<?php
class Chat extends Core
{
public function checkForLatestMessage($chatid, $iam)
{
$userinchat='for'.$iam;
$this->query("SELECT anonchat.$userinchat FROM anonchat WHERE anonchat.chatid=$chatid");
$printarray = Array();
$printaray = '';
foreach( $this->rows() as $id )
{
$printarray[] = $id[$userinchat];
}
if($printarray[0] != '')
{
$this->getNewMessages($chatid, $printarray[0]);
}
}
public function getNewMessages($chatid, $requiredMessages)
{
$this->query("SELECT anonmessage.content, anonmessage.timeposted FROM anonmessage WHERE anonmessage.messageid IN ($requiredMessages) ORDER BY anonmessage.timeposted ASC");
print_r($this->rows());
}
The last print_r contains elements from the previous function. I don't know why that is.
Edit. This is the output:
Array ( [0] => Array ( [for1] => 2,4,6 ) [1] => Array ( [content] =>
Message 2 [timeposted] => 2017-08-04 16:12:34 ) [2] => Array (
[content] => Message 4 [timeposted] => 2017-08-04 16:12:48 ) [3] =>
Array ( [content] => Message 6 [timeposted] => 2017-08-04 16:13:03 ) )
Element [0] of array (the one with "for1") is remaining from previous function.
To answer your question, you're initializing the class property $this->rows in the first method and then the 2nd method is appending to it. You need to reset $this->rows before adding to it.
public function getNewMessages($chatid, $requiredMessages)
{
$this->rows = null;
$this->query("SELECT anonmessage...");
print_r($this->rows());
}
Or better yet, reset the variable in the query() method. That way you don't have to do it each time.
Please don't take offense when I say that this is a bad design.
You're trying to write your own DAL (Data Abstraction Layer). This is a very complicated task and there are already lots of implementations out there. The Core class is going to become massive, complicated, and unwieldy when you try to adapt it to a dozen other classes.
PHP only supports a single inheritance so right off the bat you shot your self in the foot because any class that needs DB interactions will have to extend Core and you won't be able to extend anything else.
Consider keeping things simple for now and let each method handle their own queries and DB interactions. Focus on major concepts like DRY, encapsulation and keeping your classes focused on their responsibility.
Ex. checkForLatestMessage() what is this supposed to do? It sounds like should check for messages and then return a boolean (true|false) but instead it is calling getNewMessages() which outputs some data.
I don't know enough about your application to really suggest something useful but this feels a bit better than the path you're heading down. Notice we're not inheriting from Core so you're free to inherit from something else. The methods are concise and do what they say. You'd probably also save a few lines of code this way and it's easier to read.
<?php
class Chat
{
public function hasNewMessages($chatid, $iam)
{
// Query using PDO properly
return (bool)$hasNewMessages;
}
public function getNewMessages($chatid, $requiredMessages)
{
// Query using PDO properly
// An array of data or objects
return $messages;
}
}
/******** Client Code ***********/
$chat = new Chat();
if ($chat->hasNewMessages()) {
foreach ($chat->getNewMessages($id, $required) as $message) {
// $message
}
}
Just some of my thoughts... good luck.

"Family Tree" Data Structure

I'm looking for a way to represent a family tree in PHP. This means that children will need to inherit from two (or more) parents.
Here are the requirements:
1, 2, or more parents
Bonus points if I can attach metadata like a last name or relationship status
Here is my non-working attempt (no arrays as keys, sadly):
$tree = array(
'uncle' => false, // no children
array('mom', 'dad') => array(
'me' => false,
array('brother', 'sister-in-law') => array(
'niece' => false
)
)
);
The question is, how can I represent a family tree with these requirements?
You won't be able to do it all in a single array() like that. You can set up trees like that, but setting up more complicated graphs with multiple parents and other relations requires multiple lines of code.
It'll help a lot if you throw some OO at this. Let's create a Person class to help manage the relationships. Fundamentally, we've got people and their relationships with other people, so we'll start there.
Person class
What I imagine is each person having an array of relationships. This array will be indexed first by the type of relationship, for example "parents" or "children". Each entry will then be an array of Persons.
class Person {
var $name, $relations;
function __construct($name) {
$this->name = $name;
$this->relations = array();
}
function addRelation($type, $person) {
if (!isset($this->relations[$type])) {
$this->relations[$type] = array();
}
$this->relations[$type][] = $person;
}
// Looks up multiple relations, for example "parents".
function getRelations($type) {
if (!isset($this->relations[$type])) {
return array();
}
return $this->relations[$type];
}
// Looks up a single relation, for example "spouse".
function getRelation($type) {
$relations = $this->getRelations($type);
return empty($relations) ? null : $relations[0];
}
function __toString() {
return $this->name;
}
Friendly adders and getters
With the above as a foundation we can then add some friendlier-named methods. For illustration we'll handle the parent/child relation and spouses.
function addParents($mom, $dad) {
$mom->addChild($this);
$dad->addChild($this);
}
function addChild($child) {
$this ->addRelation('children', $child);
$child->addRelation('parents', $this);
}
function addSpouse($spouse) {
$this ->addRelation('spouse', $spouse);
$spouse->addRelation('spouse', $this);
}
function getParents () { return $this->getRelations('parents'); }
function getChildren() { return $this->getRelations('children'); }
function getSpouse () { return $this->getRelation ('spouse'); }
}
Creating people
Now we can create a couple of people and setup their relationships. Let's try Billy and his parents John and Jane.
$john = new Person('John');
$jane = new Person('Jane');
$billy = new Person('Billy');
$john ->addSpouse ($jane);
$billy->addParents($jane, $john);
And we can check out their relationships like so:
echo "John is married to " . $john->getSpouse() . ".\n";
echo "Billy's parents are " . implode(" and ", $billy->getParents()) . ".\n";
Output:
John is married to Jane.
Billy's parents are Jane and John.
Display family tree
We can traverse the graph recursively if it grows bigger. Here's an example tree-walking function which displays a rudimentary family tree. I've added Sara, her husband Mike, and their son Bobby to the mix.
$john = new Person('John');
$jane = new Person('Jane');
$sara = new Person('Sara');
$mike = new Person('Mike');
$bobby = new Person('Bobby');
$billy = new Person('Billy');
$john ->addSpouse ($jane);
$sara ->addParents($jane, $john);
$sara ->addSpouse ($mike);
$bobby->addParents($sara, $mike);
$billy->addParents($jane, $john);
function displayFamilyTree($root, $prefix = "") {
$parents = array($root);
if ($root->getSpouse() != null) {
$parents[] = $root->getSpouse();
}
echo $prefix . implode(" & ", $parents) . "\n";
foreach ($root->getChildren() as $child) {
displayFamilyTree($child, "....$prefix");
}
}
displayFamilyTree($john);
Output:
John & Jane
....Sara & Mike
........Bobby
....Billy
Edit: Here's #Wrikken's comment below, reproduced for readability:
About it indeed. IMHO add a from-until date to every relationship though (possibly NULL for no end). Divorces happen, as do adoptions, etc. Also: I'd add a reverse types & 'ping-back' to the addRelation() function:
function addRelation($type, $person, $reverseType, $pingback = false) {
if (!isset($this->relations[$type])) {
$this->relations[$type] = array();
}
if (!in_array($person, $this->relations[$type], true)) {
$this->relations[$type][] = $person;
}
if (!$pingback) {
$person->addRelation($reverseType, $this, $type, true);
}
}
GEDCOM is an open specification for exchanging genealogical data between different genealogy software. A GEDCOM file is plain text (usually either ANSEL or ASCII) containing genealogical information about individuals, and meta data linking these records together. Most genealogy software supports importing from and/or exporting to GEDCOM format.
A major advantage of using GEDCOM, would be that you could use desktop programs like Aldfaer (Dutch only), Gramps or Legacy Family Tree as well as online tools like Geneanet to build or modify your family tree and compare it with the family trees of others.
Another major advantage of using the GEDCOM format, is that there are libraries in multiple programming language at your disposal to save and load your data. Examples of PHP libraries would be GEDCOM Import/Export-Filter, GenealogyGedcom or PHP GEDCOM.
Using PHP GEDCOM, reading and parsing a GEDCOM file would be as simple as this:
$parser = new \PhpGedcom\Parser();
$gedcom = $parser->parse('gedcom.ged');
A major disadvantage of using GEDCOM, is that GEDCOM's data format is built around the nuclear family, which means that the standard is limited in its support of non-traditional family structures, like same-sex partnerships, blended families or cohabitation. While it is possible to extend GEDCOM to support this type of relationships, inter-operability between different software is limited for such extensions.
Another major disadvantage of using GEDCOM, is that GEDCOM files are monolithic. If you have a dataset of thousands of people or your want to frequently change your data structure, you're likely to experience performance problems. Especially in those cases, it's best to store your data in a database instead. Still, that doesn't mean GEDCOM is useless. In those cases, you might want to consider using a database schema based on the GEDCOM format that allows you to import/export between your database and the GEDCOM format. For this, libraries exist as well. Oxy-Gen would be an example.
Alternatives to GEDCOM would be GenTech's data model or Gramps data model. While they aren't as commonly used as the GEDCOM standard, they might better suit your needs.
If you want to use the Gramps data model, you can use eg. the Gramps PHP exporter to export your data into an SQLite database. See also this source on how to design your database to be suitable for the Gramps data model.

Get Instance ID of an Object in PHP

I've learn a while ago on StackOverflow that we can get the "instance ID" of any resource, for instance:
var_dump(intval(curl_init())); // int(2)
var_dump(intval(finfo_open())); // int(3)
var_dump(intval(curl_init())); // int(4)
var_dump(intval(finfo_open())); // int(5)
var_dump(intval(curl_init())); // int(6)
I need something similar but applied to classes:
class foo {
public function __construct() {
ob_start();
var_dump($this); // object(foo)#INSTANCE_ID (0) { }
echo preg_replace('~.+#(\d+).+~s', '$1', ob_get_clean());
}
}
$foo = new foo(); // 1
$foo2 = new foo(); // 2
The above works but I was hoping for a faster solution or, at least, one that didn't involve output buffers. Please note that this won't necessarily be used within the constructor or even inside the class itself!
spl_object_hash() is not what I'm looking for because the two objects produce identical hashes
The question previously contained an incorrect example of spl_object_hash output; ensuring that both objects exist at the same time produces hashes which are subtly different:
var_dump(spl_object_hash($foo)); // 0000000079e5f3b60000000042b31773
var_dump(spl_object_hash($foo2)); // 0000000079e5f3b50000000042b31773
Casting to int like resources doesn't seem to work for objects:
Notice: Object of class foo could not be converted to int.
Is there a quick way to grab the same output without using object properties?
Besides var_dump(), I've discovered by trial and error that debug_zval_dump() also outputs the object instance, unfortunately it also needs output buffering since it doesn't return the result.
spl_object_hash() could help you out here. It
returns a unique identifier for the object
which is always the same for a given instance.
EDIT after OP comment:
You could implement such a behavior using a static class property, e.g:
class MyClass
{
private static $_initialized = false;
public function __construct()
{
if (!self::$_initialized) {
self::$_initialized = true;
// your run-only-once code
}
}
}
But actually this has nothing to with your original question.
Well, yes, with an extension.
Note that the handles used for objects that were, in the meantime, destroyed, can be reused.
Build with phpize && ./configure && make && make install
testext.h
#ifndef PHP_EXTTEST_H
# define PHP_EXTTEST_H
# ifdef HAVE_CONFIG_H
# include<config.h>
# endif
# include <php.h>
extern zend_module_entry testext_module_entry;
#define phpext_testext_ptr &testext_module_entry
#endif
testext.c
#include "testext.h"
PHP_FUNCTION(get_object_id)
{
zval *obj;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &obj)
== FAILURE) {
return;
}
RETURN_LONG(Z_OBJ_HANDLE_P(obj));
}
static zend_function_entry ext_functions[] = {
PHP_FE(get_object_id, NULL)
{NULL, NULL, NULL, 0, 0}
};
zend_module_entry testext_module_entry = {
STANDARD_MODULE_HEADER,
"testext",
ext_functions, /* Functions */
NULL, /* MINIT */
NULL, /* MSHUTDOWN */
NULL, /* RINIT */
NULL, /* RSHUTDOWN */
NULL, /* MINFO */
NO_VERSION_YET,
STANDARD_MODULE_PROPERTIES
};
ZEND_GET_MODULE(testext)
config.m4
PHP_ARG_ENABLE(testext,
[Whether to enable the "testext" extension],
[ enable-testext Enable "testext" extension support])
if test $PHP_EXTTEST != "no"; then
PHP_SUBST(EXTTEST_SHARED_LIBADD)
PHP_NEW_EXTENSION(testext, testext.c, $ext_shared)
fi
Test script
<?php
$a = new stdclass();
$b = new stdclass();
var_dump(get_object_id($a));
var_dump(get_object_id($b));
Output
int(1)
int(2)
Alix, your solution in the question was exactly what I needed, but actually breaks when there's an object in an object, returns the last # in the var_dump. I fixed this, made the regex faster, and put it in a nice little function.
/**
* Get global object ID
* From: http://stackoverflow.com/questions/2872366/get-instance-id-of-an-object-in-php
* By: Alix Axel, non-greedy fix by Nate Ferrero
*/
function get_object_id(&$obj) {
if(!is_object($obj))
return false;
ob_start();
var_dump($obj);// object(foo)#INSTANCE_ID (0) { }
preg_match('~^.+?#(\d+)~s', ob_get_clean(), $oid);
return $oid[1];
}
Have a look at spl_object_hash(). Usage example:
$id = spl_object_hash($object);
Note that you'll need PHP 5 >= 5.2.0 for that to work.
As long as you implement the base class all the classes you're going to need this from, you can do something like this:
class MyBase
{
protected static $instances = 0;
private $_instanceId = null;
public function getInstanceId()
{
return $this->_instanceId;
}
public function __construct()
{
$this->_instanceId = ++self::$instances;
}
}
class MyTest extends MyBase
{
public function Foo()
{
/* do something really nifty */
}
}
$a = new MyBase();
$b = new MyBase();
$c = new MyTest();
$d = new MyTest();
printf("%d (should be 1) \n", $a->getInstanceId());
printf("%d (should be 2) \n", $b->getInstanceId());
printf("%d (should be 3) \n", $c->getInstanceId());
printf("%d (should be 4) \n", $d->getInstanceId());
The output would be:
1 (should be 1)
2 (should be 2)
3 (should be 3)
4 (should be 4)
As of PHP 7.2 you can use spl_object_id
$id = spl_object_id($object);
$storage[$id] = $object;
What you're trying to do, is actually Aspect-Oriented Programming (AOP).
There are at least a couple of frameworks available for AOP in PHP at this point:
seasar (formerly PHPaspect) is a larger framework integrating with Eclipse - the screenshot shows you a little code snippet that answers your question, weaving some code around a particular new statement throughout a project.
php-aop is a lightweight framework for AOP.
typo3 has an AOP framework built in.
This may be overkill for your needs, but you may find that exploring the kind of thinking behind ideas like these will lead you down the rabbit hole, and teach you new ways to think about software development in general - AOP is a powerful concept, allowing you to program in terms of strategies and concerns, or "aspects".
Languages like PHP were designed to solve programming tasks - the concept of AOP was designed to solve a programmers' task. When normally you would need to think about how to ensure that a particular concern gets fulfilled every time in your code base, you can think of this as simply an "aspect" of how you're programming, implement it in those terms directly, and count on your concerns to be implemented every time.
It requires less discipline, and you can focus on solving the practical programming tasks rather than trying to architect your way through high-level structural code requirements.
I don't have the PECL runkit enabled to test this, but this may allow you to remove the constructor code from the class definition after the first time that an instance of the class has been created.
Whether you can remove the constructor from within the constructor would be an interesting experiment.
This is a bit late to the party but I didn't see this answer and just recently implemented something similar for a debugging class ( to handle circular references). As you guys may or may not know the normal printing functions such as var_export, have limited or no circular reference support.
As noted the spl_object_hash is unique per instance, the problem I had with it is that it is ugly. Not really suited to printing for my debugger as it's something like this 000000006ac56bae0000000044fda36f which can be hard to compare to say this 000000006ac56bae0000000044fda35f. So like the OP stated what I wanted was just a number of the instance ( I only really needed this on a per class basis ).
Therefor the simple solution for me was to do the following.
$class = get_class( $input );
$hash = spl_object_hash( $input );
if( !isset( $objInstances[ $class ] )){
$objInstances[ $class ] = array();
}
$output = 'object(%s) #%s (%s){%s}'; //class, instance, prop_count, props
if( false === ( $index = array_search($hash, $objInstances[ $class ] ) ) ){
$index = count($objInstances[ $class ]); //set init index for instance
$objInstances[ $class ][] = $hash;
// .... debugging code
$output = 'debugging result.', //sprintf
}else{
$output = sprintf( $output, $class, $index, 0, '#_CIRCULAR_REFRENCE_#');
}
Obviously the debugging code is way more complex, but the essential thing here is that by tracking the class and spl hash in $objInstances I can easily assign my own instance numbers outside of the class. This means I don't need some ugly hack ( that affects the class's code ) to get a reference number. Also, I don't need to display the "ugly" spl hash. Anyway my full code for this outputs something like this.
$obj = new TestObj();
$obj1 = new TestObj();
$obj->setProProp($obj1);
$obj1->setProProp($obj); //create a circular reference
object(TestObj) #0 (7){
["SOME_CONST":const] => string(10) 'some_const',
["SOMEOTHER_CONST":const] => string(16) 'some_other_const',
["SOME_STATIC":public static] => string(6) 'static',
["_PRO_STATIC":protected static] => string(10) 'pro_static',
["someProp":public] => string(8) 'someProp',
["_pro_prop":protected] => object(TestObj) #1 (7){
["SOME_CONST":const] => string(10) 'some_const',
["SOMEOTHER_CONST":const] => string(16) 'some_other_const',
["SOME_STATIC":public static] => string(6) 'static',
["_PRO_STATIC":protected static] => string(10) 'pro_static',
["someProp":public] => string(8) 'someProp',
["_pro_prop":protected] => object(TestObj) #0 (0){#_CIRCULAR_REFRENCE_#},
["_proProp":protected] => string(7) 'proProp'
},
["_proProp":protected] => string(7) 'proProp'
}
As you can see it's very easy to see where object(TestObj) #0 (0){#_CIRCULAR_REFRENCE_#} came from now. I wanted to keep this debugging code as close to the native var_dump
which outputs this.
object(TestObj)#7 (3) {
["someProp"]=> string(8) "someProp"
["_pro_prop":protected]=> object(TestObj)#10 (3) {
["someProp"]=> string(8) "someProp"
["_pro_prop":protected]=> *RECURSION*
["_proProp":protected]=> string(7) "proProp"
}
["_proProp":protected]=> string(7) "proProp"
}
The difference here is I needed the return as a string, not output to the browser. I also wanted to be able to show class constants, static properties, and private properties ( with flags to change what the debugger outputs, and the depth limit). And, I wanted a bit more information as to what the circular reference was instead of just *RECURSION* which doesn't tell me anything.
Hope it helps someone in the future.
Here is the full code for my Debug class, you can find this used about line #300
https://github.com/ArtisticPhoenix/Evo/blob/master/Evo/Debug.php
If you don't want to use output buffering... perhaps use var_export instead of var_dump?

What's the best way to implement user's preferences in this PHP app?

I have a smaller web app that republishes content from one social source to another. Users have, let's say 5 options for how to filter that content. Their prefs are stored in my user DB as 1 or 0 markers.
When I do my major "publish" action hourly, what's the best way to break up my code to implement these preferences? To make it more clear, my current implementation is something like this:
mysql_query(SELECT * FROM users);
foreach ($user as $row){
get_json_data($userID);
if ($pref1 == 1){
/code that enacts preference 1, adds results to array $filtereddata
}
if ($pre2 == 1 ){
/code that filters out preference 2, adds results to $filtereddata
{
postfinalarray($filtereddata);
}
Obviously this is mock code, but that's the general flow I've been using. Is there a better way to implement customizing a function with user's preferences? Should I design the function to accept these preferences as parameters? Will that save processing time or be more maintainable?
Sorry if this is too general, please ask questions so I can clarify.
Well of course there are many possibilities to improve this kind of code. Just imagine, if you would add another preference you would have to rewrite your whole code.
I always try to use the object oriented way so creating a user class always makes sense:
<?php
class User
{
private $_data;
public function __construct($userdata, $preferences)
{
$this->_data = $userdata;
}
public function getPreferencesData($preferences)
{
$result = array();
$prefs = $this->_data['preferences'];
foreach($preferences as $key => $value)
{
if($value == "1")
$result[] = $this->_data[$key];
}
return $result;
}
}
$mypreferences = array("name" => 1, "birthdate" => 0); // show e.g. name and birthdate
$mydata = array("name" => "Gaius Julius Caesar", "birthdate" => "July 13th -100");
$testuser = new User($mydata);
print_r($test->getPreferencesData($mypreferences));
?>
Then you can easily adapt to whatefer preferences the user has chosen without having to change your code.
From the limited info you've provided, your method seems fine.
I would do something slightly different probably. I would have a table of your 5 prefs (or would just hard code them if they're very unlikely to change). I would create a cross-reference table linking the prefs and users. Then you can do something like:
foreach($users as $user)
{
$filtereddata = array();
foreach($user->getPreferences() as $pref)
{
$filtereddata += $this->getFilteredData($user, $pref);
}
}
This is more overhead than what you're using, but more easily extensible if/when you add preferences/features.

Categories