Jump to content

Objects belong to two objects


Recommended Posts

I have an object which contains two properties which are array like objects extended from my Collections class and they are called xAxis and yAxis.

I also have another object which is "located" at the intersection of the x and y axis (i.e. the position in the container for xAxis and yAxis).

I can do something like $chart->xAxis->someMethod() as well as $chart->yAxis->someMethod(), but am struggling how to deal with these objects located at the intersection of the two.

Any recommendations on where I go from here?  On a related note, I don't think I am correctly implementing a collection class.  Any feedback would be appreciated.

Thank you

<?php

$chart=new Chart(new XAxis([new Node()]), new YAxis([new Node()]));

class Chart
{
    public $xAxis, $yAxis;
    public function __construct(XAxis $xAxis, AAxis $yAxis) {
        $this->xAxis=$xAxis;
        $this->yAxis=$yAxis;
    }
}
class XAxis extends Collection{}
class YAxis extends Collection{}
abstract class Collection implements \JsonSerializable, \ArrayAccess, \IteratorAggregate , CollectionInterface
{
    protected $container=[];
    private $originalCollection;

    public function __construct(array $nodes=[]) { //$nodes is an array of Node objects
        $this->container=$nodes;
        $this->originalCollection=array_merge(array(), $nodes);    //Arrays not passed by reference but the objects are!
    }

    public function jsonSerialize() {
        $arr=[];
        foreach($this->container as $node) $arr[]=$node;
        return $arr;
    }

    public function getIterator() {
        return new \ArrayIterator($this->container);
    }

    public function hasContent() {
        return !empty($this->container);
    }

    public function offsetSet($offset, $value) {
        if (is_null($offset)) {
            $this->container[] = $value;
        }
        elseif(is_int($offset)) {
            $this->container[$offset] = $value;
        }
        else throw new CollectionException('Offset must be an integer');
    }

    public function offsetExists($offset) {
        if(!is_int($offset)) throw new CollectionException('Offset must be an integer');
        return isset($this->container[$offset]);
        //return array_key_exists($offset, $this->container);
    }

    public function offsetUnset($offset) {
        if(!is_int($offset)) throw new CollectionException('Offset must be an integer');
        if(!isset($this->container[$offset])) throw new CollectionException('Offset does not exist');
        unset($this->container[$offset]);
        $this->container=array_values($this->container);
    }

    public function offsetGet($offset) {
        return isset($this->container[$offset]) ? $this->container[$offset] : null;
        //return $this->_data[$offset];
    }

    public function update($newValues) {
        if(count($this->container)!==count($newValues)) {
            throw new CollectionException('Collection counts do not match.');
        }
        foreach($this->container as $key=>$item) {
            $item->update($newValues[$key]);
        }
        return $this;
    }

    public function getChanges(){
        $this->container;
    }

    /**
    * Returns an array who's index is the position array given unique
    *
    * @param string $prop
    * @return array
    */
    public function getPositionChanges($prop){
        return array_udiff_assoc($this->container, $this->originalCollection,
            function ($stack, $originalStack) {
                return is_numeric($stack->$prop) && is_numeric($originalStack->$prop)
                ?$stack->$prop - $originalStack->$prop
                :strcmp($stack->$prop, $originalStack->$prop);
            }
        );
    }

    public function getAll(){
        $this->container;
    }

    public function move(int $initialPosition, int $finalPosition){
        if(!isset($this->container[$initialPosition]) || !isset($this->container[$finalPosition])) throw new CollectionException('Index does not exist');
        $node=$this->container[$initialPosition];
        unset($this->container[$initialPosition]);
        array_splice($this->container, $finalPosition, 0, $node);
        $this->container=array_values($this->container);
        //?? return $this->container;
    }

}

 

Link to comment
Share on other sites

That's not really how charts or grid are normally managed. There could very well be an Axis class, but it represents literally the axis. The line. Items positioned on the chart either have plain coordinates or use a Point object containing coordinates (I think a Point would be overkill), then those go into the Chart.

In your case I think I would have Chart contain a collection for items and a collection for other drawable objects like axes.

Link to comment
Share on other sites

40 minutes ago, requinix said:

That's not really how charts or grid are normally managed. There could very well be an Axis class, but it represents literally the axis. The line. Items positioned on the chart either have plain coordinates or use a Point object containing coordinates (I think a Point would be overkill), then those go into the Chart.

In your case I think I would have Chart contain a collection for items and a collection for other drawable objects like axes.

A bad choice of words on my part.

Say we had types of fruit and locations as well as quantities produced for each fruit/location intersect.  I think I will need to arbitrarily pick an axis to contain the data such as the following.   I guess this is kind of how multidimensional PHP arrays work as well, and will need to create some method which accepts two arguments for the position on both axis to access the intersecting object.  The reason I am going to this complication is that the values are not just fruit and location names and production quantity but some object with methods to allow the user to configure each.

I expect my collection class is a bunch of crap, but would still appreciate any comments and direction how a typical collection class should be built.

Thanks

{
    "categories":[
        {"name":"Apples"},
        {"name":"Oranges"},
        {"name":"Pears"},
        {"name":"Grapes"},
        {"name":"Bananas"}
    ],
    "series":[
        {"name":"California","data":[{"value":123},{"value":123},{"value":123},{"value":123},{"value":123}]},
        {"name":"Florida","data":[{"value":123},{"value":123},{"value":123},{"value":123},{"value":123}]},
        {"name":"Arizona","data":[{"value":123},{"value":123},{"value":123},{"value":123},{"value":123}]},
        {"name":"Texas","data":[{"value":123},{"value":123},{"value":123},{"value":123},{"value":123}]}
    ]
}

 

Link to comment
Share on other sites

I'm saying you put the information into each point that goes onto the chart. Not with the axes. You're using series so you could have the chart contain series and each series contains its points, or you could put all the points into the chart directly.

{ "series": [
	{ "name": "California", "points": [
		{ "x": "Apples", "y": 123 },
		{ "x": "Oranges", "y": 123 },
		{ "x": "Pears", "y": 123 },
		{ "x": "Grapes", "y": 123 },
		{ "x": "Bananas", "y": 123 }
	] }
] }

or on the chart itself

{ "points": [
	{ "series": "California", "x": "Apples", "y": 123 },
	{ "series": "California", "x": "Oranges", "y": 123 },
	{ "series": "California", "x": "Pears", "y": 123 },
	{ "series": "California", "x": "Grapes", "y": 123 },
	{ "series": "California", "x": "Bananas", "y": 123 }
] }

 

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.