Jump to content

NotionCommotion

Members
  • Posts

    2,446
  • Joined

  • Last visited

  • Days Won

    10

Everything posted by NotionCommotion

  1. UGGG. What am I doing wrong? As seen, it only saves the last entry. Furthermore, if I run the file a second time, additional ^@^@^@^@ content is added (cat doesn't display it, but vi does and the content is obviously no longer valid json). Thanks! <?php $file='myjson.json'; addRecord($file,'hello1'); addRecord($file,'hello2'); addRecord($file,'hello3'); echo(file_get_contents($file)); function addRecord($file,$msg) { $fp = fopen($file, "r+"); if (flock($fp, LOCK_EX)) { $filesize=filesize($file); $json=$filesize?fread($fp, $filesize):'[]'; $arr=json_decode($json); $newRow=(object)['name'=>$msg]; $arr[]=$newRow; $new_json=json_encode($arr); ftruncate($fp, 0); fwrite($fp, $new_json); fflush($fp); flock($fp, LOCK_UN); } else{ exit('Could not lock the file!!!'); } fclose($fp); } Browser Output: [{"name":"hello3"}] [Michael@devserver public]$ vi myjson.json ^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@[{"name":"hello3"}]
  2. Still questioning why if flock is blocking, why does the PHP docs use the IF statement. This is what I now have. Without even using the getTestData function, for some reason I am not appending the new records, but writing over the buffer. function saveTestData($msg, $from=null, $to="null", $error=false) { $file='/var/www/test/buffer.json'; $fp = fopen($file, "r+"); if (flock($fp, LOCK_EX)) { $records=($filesize=filesize($file))?json_decode(fread($fp, $filesize),true):[]; $records[]=['from'=>$from,'to'=>$to, 'message'=>json_encode($msg),'error'=>$error]; ftruncate($fp, 0); fwrite($fp, json_encode($records)); fflush($fp); flock($fp, LOCK_UN); } else { echo "Couldn't get the lock!"; } fclose($fp); } function getTestData() { $file='/var/www/test/buffer.json'; $fp = fopen($file, "r+"); if (flock($fp, LOCK_EX)) { $records=($filesize=filesize($file))?fread($fp, $filesize):'[]'; ftruncate($fp, 0); fwrite($fp, ''); fflush($fp); flock($fp, LOCK_UN); } else { echo "Couldn't get the lock!"; } fclose($fp); return $records; }
  3. What confused me was this example from http://php.net/manual/en/function.flock.php. If flock is blocking, what is the purpose of the if statement? So, my writeSomething() will do the following? Open a file. Wait until it is available and instantly place a lock on it. Truncate all data to zero (i.e. delete all content). Add $txt to a buffer. Flush it (i.e. write the buffer to the file). Release the lock. Close the file. <?php function writeSomething($txt) { #Example #1 flock() example $fp = fopen("/tmp/lock.txt", "r+"); if (flock($fp, LOCK_EX)) { // acquire an exclusive lock ftruncate($fp, 0); // truncate file fwrite($fp, $txt); fflush($fp); // flush output before releasing the lock flock($fp, LOCK_UN); // release the lock } else { echo "Couldn't get the lock!"; } fclose($fp); } writeSomething('hello');
  4. Wait (forever if necessary) to be able to write to the file.
  5. Really, it isn't that complicated when you break it down. Define a bunch of variables to whatever you want. $hostdb = 'localhost'; $dbname = 'your_DB'; $username = 'root'; $password = ''; $table = 'YOURTABLE'; Okay, at first these can be a little intimidating. First one just sets up a connection to your database using the host name (likely localhost), and your database name and credentials. The second line tells it how to deal with errors, and you "can" do without, but probably should leave it in. $pdo = new PDO("mysql:host=$hostdb;dbname=$dbname", $username, $password); $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); Define a query, prepare it in MySQL PDO, and execute it. Note that I slightly changed your query by adding a WHERE query. The strange part is the silly :id at the end. This just tells PDO to replace it with the value in the array with the same index. Instead of :id, you can also use ?, and use a non-associated array. You can also use some crazy binding and whatnot, but don't worry about that for a while. Queries with one or two things to replace, use ?, otherwise, use the first method. Not only are your queries faster (but who cares), they are also much more secure as they are automatically escaped. $sql = "SELECT * FROM $table WHERE id=:id"; $stmt = $pdo->prepare($sql); $stmt->execute(['id']=>123); Get all your results. You could have used $stmt->fetch(), and it would have pulled only one (such as what you would have wanted to use if you used my example where I had the WHERE clause on the PK. $result = $stmt->fetchAll(); And print them. echo '<pre>'; print_r($result); echo '</pre>'; While there are many benefits of PDO, one of the greatest ones is it is so dang easy.
  6. Your missing quote at the end of title, but that isn't the only problem. Arrays are accessed as you did so, but objects use -> instead. $feed_to_array['entry'][0]->title;
  7. For testing only, I wish to use a file as a simple queue. Yea, I know I should be using a real queue, but I also wish to learn how to do it, and it is just for testing purposes only. Is this correct? Throughput will be low. Thanks Add to the buffer. public function saveTestData($json, $from, $to, $error=false) { $file='/var/www/test/buffer.json'; $fp = fopen($file, 'r+'); while (!flock($fp, LOCK_SH)) { usleep(1); } $existing = fread($fp, filesize($file)); $new=$existing?json_decode($existing,true):[]; $new[]=['from'=>$from,'to'=>$to, 'message'=>json_encode($json),'error'=>$error]; ftruncate($fp, 0); fwrite($fp, json_encode($new)); fflush($fp); flock($fp, LOCK_UN); fclose($fp); } Get the buffer data and delete it. function getTestData() { $file='/var/www/test/buffer.json'; $fp = fopen($file, 'r+'); while (!flock($fp, LOCK_SH)) { usleep(1); } $existing = fread($fp, filesize($file)); ftruncate($fp, 0); fwrite($fp, ''); fflush($fp); flock($fp, LOCK_UN); fclose($fp); return $existing; }
  8. Agree, I am hacking an array to mimic an object. There just easier to initiate for the type I needed. Better off using an object, and it works as well.
  9. Thanks requinix, An error emit was my original plan, but then I thought exceptions are much more standardized and the better approach. Is there any type of standardized error event pattern used or do I just make something up?
  10. Server:start() wraps LengthPrefixStream in a try/catch block. LengthPrefixStream throws an exception. Why can't I catch it? <?php namespace Base\Server; class Server { public function start() { $loop = \React\EventLoop\Factory::create(); // Or \React\EventLoop\StreamSelectLoop()? $socket = new \React\Socket\Server($loop); $socket->on('connection', function (\React\Socket\ConnectionInterface $stream) { try { $client = new LengthPrefixStream($stream); $client->on('data', function($data) use ($client){ //.... }); } catch(LengthPrefixStreamException $e) { $this->app->logger->logExceptionError($e); } catch(Exception $e) { $this->app->logger->logExceptionError($e); } }); $socket->listen($this->host['port'],$this->host['url']); $loop->run(); } } <?php namespace Base\Server; class LengthPrefixStreamException extends \Exception {} <?php namespace Base\Server; use Evenement\EventEmitterInterface; use Evenement\EventEmitterTrait; use React\Stream\DuplexStreamInterface; class LengthPrefixStream implements EventEmitterInterface { use EventEmitterTrait; private $socket=false, $buffer='', $parseJson; //0=>no, 1=>yes and return object, 2=>yes and return array public function __construct(DuplexStreamInterface $socket, $parseJson=1){ $this->parseJson = $parseJson; $this->socket = $socket; $this->socket->on('data', function($data){ $this->buffer .= $data; $this->parseBuffer(); }); } public function send($msg){ //Still need to implement drain if($this->isConnected()) { if($this->parseJson) { $msg=json_encode($msg); } $this->socket->write(pack("V", strlen($msg)).$msg); return true; } else { return false; } } private function parseBuffer(){ do { $checkAgain = false; $bufferLength = strlen($this->buffer); $length = unpack('Vlen', substr($this->buffer, 0, 4))['len']; if($bufferLength >= $length + 4){ $msg=substr($this->buffer, 4, $length).'bogus JSON'; if($this->parseJson) { $msg=json_decode($msg,$this->parseJson-1); if (json_last_error() != JSON_ERROR_NONE){ throw new LengthPrefixStreamException('Invalid JSON provided: '.substr($this->buffer, 4, $length)); } } $this->emit('data', [$msg]); $this->buffer = substr($this->buffer, $length+4); $checkAgain = strlen($this->buffer)>=4; } } while ($checkAgain); } public function isConnected() { return $this->socket?true:false; } public function close() { $this->socket->close(); } }
  11. How does that relate to the warning Indirect modification of overloaded element of SplObjectStorage has no effect warning? When storing an array, is it caused by PHP internally hashing the array and turning it into a string and storing that hash? Where is this documented? Is it more typical to use an object since they are passed by reference? $s->attach($o,(object)['a'=>111,'b'=>222]); $s[$o1]->b=555;
  12. Really? The only way? Why? <?php $s = new SplObjectStorage(); $o = new StdClass; $s->attach($o,['a'=>111,'b'=>222]); $bla=$s[$o]; $bla['b']=555; $s[$o]=$bla;
  13. How do I set the value of an element in an array stored in SplObjectStorage? As seen, I receive a Indirect modification of overloaded element of SplObjectStorage has no effect warning. Thanks <?php $s = new SplObjectStorage(); $o1 = new StdClass; $s->attach($o1,123); echo('$s[$o1]='); var_dump($s[$o1]); echo('$s[$o1]=321;'."\n"); $s[$o1]=321; echo('$s[$o1]='); var_dump($s[$o1]); $o2 = new StdClass; $s->attach($o2,['a'=>111,'b'=>222]); echo('$s[$o2]='); var_dump($s[$o2]); echo('s[$o2][a]='); var_dump($s[$o2]['a']); echo('$s[$o2][a]=333;'."\n"); $s[$o2]['a']=333; var_dump($s[$o2]['a']); $s[$o1]=int(123) $s[$o1]=321; $s[$o1]=int(321) $s[$o2]=array(2) { ["a"]=> int(111) ["b"]=> int(222) } s[$o2][a]=int(111) $s[$o2][a]=333; <br /> <b>Notice</b>: Indirect modification of overloaded element of SplObjectStorage has no effect in <b>/var/www/public/spl.php</b> on line <b>27</b><br /> int(111)
  14. Actually, what I will do is put the json scope in the class, but through an exception upon invalid json.
  15. Almost... Yours worked! Maybe I put the on method in the constructor like you did. Or maybe I just go back to putting this json functionality in the class like you did, and pass back some message if json isn't valid.
  16. Or maybe I should be wrapping it not in a method, but another class? The send() method seems okay, but not the on() method. The reason I tried to get away from having the json scope in the LengthPrefixStream class is I wish to log json errors, and didn't want to pass a logger into a generic class. Guess I will need to do the same if I use this approach... $client = new wrapClient(new \DataLogger\Server\LengthPrefixStream($stream)); class wrapClient { public function __construct($client){ $this->client = $client; } public function send($msg) { $this->client->send(json_encode($msg)); } public function on($msg) { $o = json_decode($msg); if (json_last_error() != JSON_ERROR_NONE){ $rsp='ERROR: Invalid JSON provided'; } return o; } }
  17. I have a class for streaming text. My question has nothing to do with this particular, but how to modify an object. Originally, I had functionality to deal JSON, but decided to remove that functionality as I felt it didn't belong there. The class now looks like the following: <?php namespace Server; use Evenement\EventEmitterInterface; use Evenement\EventEmitterTrait; use React\Stream\DuplexStreamInterface; class LengthPrefixStream implements EventEmitterInterface { use EventEmitterTrait; private $socket=false, $buffer=''; public function __construct(DuplexStreamInterface $socket){ $this->socket = $socket; $this->socket->on('data', function($data){ $this->buffer .= $data; $this->parseBuffer(); }); } public function send($message){ //Still need to implement drain if($this->isConnected()) { $this->socket->write(pack("V", strlen($message)).$message); return true; } else { return false; } } private function parseBuffer(){ do { $checkAgain = false; $bufferLength = strlen($this->buffer); $length = unpack('Vlen', substr($this->buffer, 0, 4))['len']; if($bufferLength >= $length + 4){ $this->emit('data', [substr($this->buffer, 4, $length)]); $this->buffer = substr($this->buffer, $length+4); $checkAgain = strlen($this->buffer)>=4; } } while ($checkAgain); } public function isConnected() { return $this->socket?true:false; } public function close() { $this->socket->close(); } } I use it something like this: protected function sendCommand($text) { $data = false; $loop = new \React\EventLoop\StreamSelectLoop(); $socket = new \React\SocketClient\TimeoutConnector(new \React\SocketClient\TcpConnector($loop), 15, $loop); $socket->create($this->host['url'], $this->host['port'])->then(function($stream) use (&$data, $loop, $text){ $client = new \DataLogger\Server\LengthPrefixStream($stream); $client->on('data', function($data) use (&$data, $loop, $stream){ //Passed by reference $data will be set. Maybe need to use a separate variable? $stream->close(); $loop->stop(); }); $client->send($text); }); $loop->run(); return $data; //False on failure } But now I wish to send and return variables other than text, and will need to convert them to JSON. I still don't wish to put this functionality in the class. Furthermore, I use this class more than one place, so don't wish to duplicate the JSON conversion and checking that it is valid JSON each time. I am thinking I might be able to wrap the object in another method. //$client = new \DataLogger\Server\LengthPrefixStream($stream); $client = $this->wrapClient(new \DataLogger\Server\LengthPrefixStream($stream)); protected function wrapClient($client) { /* Turn messages sent into JSON and verify that it is valid. Turn responses received into JSON and verify that it is valid. */ } But I am kind of at a lose where to go next. Any suggestions?
  18. At the very beginning of your script, add the following three lines. If you are using sessions or setting headers, you need to be careful not to send content to the page (i.e. echo something), but for your script you are not doing so, so no worries. You can use var_dump() instead of print_r() to get a little more information, but I often find print_r() easier to read. Spend some time looking at the results. $_GET and $_POST are all yours, but for the $_SERVER output, use http://php.net/manual/en/reserved.variables.server.php to understand what they mean. If you are using sessions, cookies, etc, use the same approach as shown below to display "what you have". <?php echo('$_SERVER:<pre>'.print_r($_SERVER,1).'</pre>'); echo('$_GET:<pre>'.print_r($_GET,1).'</pre>'); echo('$_POST:<pre>'.print_r($_POST,1).'</pre>'); /************************************************************************/ /* PHP Simple PasswordProtect v1.0 */ /* =========================== */
  19. You indicated earlier that I might first have one class which implements some fundamental tasks: class GDImageManipulator extends Manipulator implements ImageManipulator { } But might later wish to create a new separate implementation that does things differently but still accomplishes the same fundamental task class ImageMagickImageManipulator extends Manipulator implements ImageManipulator { } Note that unlike the example you showed, I am extending both from Manipulator. EDIT. just made class Manipulator abstract. Does doing so change the decision where to apply interfaces? Where should I apply the interfaces? For instance... abstract class Manipulator implements Manipulator { } interface Manipulator { } interface ImageManipulator { } or... abstract class Manipulator { } interface ImageManipulator extends Manipulator { } interface Manipulator { } or something else? Thanks!
  20. I am messing around a little with c++. I found that php functions which I take for granted such as json_encode() do not exist in c++. Is it possible to look at php source code and see how they did it? If so, where should I start? Thanks
  21. This is what I ended up doing, and it works great. My original post was close (or maybe the same?), but I accidentally didn't delete the old trigger when adding new ones, thus the error message. -- MySQL Script generated by MySQL Workbench -- 02/21/17 21:26:39 -- 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 -- ----------------------------------------------------- DROP SCHEMA IF EXISTS `mydb` ; CREATE SCHEMA IF NOT EXISTS `mydb` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci ; USE `mydb` ; -- ----------------------------------------------------- -- Table `mydb`.`users` -- ----------------------------------------------------- DROP TABLE IF EXISTS `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` -- ----------------------------------------------------- DROP TABLE IF EXISTS `mydb`.`_inc` ; CREATE TABLE IF NOT EXISTS `mydb`.`_inc` ( `type` CHAR( NOT NULL, `users_id` INT NOT NULL, `public_id` INT NOT NULL DEFAULT 0, PRIMARY KEY (`type`, `users_id`), INDEX `fk__inc_users_idx` (`users_id` ASC), 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` -- ----------------------------------------------------- DROP TABLE IF EXISTS `mydb`.`dogs` ; CREATE TABLE IF NOT EXISTS `mydb`.`dogs` ( `id` INT NOT NULL AUTO_INCREMENT, `users_id` INT NOT NULL, `public_id` INT NOT NULL DEFAULT 0, `name` VARCHAR(45) NOT NULL, `dogSpecificStuff` VARCHAR(45) NULL, PRIMARY KEY (`id`), INDEX `fk_dogs_users1_idx` (`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; 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`$$ DROP TRIGGER IF EXISTS `mydb`.`dogs_BINS` $$ USE `mydb`$$ CREATE TRIGGER `dogs_BINS` BEFORE INSERT ON `dogs` FOR EACH ROW begin INSERT INTO _inc (type, users_id, public_id) values ("dogs",NEW.users_id,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"); end$$ DELIMITER ;
  22. Somebody, get a rope...
  23. Yeah, I know I am often guilty of this and probably alone, but it actually helps me. But what is the real benefit of some interface of some niche final class which is and will only be that class? Wouldn't one want to define the interface early so others may extend it as they feel fit. Oh, I think I understand. It is not about extending but setting the spec what one might want to implement in the future... Isn't "ImageManipulator" a noun? That was my point about what can perform a wheelie. It must be a motorcycle, but then I am defining a noun. Makes sense.
  24. I didn't think I can have two services bound to the same port. If on the same machine which runs an Apache/Nginx/etc HTTP server and the ReactPHP socket server, wouldn't they be be bound to the same port and conflict? Ah, perfect! Just something like the following and use $_SERVER to determine the port? $socket->listen(1337,'0.0.0.0'); $socket->listen(1234,'0.0.0.0'); $loop->run(); While a goal is always to learn, will definitely go with some pre-written stuff (ReactPHP) for now (looking at your own Websocket server script, I can tell you definitely spent some time!). The thought of me implementing the websocket’s protocol on top of a ReactPHP server is a little daunting, however, probably a good learning experience. If a single server, I think dealing with routing data to the appropriate client shouldn’t be that difficult. If I have both a plain socket server and a Ratchet/etc websocket server, would the two servers be different requiring me to do something such as implement a socket client in the websocket server which sends the data to the sockets server, or can I just call some method such as $this->socket->sendSomethingUsingRatchet($someData); which would directly allow it to be sent to the websocket client?
×
×
  • 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.