Jump to content

NotionCommotion

Members
  • Content Count

    2,006
  • Joined

  • Last visited

  • Days Won

    9

NotionCommotion last won the day on July 2 2019

NotionCommotion had the most liked content!

Community Reputation

30 Good

About NotionCommotion

  • Rank
    Prolific Member

Contact Methods

  • Website URL
    http://

Profile Information

  • Gender
    Not Telling

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

  1. Are you using namespace? If so, you will need to use \PDO::FETCH_ASSOC instead of PDO::FETCH_ASSOC unless you have a PDO alias. Are you getting errors? Do you get any content or just with the stored procedure? Try a simple query such as SELECT 123 or select just from some table.
  2. I ended up mocking it up and didn't expect the following results. Creating the initial array uses 11MB, copying it uses very little, and changing it uses 529KB. I would have expected changing it would have used the same as creating it. And then when I reassign $bigArray with new values, it uses 11MB which I wasn't sure whether to expect or not and this was the basis of my original question. But then I don't reassign $bigArray but pass the array directly to the class, and it also uses 11MB which I definitely did not expect and thought that it would be saved only as a reference and use very little memory. I am using PHP7.4.1. What is going on? Thanks <?php error_reporting(E_ALL); ini_set('display_errors', 1); $settings=parse_ini_file(__DIR__.'/../../config.ini',true); $db=$settings['mysql']; $pdo=new \PDO("mysql:host={$db['host']};dbname={$db['dbname']};charset={$db['charset']}",$db['username'],$db['password'],array(\PDO::ATTR_EMULATE_PREPARES=>false,\PDO::MYSQL_ATTR_USE_BUFFERED_QUERY=>true,\PDO::ATTR_ERRMODE=>\PDO::ERRMODE_EXCEPTION,\PDO::ATTR_DEFAULT_FETCH_MODE=>\PDO::FETCH_ASSOC)); $stmt=$pdo->query('SELECT * FROM test'); function display($memory) { $s=''; foreach($memory as $i => $m) { $delta=$i>0 ?[$m[1]-$memory[$i-1][1], $m[2]-$memory[$i-1][2], $m[3]-$memory[$i-1][3], $m[4]-$memory[$i-1][4]] :[null, null, null, null]; $m=array_merge($m, $delta); $s.='<tr><td>'.implode('</td><td>', $m).'</td></tr>'; } echo "<table><tbody><tr><td>Test</td><td>Used</td><td>Peak</td><td>Peak Used</td><td>Peak Allocated</td><td>Used Change</td><td>Peak Change</td><td>Peak Used Change</td><td>Peak Allocated Change</td></tr>$s</tbody></table>"; } function logger($msg, $log=true) { global $memory; $m = [$msg, round(memory_get_usage()/1000),round( memory_get_peak_usage()/1000), round(memory_get_usage(true)/1000), round(memory_get_peak_usage(true)/1000)]; if($log) $memory[] = $m; return $m; } function addDelta($msg, $before, $after) { global $memory; $m = [$msg, $after[1]-$before[1], $after[2]-$before[2], $after[3]-$before[3], $after[4]-$before[4]]; $memory[]=$m; return $m; } function getData($stmt) { $data=[]; for ($i = 0; $i <= 3; $i++) { $stmt->execute(); $data = array_merge($data, $stmt->fetchAll()); } return $data; } class DataHolder { private $data; public function __construct(array $data) { $this->data=$data; //$this->data[]='bla'; <-- I believe this will force PHP to make a new copy of the array but I am not doing so } } $memory=[]; logger('initial'); $bigArray1=getData($stmt); logger('after creating first data set'); $bidArrayCopy=$bigArray1; logger('after copying first data set'); $bigArray1[]=123; logger('after modifying first data set'); $dataHolders=[]; $log1=logger(null, false); for ($i = 1; $i <= 5; $i++) { logger("Copy Loop $i - Before"); $stmt->execute(); $bigArray=getData($stmt); $dataHolders[] = new DataHolder($bigArray); logger("Copy Loop $i - After"); } $log2=logger(null, false); $deltaCopy = addDelta('delta copy', $log1, $log2); for ($i = 1; $i <= 5; $i++) { logger("Set Loop $i - Before"); $stmt->execute(); $dataHolders[] = new DataHolder(getData($stmt)); logger("Set Loop $i - After"); } $log3=logger(null, false); $deltaSet = addDelta('delta set', $log2, $log3); addDelta('delta copy set', $deltaCopy, $deltaSet); display($memory); | Test | Used | Peak | Peak Used | Peak Allocated | Used Change | Peak Change | Peak Used Change | Peak Allocated Change | |--------------------------------|--------|--------|-----------|----------------|-------------|-------------|------------------|-----------------------| | initial | 1345 | 1345 | 2097 | 2097 | | | | | | after creating first data set | 12631 | 13294 | 2097 | 2097 | 11286 | 11949 | 0 | 0 | | after copying first data set | 12631 | 13294 | 2097 | 2097 | 0 | 0 | 0 | 0 | | after modifying first data set | 13160 | 13294 | 2097 | 2097 | 529 | 0 | 0 | 0 | | Copy Loop 1 - Before | 13161 | 13294 | 2097 | 2097 | 1 | 0 | 0 | 0 | | Copy Loop 1 - After | 24447 | 25110 | 2097 | 2097 | 11286 | 11816 | 0 | 0 | | Copy Loop 2 - Before | 24447 | 25110 | 2097 | 2097 | 0 | 0 | 0 | 0 | | Copy Loop 2 - After | 35733 | 36396 | 2097 | 2097 | 11286 | 11286 | 0 | 0 | | Copy Loop 3 - Before | 35734 | 36396 | 2097 | 2097 | 1 | 0 | 0 | 0 | | Copy Loop 3 - After | 47020 | 47683 | 2097 | 2097 | 11286 | 11287 | 0 | 0 | | Copy Loop 4 - Before | 47020 | 47683 | 2097 | 2097 | 0 | 0 | 0 | 0 | | Copy Loop 4 - After | 58306 | 58969 | 2097 | 2097 | 11286 | 11286 | 0 | 0 | | Copy Loop 5 - Before | 58307 | 58969 | 2097 | 2097 | 1 | 0 | 0 | 0 | | Copy Loop 5 - After | 69592 | 70256 | 4194 | 4194 | 11285 | 11287 | 2097 | 2097 | | delta copy | 56433 | 56962 | 2097 | 2097 | -13159 | -13294 | -2097 | -2097 | | Set Loop 1 - Before | 69594 | 70256 | 4194 | 4194 | 13161 | 13294 | 2097 | 2097 | | Set Loop 1 - After | 80879 | 81543 | 16777 | 16777 | 11285 | 11287 | 12583 | 12583 | | Set Loop 2 - Before | 80881 | 81543 | 16777 | 16777 | 2 | 0 | 0 | 0 | | Set Loop 2 - After | 92166 | 92830 | 27263 | 27263 | 11285 | 11287 | 10486 | 10486 | | Set Loop 3 - Before | 92167 | 92830 | 27263 | 27263 | 1 | 0 | 0 | 0 | | Set Loop 3 - After | 103453 | 104116 | 39846 | 39846 | 11286 | 11286 | 12583 | 12583 | | Set Loop 4 - Before | 103453 | 104116 | 39846 | 39846 | 0 | 0 | 0 | 0 | | Set Loop 4 - After | 114739 | 115402 | 50332 | 50332 | 11286 | 11286 | 10486 | 10486 | | Set Loop 5 - Before | 114740 | 115402 | 50332 | 50332 | 1 | 0 | 0 | 0 | | Set Loop 5 - After | 126026 | 126689 | 60817 | 60817 | 11286 | 11287 | 10485 | 10485 | | delta set | 56433 | 56433 | 56623 | 56623 | -69593 | -70256 | -4194 | -4194 | | delta copy set | 0 | -529 | 54526 | 54526 | -56433 | -56962 | -2097 | -2097 |
  3. I understand older versions of PHP would actually make a copy, but that this is no longer the case and it is only copied when it is changed. When I fetch the first set of results, I obviously need to save the content in memory (just realized my typo and forgot the fetchAll). But then when I fetch the second and future data sets, I am reassigning the $bigArray variable to this new data set which "maybe" is effectively changing it. You know, it would be quicker to actually test this.
  4. I know I am not known for specific question, but do have one this time. gizmola's response makes me feel that the above will cause PHP to copy the original value. True? Guess I can prevent doing so with the following... $dataHolders[] = new DataHolder($stmt->execute([$id])); //or $bigArray[]=$stmt->execute([$id]); $dataHolders[] = new DataHolder(reset($bigArray));
  5. When will modern PHP copy an array by reference only instead of reassigning to memory? For instance, when I execute $bigArray=$stmt->execute([$id]), PHP utilizes memory to store the data. But then when I execute $dataHolders[] = new DataHolder($bigArray), I believe $bigArray is passed by reference and a new copy of $bigArray will not be stored in memory. If in DataHolder::__construct, I executed $data[]='bla', then it is my understanding that PHP would see that the array is being modified and will automatically make a copy, but I am not doing so and just state this to confirm my understanding. The part that I am uncertain about is not the first time data is retrieved but any additional times. When I execute the next $bigArray=$stmt->execute([$id]), will PHP need to first store in memory the array that DataHolder::data references, then release the memory associated with $bigArray, and then store in memory the new $bigArray? <?php class DataHolder { private $data; public function __construct(array $data) { $this->data=$data; //$this->data[]='bla'; <-- I believe this will force PHP to make a new copy of the array but I am not doing so } } $dataHolders=[]; foreach($ids as $id) { $bigArray=$stmt->execute([$id]); $dataHolders[] = new DataHolder($bigArray); }
  6. Thanks maxxd. If so, then definitely a valid consideration.
  7. Just looking for ways to limit cutting and pasting identical code and then making a change to one version and failing to update all the rest. You are likely correct that I am leaving out a key ingredient regarding interfaces and are still trying to better understand their place. I am mixed when it comes to __set and __get. When first learning about them, I used them exclusively, but then found (at least for me) that they often are more trouble than they are worth for when simple setters and getters can be used.
  8. Just for copy and past reasons. I am still undecided on whether I prefer inheritance or traits for this scenario. There is no reason why Classes A, B, and C shouldn't have access to the $id and $name property so a trait is better. But then I can just make $id and $name protected so it doesn't matter. But then again using inheritance implies some base functionality and better defines what is additional (i.e. Foo), so maybe inheritance is better. Or maybe it really doesn't matter and I should just be consistent...
  9. I expect they will not have some sort of reasonable default behavior. If not, then? The answer to the universe? World peace? I was thinking of adding some OtherStuffInterface::getValue(string $name) method but I don't think doing so is really right. Alternatively, I can create interfaces OtherTimeChartStuffInterface and OtherPieChartStuffInterface which extend OtherStuffInterface, but not sure if this really makes sense. I expect you have a viable answer but want me to think it through. If so, mind given another clue?
  10. For solely to reduce duplicated code and when injection isn't applicable, should one use inheritance or traits? <?php abstract class BaseClass { private $id, $name; public function __construct(int $id, string $name) { $this->id=$id; $this->name=$name; } public function getId():int { return $this->id; } public function getName():string { return $this->name; } } <?php class A extends BaseClass{} class B extends BaseClass{} class C extends BaseClass { private $foo; public function __construct(int $id, string $name, Foo $foo) { parent::__construct($id, $name); $this->foo=$foo; } public function getFoo():Foo { return $this->foo; } } <?php trait MyTrait { private $id, $name; public function __construct(int $id, string $name) { $this->id=$id; $this->name=$name; } public function getId():int { return $this->id; } public function getName():string { return $this->name; } } <?php class A { use MyTrait; } class B { use MyTrait; } class C { use MyTrait; private $foo; public function __construct(int $id, string $name, Foo $foo) { $this->id=$id; $this->name=$name; $this->foo=$foo; } public function getFoo():Foo { return $this->foo; } }
  11. Yes, key phrase is "so far". This seems to be a common occurrence for me. I go down some path and then later find I need some other data for a given implementation and need to go back and change my interfaces which is rather a pain. Are you suggesting some grab bag which anything extra can go in or something else? I don't think so since doing so wouldn't require the pie and time charts to work with their extra things. interface ChartInterface { public function addSeries(int $id, string $name, ?OtherStuffInterface $otherStuff); }
  12. Thank you. Well said and sunk home. Contravariance (and covariance) relaxes the interface precision, but solely for the class's customer application's benefit and not the class itself, and the given class actually has to fully implement the status quo and then do more. While I technically knew this was the intent, I wasn't really thinking this way. Am I on track? Agree, it is too abstract. Back to dealing with displaying real time and historical data in some sort of chart format and refactoring how data is retrieved in order to popular a given chart. Every chart has an ID (which is used to request the chart), name, title, etc as well as one or more series (let's focus on the series). Each series will have a name and other associated data as well as multiple data nodes where each data node has a value, name, etc. There are different types of charts which have different data requirements: Line Chart: The series has sequence of data nodes and all series for a given chart have the same number of data nodes. Categorical Chart: Uses an X/Y format where a common sequence of categories is associated with each series and all series for a given chart have the same number of data nodes. Pie Chart: Each series for a given chart can have different number of data nodes. Gauge Chart: Each series only has one data node. There are two basic ways values for the charts are generated: Each series has multiple data nodes where each's value is based on a given physical parameter current values or a given physical parameter aggregate values of historic data (mean, max, etc). Each series is only associated with a single parameter, but multiple data nodes are obtained by grouping the parameter on a given time interval. There are also different derivatives of these such as grouping based on a sample size which is applicable for a line chart, or on either a given time duration (seconds in a day, week, month, etc) or on a time unit (whole days, weeks, months, etc) which is applicable for the different chart types. The database schema utilizes a base chart table with one-to-one relations to a subtable for each chart type. Multiple charts are typically presented simultaneously, and I am querying the base table with left joins to subtables (better performance, but granted does not obey open-closed principle), and handling the aggregate values of historic data as well as the group by time requirements elsewhere with a different query. Each chart type class extends an abstract Chart class and each chart type series will extend an abstract ChartSeries class or maybe just implement an interface. So, I query the database, get a record which defines a given chart's type and associated meta data and create a chart object. I also get multiple records which define the various chart series and send this data to the applicable recently created chart object's addSeries() method, and similarly get additional records which define the various series data nodes. Each record from the query provides data for the chart, series, and data node, but I just skip creating a chart or series if it was created using a previous record. For a pie chart, I just get the chart ID, name, JSON options data, timezone, etc and pass it to a PieChart's constructor to create the chart object, then get just the series ID and name and call $series=$chart->addSeries(int $id, string $name), and then get the data node data such as ID, label, and data associated with the physical parameter and send it to $series->addDataNode(int $id, string $label, Parameter $parameter). But for a group by time chart, I also get time meta data such as the total chart's time duration and feed it to a TimeChart's constructor to create the chart object. Then for each series, I also get additional time meta data such time offset in the past and call $series=$chart::addSeries(int $id, string $name, TimeObject $timeOffset), and then the same as for a pie chart call $series->addDataNode(int $id, string $label, Parameter $parameter). Note that the database will only return a single data node record for these types of charts and I've considered not implementing TimeChart::addDataNode() and instead including this information in TimeChart::addSeries(), but I feel it is cleaner being consistent with the other chart types (agree?). So, for all chart types except time grouping charts, I have method addSeries(int $id, string $name), but for time grouping charts I need method addSeries(int $id, string $name, TimeObject $timeOffset). There are also some other minor differences between different chart types, but I feel if I get this right, the others will fall into line. Maybe I am still not thinking correctly and appreciate any advice you are willing to provide. Thanks
  13. I have an interface with method: public function foo(string $arg1, string $arg2); With PHP7.4, I can have a class relax the type without errors such as Dog::foo(string $arg1, $arg2) ($arg2 is not required to be a string) I incorrectly thought I could even relax the constraint more such as Dog::foo(string $arg1){} and not even pass $arg2 because extra arguments which exceed a method's placeholders are ignored without error but I received error: Declaration of Dog::foo(string $arg1) must be compatible with AnimalInterface::foo(string $arg1, string $arg2). Are my only options to include $arg2=null in the relaxed methods and label the methods something $dummy1, $dummy2..., or pass them in an array (which I don't wish to do)? Is passing extra parameters to the same method as I am doing considered bad practice, and if so what is considered the correct way? Thanks <?php declare(strict_types=1); ini_set('display_errors', '1'); echo "PHP Version: ".PHP_VERSION.PHP_EOL; // => PHP Version: 7.4.1 interface AnimalInterface { public function foo(string $arg1, string $arg2); } abstract class Animal implements AnimalInterface { protected string $name; public function __construct(string $name) { $this->name = $name; } protected function test($method, $arg1, $arg2) { echo $method.' '.$this->name.' '.gettype($arg1).' '.gettype($arg2).PHP_EOL; } } class Cat extends Animal { public function foo(string $arg1, string $arg2) { $this->test(__FUNCTION__, $arg1, $arg2); } public function bar(string $arg1, string $arg2) { $this->test(__FUNCTION__, $arg1, $arg2); } } class Dog extends Animal { //public function foo(string $arg1){} //generates an error public function foo(string $arg1, $arg2=null) { $this->test(__FUNCTION__, $arg1, $arg2); } public function bar(string $arg1) { $arg2=$arg2??null; $this->test(__FUNCTION__, $arg1, $arg2); } } $kitty = new Cat("Ricky"); $doggy = new Dog("Mavrick"); $kitty->foo('arg1', 'arg2'); $doggy->foo('arg1', [1,2,3]); //$kitty->bar('arg1', (int)222); //will error using strict mode only $doggy->bar('arg1', (int)222); $kitty->bar('arg1', 'arg2'); $doggy->bar('arg1', [1,2,3]);
  14. Yes only if you are including the constructor method in the "some method" group. The reason I think I should be doing so is my original statement "I have an application which receives multiple requests at once and it advantageous to process them as a group."
  15. Sure, the controller, however, I need to simplify the association between the request and response. I have two parts of the application which need to know the association and there are many requests which are processed in multiple groups and the process is complicated. I could use SplObjectStorage, however, doing so would require many updates which isn't perfect. My thought was create a response in one part of the application and save a reference to it, include that response in the request, process the requests and when each is complete, update each request's individual response. Another thought is to basically do the same but use class RequestResponsePair which holds the two.
×
×
  • 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.