Jump to content


  • Content Count

  • Joined

  • Last visited

  • Days Won


NotionCommotion last won the day on July 2

NotionCommotion had the most liked content!

Community Reputation

30 Good

About NotionCommotion

  • Rank
    Prolific Member

Contact Methods

  • Website URL

Profile Information

  • Gender
    Not Telling

Recent Profile Visitors

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

  1. Sounds pretty reasonable to me. If you want, you can add JS hoover preview.
  2. Unfortunately, I am the cause of the problem, but I am getting it under control. Trying to improve my skills regarding entities and modelling and have been making some changes along the way. Before automating the process, I would make some changes to the XML file, regenerate the entities, and it was time consuming to identified what was changed. Using annotations in the PHP file wouldn't result in these issues, but I think doing so brings other baggage. Below is what I ended up adding to my "create_entities.php" file which I run from the command line. /** * Returns an array of each method script. * * @param string $script * @param array $methods. Sequential * * @param array (associate array where keys are method names and value method script * */ function extractMethods(string $script, array $methods):array { $methods = getMethods($script, $methods); $script = explode(PHP_EOL, $script); foreach ($methods as $methodName=>$lns) { $methods[$methodName]= implode(PHP_EOL, array_slice($script, $lns[0], $lns[1])); } return $methods; } /** * Removes or replaces a given function. * * @param array $methods. If an element is associative, replaces with the vvalue, else removes * * @return string (script) */ function replaceFunction(string $script, array $methods):string { $methodNames=[]; foreach($methods as $key=>$name){ $methodNames[]=is_int($key)?$name:$key; } echo("Removing or replacing methods ".implode(', ', $methodNames).PHP_EOL); $methodNames = getMethods($script, $methodNames); //$columns = array_column($methodNames, 0); //array_multisort($columns, SORT_DESC, $methodNames); uasort($methodNames, function($a, $b) {return $b[0] <=> $a[0];}); //$script = preg_split("/\r\n|\n|\r/", $script); $script = explode(PHP_EOL, $script); foreach ($methodNames as $methodName=>$lns) { array_splice($script, $lns[0]-1, $lns[1]+1, $methods[$methodName]??null); } return implode(PHP_EOL, $script); } /** * Returns the line number and length of methods. * * @param string $script * @param array $methods. Sequential * * @param array (associate array where keys are method names and value is start line number and number of lines * */ function getMethods(string $script, array $methods):array { $tokens = token_get_all($script); if(count($tokens)!==count(token_get_all($script, TOKEN_PARSE))) exit('Investigate TOKEN_PARSE'); $count=count($tokens); $eof=$count - array_search('}',array_reverse($tokens)); $output=[]; foreach ($tokens as $index=>$token) { if (is_array($token) && $token[0]===T_FUNCTION) { //346 for ($nameIndex = $index+1; $nameIndex <= $count; $nameIndex++) { if (is_array($tokens[$nameIndex]) && $tokens[$nameIndex][0]===T_STRING) { //319 if(in_array($tokens[$nameIndex][1], $methods)) { for ($lastIndex = $nameIndex+1; $lastIndex <= $count; $lastIndex++) { if($lastIndex===$eof || (is_array($tokens[$lastIndex]) && $tokens[$lastIndex][0]===T_DOC_COMMENT)) { //378 for ($endIndex = $lastIndex-1; $endIndex > 0; $endIndex--) { if (is_array($tokens[$endIndex])) { break; } } for ($startIndex = $index-1; $startIndex > 0; $startIndex--) { if (is_array($tokens[$startIndex]) && $tokens[$startIndex][0]===T_DOC_COMMENT) { //378 $output[$tokens[$nameIndex][1]]=[$tokens[$startIndex][2], $tokens[$endIndex][2]-$tokens[$startIndex][2]]; break(3); } } exit('Initial comment not found'); } } } break; exit('Next comment or closing tag not found'); } } } } if($error = array_diff($methods, array_keys($output))){ exit(implode(', ', $error).' not found.'); } return $output; }
  3. I agree they shouldn't be but they are and thus the desire to automate.
  4. For right or wrong, I've been using XML to define my Doctrine entities. When the XML changes, my entities need to change. I've automated the process with a simple PHP script which allows me to swap some text to modify one of the auto-generated methods, add methods, etc. Kind of clunky but it works well enough. Now, I recently had the need to remove a given method in its entirety from a given class. I "could" just add the entire string which represents the method name, earlier comments, and script for the method to my parsing script to my parsing script and remove it, but would like to be a little more concise. For instance, say I have $script as follows: $script = <<<'EOT' class SomeEntityClass { //... more stuff above public function getSomething() { return $this->something; } /** * Get foos. * * @return \Doctrine\Common\Collections\Collection */ public function getFoos() { return $this->foos; } /** * Get somethingElse. * */ //... more stuff below } EOT; How would you recommend creating the function: removeFunction($script, 'getFoos') which would remove the given function along with its comments from the $script string and result with? $script = <<<'EOT' class SomeEntityClass { //... more stuff above public function getSomething() { return $this->something; } /** * Get somethingElse. * */ //... more stuff below } EOT; Assuming regex is the way to go, I was thinking of something like the following, but could use some help with the regex expression. function removeFunction($script, $method) { $method="public function $method("; //regex to remove script with which starts after pattern "{\n" OR "**/", contains $method, and is located before pattern "\n{" OR "\n /**" return $script; } Thanks
  5. I think I am somewhat doing as you do. I happen to be using Doctrine, but the approach is applicable without using it. At a minimum, abstract_thing_table will have PK column ID and string column discriminator. There is a schema config file that then maps this discriminator value to a specific class. For one or two rare cases, I have a table just with these two columns. While I think it is a little odd, a good part is if accessing the DB directly without Doctrine, I can save a JOIN. For most, however, I moved any common columns in the three InjectedThing tables to abstract_thing_table.
  6. I wish to create and store in a DB three objects which are created using injection; $myAObject=new BaseEntity(new InjectedThingA()); $myBObject=new BaseEntity(new InjectedThingB()); $myCObject=new BaseEntity(new InjectedThingC()); BaseEntity is defined by SQL table base_entity and my three injected objects InjectedThingA, InjectedThingB, and InjectedThingC are each defined by SQL tables injected_thing_a, injected_thing_b, injected_thing_c, respectively. Each of these injected tables has autoincrement column id plus whatever other columns, and base_entity includes a column injected_thing_id. But this won't work since this ID is not unique across InjectedThings and also poor since there is no foreign key, so instead I do the following. InjectedThingA extends AbstractInjectedThing InjectedThingB extends AbstractInjectedThing InjectedThingC extends AbstractInjectedThing Then I add an autoincrement id column to AbstractedInjectedThing and place a one-to-one constraint from column id in InjectedThingA, InjectedThingB, and InjectedThingC to column id in AbstractedInjectedThing. So, I still need to use inheritance, right? I don't think that this type of inheritance brings the baggage which MyInheritedEntity extends BaseEntity does and I am okay with it, but just want to make sure I am doing this right. Thanks
  7. A HTTP request is made to the server, Slim creates a Request and Response object, content in the Request is sent to another server using cURL via Guzzle, Guzzle returns its own Response, and content from Guzzle's response must be returned by the original Slim response. Would you recommend white-listing or black-listing response headers, and which specific headers? Similarly, would you recommend white-listing or black-listing the request headers sent via cURL, and which specific headers? Thanks <?php use Psr\Http\Message\ResponseInterface as Response; use GuzzleHttp\Psr7\Response as CurlResponse; class ApiResponder { public function delete(Response $httpResponse, CurlResponse $curlResponse) { return $this->proxy($httpResponse, $curlResponse); } //other public methods... private function proxy(Response $httpResponse, CurlResponse $curlResponse) { foreach($this->getResponseHeaders($curlResponse) as $name=>$value) { $httpResponse=$httpResponse->withHeader($name, $value); } return $httpResponse->withBody($curlResponse->getBody())->withStatus($curlResponse->getStatusCode()); } private function getResponseHeaders(Response $httpResponse):array { //Blacklist headers which should be returned to original client. TBD whether I should whitelist headers instead. $blacklist=['Date'=>null, 'Server'=>null, 'X-Powered-By'=>null, 'Access-Control-Allow-Origin'=>null, 'Access-Control-Allow-Methods'=>null, 'Access-Control-Allow-Headers'=>null, 'Set-Cookie'=>null]; return array_diff_key($curlResponse->getHeaders(), $blacklist); } /** * This method doesn't really exist in this class, but is just included to show which headers I am forwarding in the cURL request. */ private function getRequestHeaders($clientRequest):array { $whitelist=['connection'=>null,'accept'=>null,'accept-encoding'=>null,'accept-language'=>null,'content-type'=>null,'content-length'=>null]; return array_intersect_key($clientRequest->getHeaders(), $whitelist); } }
  8. Sounds like a good idea. These two interdependent collections have brought complication and it would be nice to have it encapsulated elsewhere. Do you envision this NodeCollection object as being an entity with two collection properties? Or maybe it is just a collection of series, but it has a getCategories() method which iterates over the series and creates an array of categories? I was implementing this __clone() method for a pie chart, and accidentally forgot to replace the chart's series with the new collection of clones, and was surprised that it worked. I then commented out doing so for the bar chart I previously showed, and it too worked without errors. While it works, I would still like to understand why it works. I also included my chart setter for series and category is the same. Any ideas? public function __clone() { parent::__clone(); $s = new \SplObjectStorage(); $seriesArray = new ArrayCollection(); foreach($this->series as $serie) { $serieClone = clone $serie; $serieClone->setChart($this); $nodesArray = new ArrayCollection(); foreach($serieClone->getNodes() as $node) { $nodeClone = clone $node; $nodeClone->setSerie($serieClone); $s[$node]=$nodeClone; $nodesArray->add($nodeClone); } $seriesArray->add($serieClone); } //$this->series=$seriesArray; $categoriesArray = new ArrayCollection(); foreach($this->categories as $category) { $categoryClone = clone $category; $categoryClone->setChart($this); $nodesArray = new ArrayCollection(); foreach($categoryClone->getNodes() as $node) { $nodeClone = $s[$node]; $nodeClone->setCategory($categoryClone); $nodesArray->add($nodeClone); } $categoriesArray->add($categoryClone); } //$this->categories=$categoriesArray; } <?php class CategoryChartSerie { public function setChart(CategoryChart $chart) { $chart->addSeries($this); $this->chart = $chart; return $this; } //... }
  9. The following works as desired. Thank you for keeping me from chasing unicorns. This what you had in mind? One thing I might rather do different is instead of cloning the nodes in the chart entity, clone them in the chart's serie entity and set the newly cloned notes in the category entity. The problem, however, is using SplObjectStorage in the chart as I have done, the category does not have access to these newly cloned nodes. Should I abandon trying to do so? public function __clone() { parent::__clone(); $s = new \SplObjectStorage(); $seriesArray = new ArrayCollection(); foreach($this->series as $serie) { $serieClone = clone $serie; $serieClone->setChart($this); $nodesArray = new ArrayCollection(); foreach($serieClone->getNodes() as $node) { $nodeClone = clone $node; $nodeClone->setSerie($serieClone); $s[$node]=$nodeClone; $nodesArray->add($nodeClone); } $seriesArray->add($serieClone); } $this->series=$seriesArray; $categoriesArray = new ArrayCollection(); foreach($this->categories as $category) { $categoryClone = clone $category; $categoryClone->setChart($this); $nodesArray = new ArrayCollection(); foreach($categoryClone->getNodes() as $node) { $nodeClone = $s[$node]; $nodeClone->setCategory($categoryClone); $nodesArray->add($nodeClone); } $categoriesArray->add($categoryClone); } $this->categories=$categoriesArray; } When setting the parent entity which belongs in a collection, I am also adding to the collection as shown, and do the same for the CategoryChartSerie's and CategoryChartCategory's. Is doing so good practice? Is it best to set the reciprocating properties always in the child entity as I have done or instead do it in the parent entity? <?php class CategoryChartNode { private $serie; private $category; private $point; public function setSerie(CategoryChartSerie $serie) { $serie->addNode($this); $this->serie = $serie; return $this; } //... } When cloning, I often see the following check before cloning. Recommended? public function __clone() { if ($this->id) { $this->id=null; } } Lastly, you stated that the nodes must be cloned. While I do not disagree, is the reason this is necessary that Doctrine must be internally using the node's hash to keep track of them? Thanks again for your help.
  10. Thanks, Was thinking I might need to go down that path but wasn't sure and was resisting doing so. Now I know so upward and onward!
  11. Yes, probably. What do you mean by a "(deep)" clone? This is for a BarChart. The parent object Chart as well as the Serie and Category objects use __clone() to set their PK to NULL. Where I am having problems is with the Node objects which are in a collection in both Serie and Category. I can clone each node in a series, but then I still have old nodes in the collection and I can't just clone those nodes in the collection because they need to be the same instances as in the series. Same is true if I do the categories first and then the series. So, instead I tried to replace the series and categories in each node with the newly cloned series and categories, but that doesn't change the node entities so no good. Any advise? Thank yuo public function __clone() { if ($this->getId()) { parent::__clone(); $seriesArray = new ArrayCollection(); foreach($this->series as $serie) { $serieClone = clone $serie; //$serieClone->setChart($this); //$nodesArray = new ArrayCollection(); foreach($serieClone->getNodes() as $node) { //$nodeClone = clone $node; //$nodesArray->add($nodeClone); $node->replaceSerie($serieClone); } $seriesArray->add($serieClone); } $this->series=$seriesArray; $categoriesArray = new ArrayCollection(); foreach($this->categories as $category) { $categoryClone = clone $category; //$categoryClone->setChart($this); //$nodesArray = new ArrayCollection(); foreach($categoryClone->getNodes() as $node) { //$nodeClone = clone $node; //$nodesArray->add($nodeClone); $node->replaceCategory($categoryClone); } $categoriesArray->add($categoryClone); } $this->categories=$categoriesArray; } }
  12. I don't know how Google's login API works, but couldn't you just add the following logic to the entry point to your app? <?php if(empty($_SESSION['auth'])) { $email=$_POST['email']; //or whatever //query DB. If email doesn't exist, exit. If email exists, set $_SESSION['auth'] }
  13. I am using PHP and Doctrine to store and manipulate Highchart objects such as the following: { "chart": { "type": "bar" }, "xAxis": { "categories": ["Africa", "America", "Asia", "Europe", "Oceania"] } }, "series": [{ "name": "Year 1800", "data": [107, 31, 635, 203, 2] }, { "name": "Year 1900", "data": [133, 156, 947, 408, 6] }, { "name": "Year 2000", "data": [814, 841, 3714, 727, 31] }, { "name": "Year 2016", "data": [1216, 1001, 4436, 738, 40] }] } My DB schema is: BarChart -id (PK) -name (string) BarChartSerie -id (PK) -barChartId (FK) -name (string) -position (int) BarChartCategory -id (PK) -barChartId (FK) -name (string) -position (int) BarChartNode -barChartSerie (FK) -barChartCategory (FK) -value (decimal) The chart entity has a collection of serie and category, and the serie and category entities both contain a reference to the shared node. I wish to clone the chart entity and thus use __clone() to set the chart, category, and serie entity's' PK to NULL, however, am running into issues as the node entity still has the original entitiy's PKs. I think maybe I should be creating the entities differently. Any suggestions how these objects should be created? Maybe instead have my series contain a collection of nodes and have each of these nodes contain a reference to the applicable category? Thanks
  14. There is some things you need to understand first. Your PHP server does not magically know $_GET['name'] . It doesn't even save it. Every time your browser accessed the page, it is actually given this data to the server. $_POST is similar. Go back to your browser, and open the console (F12 for most browsers) and look for a network tab and look what your browser is sending and receiving from the server. For chrome, sending is Form Data at the bottom of the Headers tab, and receiving is the Response tab. Now, look at the content sent and retrieved on your wizard request, and you will see that your browser is not sending a value for name. Therefore, it has no idea what it is. $_SESSION['name'] is storage. Every time your browser accesses the server, it sends a secret cookie which points to the storage. So you "could" in your normal page where $_GET['name'] is being sent copy this value to a session, and then latter in your wizard script retrieve it, but this is most likely not the intended way to do so. Just don't try to save the session in your wizard script because obviously it doesn't have the $_GET['name'].
  15. I am working on a REST application which is intended to be used with various CMS’s (Drupal, WordPress, etc). Each CMS installation passes a unique GUID in the header to identify the organization so that the organization's individual data is utilized. I’ve since realized I need some basic way to identify the individual user for at least two reasons: The API provides a help desk where individual users can ask questions and get responses (not real time). There is some need for user access/privileges (I suppose this could be CMS side if necessary). Instead of inputting users both into the API as well as the CMS, the organization should be responsible for entry only through the CMS. They will add users as appropriate for the given CMS and then another page on the CMS will list all the CMS users and provide a way to set whether they are authorized to access the API as well as their access level. The remaining of this post is kind of what I am thinking, but I am open to change. When the CMS gives a user access to the API for the first time, a cURL request is made to the API and a unique key is returned and the CMS will save it as being associated with the given user. Note sure if this should be an incrementing number on a per organization basis or another GUID, and if a GUID whether it should be passed along with the organization’s GUID or replace it. Also, not positive, but thinking that user data (name, email, etc) should not be given to the API as it might be difficult to keep them synchronized. If a user’s access level is changed on the CMS or their access is removed, the user’s GUID is passed to the API and the work is done on the API. If the user is removed, they are not deleted from the API’s database but just tagged as deleted. Before performing step 1, the CMS should first perform a query requesting all users who are tagged as deleted and is responsible to determine whether a new user should be added or an existing user should be reinstated. Alternatively, I can make the API responsible for doing so, but then it would need to have stored various data to identify whether the user was previously instated which might result in the synchronization issue I described in step 1. Any comments, potential pitfalls, or recommendations would be appreciated.
  • 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.