Jump to content

NotionCommotion

Members
  • Posts

    2,446
  • Joined

  • Last visited

  • Days Won

    10

Everything posted by NotionCommotion

  1. Thanks dalesosp, I actually mean to change the title of this post from "Any good articles on interfaces?" to a real question, but hit the submit button and then couldn't change it. The title should have been something like "Should interfaces be applied to end class or extended classes". I have googled and likely have seen some if not all of these. My difficulty is I am not qualified to know which ones to believe. Do you recommend any of them, and if so, which ones? Thanks again!
  2. Your post showing both a domain name and port might have clarified my confusion. Would one just go to domain host, and have ws://example.com: point to the appropriate IP, and the connection port would be as specified on the client (8000 for your example) or 80 or 443 if not specified? Would it use 80 if the the HTML page used 80 or if the JavaScript file used 80? Is Ratchet a implementation of the websocket protocol? Does it use ReactPHP? I see it is on the http://reactphp.org/ website, but I couldn't find any reference to ReactPHP on http://socketo.me/. My interest in websockets was to provide webbrowser logging screen displaying communication between a non-websocket client and a non-websocket server. My thought was the non-websocket client would initiate communication to the server, and give the server something to identify itself. A websocket client could then connect to the server and provide the identifier. The server script could then send the data sent to and received from the non-websocket client to the websocket client. I am not sure if it is possible, but it might be nice for the server to listen to two different ports so it knows whether it is communicating with the non-websocket client or the websocket client. If a single server was used to interface to both clients, it would make transferring the information easy, but then requires building a websocket server myself with ReactPHP. Don’t know whether this makes any sense! But if it does, how difficult would it be to implement? Also, would you recommend creating my own websocket server or using one which has already implemented the websockets protocol? Thanks
  3. How can I access a ReactPHP sockets server? Not looking for client side assistance (I will need it be it is a question for another forum) but the server side. Don't even know where to start. I know the IP and port where the socket server is running. I saw a client side tutorial which showed creating the connection as websocket = new WebSocket("ws://echo.websocket.org/");. What happens in between? Thanks
  4. Hi Callum, Instead of attaching files, add your script in the post and use the script tags (the <> icon). Also, what are your specific questions?
  5. The following resets all $_SESSION indexes. This is probably not what you want, and should do $_SESSION['someIndex']=.... $_SESSION = mysqli_fetch_array ($r, MYSQLI_ASSOC); Then, when this happens, $_SESSION['email'] is not set because of the above line, and it exists. if (!isset($_SESSION['email'])) {
  6. Boring is good! How can the session variable be used to return the incremented ID so it may be inserted in the intended table? Or do you mean not using a trigger, but have PHP insert a record in _inc and returning that incremented ID to the PHP application, and having PHP insert this value in the intended table?
  7. It appears that my proposed solution in the original post might not be feasible as it results in the following error: ERROR 1235 (42000) at line 68: This version of MySQL doesn't yet support 'multiple triggers with the same action time and event for one table' It appears that I might need to utilize MyISAM to accomplish this. Make _inc a primary composite incremented table, insert a value, get the last value inserted, and then use this for the other table.
  8. All I was asking was whether my implementation of triggers was correct to meet my stated objectives. With the exception of Barand's first post (which unfortunately I don't wish to implement), all I got were opinions that my objectives were wrong. For my specific application, I believe my objectives are appropriate and I never asked for my objectives to be validated. I recognize that all advice received has been given freely and truly appreciate all you have all given whatever the format, but I do hope to implement this and hope someone can provide specific advice for the problem at hand. Thank you
  9. Still struggling a bit with interfaces. When I just started messing around with them, I started making an interface for all my end classes. But, then started thinking I am going about it wrong, and should start the interface much earlier and not duplicate the capabilities. For instance, all things exist but this hardly deserves an interface, all vehicles start, stop, turn, etc, so I should make an interface for vehicles, only a motorcycle can pop a wheelie so I should extend the interface, and dirtbikes don't do much more than normal motorcycles (other than being more fun!) so probably should extend it. Now I am thinking that I might not want an interface for a motorcycle, but I want an interface for something that can pop a wheelie. But isn't that a motorcycle? How should interfaces really be used for these classes? Also, does anyone know of any good tutorials or articles on interfaces? Thanks Thing->Vehicle->VehicleThatCarriesHumans->Motorcycle->DirtBike Thing->Vehicle->VehicleThatCarriesHumans->Automobile Thing->Vehicle->Drone->Phantom
  10. Well, that is sure reassuring and appreciated!
  11. Who? I said something about a composite key as I've been told by some smart SQL people that it is a good (beautiful) thing. I've since come to my senses, agree with your point of view, and want to use a plain old auto-incremented integer ID for my entire zoo. The ID am am talking about is not for the database, but for the user. Given that ID and their usersID (which they don't know, but they logged on so the system knows it), they can find a record which happens to have a plan old auto-incremented integer ID (which they they also will never know know as well). We all have a user ID on this site (barand: 3105, benanamen: 179806, jacques1: 167590, and me: 26806). There are also IDs to identify posts (303227 for this one). One could argue based on a risk analysis whether these shouldn't be actual primary keys which the database uses, but it doesn't matter for what I am asking. What if it was desired to instead of me having to refer to this post as #303227, I should refer to it as "NotionCommotion's post #1186"? Please assume that this is a UX requirement that management says needs to be implemented and that this second number should be a sequence and not a random value, and don't argue that these business rules shouldn't be implemented. Well, we can change the schema and use a composite primary key (26806-1186 for this record), but as I said, I don't wish to use composite keys. Instead I want the post table to be: posts -id (PK auto-incremented where no one sees its value) -users_id (FK) -my_own_public_id (unique index with users_id, will never be a FK to another table, and will be 1186 for this post) -date_added -content -whatever If I delete this post, and then add another one, I want my_own_public_id to be 1187, and not duplicate 1186 (please assume it the right thing for my particular application to delete a record instead of leaving it in the database and just flagging it as deleted). So, how do I determine the value of this secondary extra key which is provided for the UX and not database integrity?
  12. ??? I was under the impression that jaques1 scolding of insisting on pretty IDs was directed at me. Or maybe "intervention" in a good way
  13. Ha, ha, Yes, I remember those discussions (I was kind of hoping you didn't), and it is my time to eat crow. The MySQL purists often preach the virtues of composite keys, and while they sometimes save a JOIN, and might sometimes make some application work simpler, they in my opinion make the application work more complicated and less flexible, and are not worth it. So, anyone know how to implement this second incrementing key? I believe my originally proposed solution was going in the right direction, and would appreciate recommendations.
  14. InnoDB doesn't support incrementing composite keys.
  15. I already understand how super/subtype tables work. Thanks for the recommendation about MongoDB. The public_id is just an incrementing non-reusable series of numbers starting from 1 and going up for each users' dogs, cats, and hamsters. My only need is to figure out how to implement it. How about if I didn't care about cats or hamsters (notice how the cat got deleted, but not the dog!), just had one "dogs" table which had id, public_id, users_id, and some various other columns. How can I implement this incrementing column under this scenario? PS. Think of the public_id as the person's SSN. Yes, some will argue that it should be used as a natural primary key for the users table, but most would recommend using a surrogate and placing a unique constraint on SSNs.
  16. As addressed to banadamen's comment, different types of animals require different properties. That being said, I suppose it is irreverent as I need the same solution even if there was just one table. I am actually currently doing very similar to what you have shown. I have a single MyISAM table with columns id, users_id, and type all making up the primary key, and have it autoincrementing id. I insert a record, get the autoincrementing id value, and then use the application to use that id along with the users_id in he dogs, cats, hamsters table. I have two issues with this approach: MyISAM doesn't support referential integrity constraints so I really should be using triggers to enforce instead of the application. Composite PKs seem all good, but they really become a pain when you have several JOINs and every table needs to include the composite key. I would like opinions on this as I am still on the fence, but starting side against them. Not a big deal, but I need to store all the previous used public ids in this MyISAM table. Guess I can easily enough add a trigger to delete the old ones when a new one is added. Thanks
  17. Because different types of animals require different properties, however, I agree they also share some common properties and as such a supertype/subtype solution is appropriate. The "public_id" is provided to expose to the user, and is not joined to any other tables. Do you know how I can accomplish this?
  18. Am I doing this correct and if so, can it be improved? My desire is to have an incrementing key (public_id) individually for dogs, cats, and hamsters and individually for each user. For instance, user #1 can have dogs with public key 1, 2, and 3 as well as cats with public key 1, 2, and 3, and user #2 can dogs with public key 1, 2, and 3... Note that public keys should not be duplicated for a given type and user. For instance, if user #1's highest public ID for cats happens to be 3, he deletes that cat, and then adds a new cat, the new cat's public ID should be 4 and not 3. See the triggers I've added. I am hoping to use the following query to add a dog named Fido to user 123.: INSERT INTO dogs(users_id,name) VALUES(123,"Fido"); Thanks -- MySQL Script generated by MySQL Workbench -- 02/18/17 08:40:07 -- Model: New Model Version: 1.0 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0; SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0; SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='TRADITIONAL,ALLOW_INVALID_DATES'; -- ----------------------------------------------------- -- Schema mydb -- ----------------------------------------------------- CREATE SCHEMA IF NOT EXISTS `mydb` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci ; USE `mydb` ; -- ----------------------------------------------------- -- Table `mydb`.`users` -- ----------------------------------------------------- CREATE TABLE IF NOT EXISTS `mydb`.`users` ( `id` INT NOT NULL AUTO_INCREMENT, `name` VARCHAR(45) NOT NULL, `userSpecificStuff` VARCHAR(45) NULL, PRIMARY KEY (`id`)) ENGINE = InnoDB; -- ----------------------------------------------------- -- Table `mydb`.`_inc` -- ----------------------------------------------------- CREATE TABLE IF NOT EXISTS `mydb`.`_inc` ( `users_id` INT NOT NULL, `type` ENUM('dogs', 'cats', 'hamsters') NOT NULL, `public_id` INT NOT NULL, PRIMARY KEY (`users_id`, `type`), CONSTRAINT `fk__inc_users` FOREIGN KEY (`users_id`) REFERENCES `mydb`.`users` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION) ENGINE = InnoDB; -- ----------------------------------------------------- -- Table `mydb`.`dogs` -- ----------------------------------------------------- CREATE TABLE IF NOT EXISTS `mydb`.`dogs` ( `iddogs` INT NOT NULL AUTO_INCREMENT, `users_id` INT NOT NULL, `public_id` INT NOT NULL, `name` VARCHAR(45) NOT NULL, `dogSpecificStuff` VARCHAR(45) NULL, PRIMARY KEY (`iddogs`), INDEX `fk_dogs_users1_idx` (`users_id` ASC), UNIQUE INDEX `public_id_UNIQUE` (`public_id` ASC, `users_id` ASC), CONSTRAINT `fk_dogs_users1` FOREIGN KEY (`users_id`) REFERENCES `mydb`.`users` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION) ENGINE = InnoDB; -- ----------------------------------------------------- -- Table `mydb`.`cats` -- ----------------------------------------------------- CREATE TABLE IF NOT EXISTS `mydb`.`cats` ( `idcats` INT NOT NULL AUTO_INCREMENT, `users_id` INT NOT NULL, `public_id` INT NOT NULL, `name` VARCHAR(45) NOT NULL, `catSpecificStuff` VARCHAR(45) NULL, PRIMARY KEY (`idcats`), INDEX `fk_cats_users1_idx` (`users_id` ASC), UNIQUE INDEX `public_id_UNIQUE` (`public_id` ASC, `users_id` ASC), CONSTRAINT `fk_cats_users1` FOREIGN KEY (`users_id`) REFERENCES `mydb`.`users` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION) ENGINE = InnoDB; -- ----------------------------------------------------- -- Table `mydb`.`hamsters` -- ----------------------------------------------------- CREATE TABLE IF NOT EXISTS `mydb`.`hamsters` ( `idhamsters` INT NOT NULL AUTO_INCREMENT, `users_id` INT NOT NULL, `public_id` INT NOT NULL, `name` VARCHAR(45) NOT NULL, `hamsterSpecificStuff` VARCHAR(45) NULL, PRIMARY KEY (`idhamsters`), INDEX `fk_hamsters_users1_idx` (`users_id` ASC), UNIQUE INDEX `public_id_UNIQUE` (`public_id` ASC, `users_id` ASC), CONSTRAINT `fk_hamsters_users1` FOREIGN KEY (`users_id`) REFERENCES `mydb`.`users` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION) ENGINE = InnoDB; SET SQL_MODE=@OLD_SQL_MODE; SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS; SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS; USE `mydb`; DELIMITER $$ USE `mydb`$$ CREATE TRIGGER `dogs_BINS` BEFORE INSERT ON `dogs` FOR EACH ROW INSERT INTO _inc (users_id,type,public_id) VALUES (NEW.users_id, "dogs", 1) ON DUPLICATE KEY UPDATE public_id=public_id+1; SET NEW.public_id = ( SELECT public_id FROM _inc WHERE users_id=NEW.users_id AND type="dogs"; );$$ USE `mydb`$$ CREATE TRIGGER `cats_BINS` BEFORE INSERT ON `cats` FOR EACH ROW INSERT INTO _inc (users_id,type,public_id) VALUES (NEW.users_id, "cats", 1) ON DUPLICATE KEY UPDATE public_id=public_id+1; SET NEW.public_id = ( SELECT public_id FROM _inc WHERE users_id=NEW.users_id AND type="cats"; );$$ USE `mydb`$$ CREATE TRIGGER `hamsters_BINS` BEFORE INSERT ON `hamsters` FOR EACH ROW INSERT INTO _inc (users_id,type,public_id) VALUES (NEW.users_id, "hamsters", 1) ON DUPLICATE KEY UPDATE public_id=public_id+1; SET NEW.public_id = ( SELECT public_id FROM _inc WHERE users_id=NEW.users_id AND type="hamsters"; );$$ DELIMITER ;
  19. Thanks requinix, I guess unsetting $this doesn't make much sense, and I can do whatever necessary in the close() callback.
  20. Is it possible to close a connection and delete an object when within that object? For instance: <?php //.... $socket->on('connection', function (\React\Socket\ConnectionInterface $stream){ $client = new DuplexStreamInterface($stream); //.... }); //.... class LengthPrefixStream { public function __construct(DuplexStreamInterface $socket){ $this->socket = $socket; $this->socket->on('data', function($data){ $this->buffer .= $data; $this->parseBuffer(); }); } public function parseBuffer(){ //... if($badConnectionSoCloseSelf) { $this->socket->close(); unset($this); } //... } }
  21. requinix's sudo code was simpler than mine, but yours takes that cake! I would rather not. How important do you think this is? Interesting. Would invalid JSON be a condition to close the connection? What about X number of invalid JSON transmissions within a given timeframe? If so, do you have any rules of thumb?
  22. Started thinking about it, and can came to the same "then it's their fault" conclusion. Not saying it is everything, but this is one benefit of using deliminator over length prefixes.
  23. Thanks, My send() method look okay? As far parseBuffer(), I believe it performs the same task, however, your implementation is easier to follow. private function parseBuffer(){ //How can I validate that the received message length prefix matchs the length of the message so it doesn't get out of sync? do { if($this->messageLength) { if(strlen($this->buffer)>=$this->messageLength){ $message=substr($this->buffer, 0, $this->messageLength); if($this->type=='s') { $this->emit('data', [$message]); } else { //emit either an array or object $message = json_decode($message,$this->type=='a'); if (json_last_error() == JSON_ERROR_NONE){ $this->emit('data', [$message]); } } $this->buffer = substr($this->buffer, $this->messageLength); $this->messageLength=false; } else { break; } } else { if(strlen($this->buffer)>=4){ $this->messageLength=unpack('Vlen', substr($this->buffer,0,4))['len']; $this->buffer = substr($this->buffer, 4); } else { break; } } } while (true); }
  24. The following script seems to work, however, might have a couple of issues. First, LengthPrefixStream::send()seems to work, however, the receiving client doesn't respond correctly to it. See any issues with it? LengthPrefixStream::parseBuffer() works by making sure that $this->buffer always starts with a new packet/message (don't know the right word to use for this), and then knows that the first four bytes indicate the length of the message. See any issues? One concern I have is "if" it is sent content with more or less bytes than the length prefix indicates, $this->buffer might not always start with a new message, and I will lose the ability to find out the length prefix. Should this be a concern? Thanks <?php require 'vendor/autoload.php'; $port = isset($argv[1])?$argv[1]:1337; $host = isset($argv[2])?$argv[2]:'0.0.0.0'; $server=new Server($port,$host); $server->start(); class Server { private $port,$host,$client; public function __construct($port,$host) { $this->port=$port; $this->host=$host; } public function start() { $loop = React\EventLoop\Factory::create(); $socket = new React\Socket\Server($loop); $socket->on('connection', function (\React\Socket\ConnectionInterface $stream){ $client = new DataLogger\Server\LengthPrefixStream($stream,'o'); $this->client=$client; echo("New connection accepted.".PHP_EOL); $client->on('data', function($rsp) use ($client){ echo('received: '.json_encode($rsp).PHP_EOL); }); }); $loop->addPeriodicTimer(15, function() { $this->client->send(["method"=>"discovery.Start"]); }); $socket->listen($this->port,$this->host); echo("TCP Socket Server Started: {$this->host}:{$this->port} \r\n"); $loop->run(); } } <?php namespace DataLogger\Server; use Evenement\EventEmitterInterface; use Evenement\EventEmitterTrait; use React\Stream\DuplexStreamInterface; class LengthPrefixStream implements EventEmitterInterface { use EventEmitterTrait; private $socket, $buffer='', $messageLength=false, $type; //Type of data provided and returned. Can be s for string, a for array, or o for object. If array is associated, will be sent as an object. public function __construct(DuplexStreamInterface $socket, $type='s'){ if (!in_array($type,['s','a','o'])){ trigger_error("Invalid LengthPrefixStream type.", E_USER_ERROR); } $this->socket = $socket; $this->type=$type; $this->socket->on('data', function($data){ //echo("LengthPrefixStream on data: $data".PHP_EOL); $this->buffer .= $data; $this->parseBuffer(); }); } public function send($message){ //How should drain be implemented? if($this->type!='s') { $message = json_encode($message); } echo("send: $message".PHP_EOL); $lng=pack("V", strlen($message)); //Is this correct? $this->socket->write($lng.$message); } private function parseBuffer(){ //Question. What happens if something goes wrong and I lose $this->messageLength so I can't find the length prefix? if(!$this->messageLength) { //Save the first time data is received or if not enough stream was provided to determine the length $this->messageLength=$this->getLength($this->buffer); } while (strlen($this->buffer)>=($this->messageLength+4)){ $message = substr($this->buffer, 4, $this->messageLength); if($this->type=='s') { $this->emit('data', [$message]); } else { //emit either an array or object $message = json_decode($message,$this->type=='a'); if (json_last_error() == JSON_ERROR_NONE){ $this->emit('data', [$message]); } } $this->buffer = substr($this->buffer, $this->messageLength+4); $this->messageLength=strlen($this->buffer)>=4?$this->getLength($this->buffer):false; } } private function getLength($string){ // Appears length prefix is given as unsigned long (always 32 bit, little endian byte order) /* L unsigned long (always 32 bit, machine byte order) N unsigned long (always 32 bit, big endian byte order) V unsigned long (always 32 bit, little endian byte order) */ return unpack('Vlen', substr($string,0,4))['len']; } }
  25. Thanks kicken, Yeah, I've gone back and forth a couple times. The implications of the two approaches really didn't sink in until recently. I get the JSONStream class and appreciate your sharing it. I'll take a look at the Gearman code and ask questions if necessary. Night!
×
×
  • 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.