{"id":7049,"date":"2023-02-27T19:30:40","date_gmt":"2023-02-27T18:30:40","guid":{"rendered":"http:\/\/blog.bart.sk\/en\/?p=7049"},"modified":"2023-03-10T08:31:38","modified_gmt":"2023-03-10T07:31:38","slug":"create-properly-use-generators-php","status":"publish","type":"post","link":"https:\/\/blog.bart.sk\/en\/create-properly-use-generators-php\/","title":{"rendered":"How to Create and Properly Use Generators in PHP"},"content":{"rendered":"<p><b>Generators are very useful features in PHP that allow you to generate and return large amounts of data based on requirements or conditions without taking up too much memory. I feel that despite their practicality, they aren&#8217;t very popular among PHP developers. That&#8217;s why I&#8217;ve outlined how to create and use them in this blog. I hope this article will help the programming community understand PHP generators and motivate them to use them more often.<\/b><\/p>\n<h2><b>First, something about arrays and iterators<\/b><\/h2>\n<p><span style=\"font-weight: 400;\">Each program uses an <\/span><b>array<\/b><span style=\"font-weight: 400;\"> \u2013 the simplest list of values. We can fill it, reduce it and go through it, &#8220;iterate&#8221; it using <\/span><b>foreach<\/b><span style=\"font-weight: 400;\">. The entire array exists in memory, and the larger the array, the more memory it takes up.\u00a0<\/span><\/p>\n<p><span style=\"font-weight: 400;\">The <\/span><b>array <\/b><span style=\"font-weight: 400;\">is not the only one that can be iterated through <\/span><b>foreach.<\/b><span style=\"font-weight: 400;\"> In PHP, there&#8217;s an <\/span><b>Iterator<\/b><span style=\"font-weight: 400;\"> interface that we can use to iterate through <\/span><b>foreach <\/b><span style=\"font-weight: 400;\">as well<\/span><b>.<\/b><span style=\"font-weight: 400;\"> In addition, we can also incorporate some logic into iterations.\u00a0<\/span><\/p>\n<p><span style=\"font-weight: 400;\">For example, if we wanted to send the contents of files in a certain folder somewhere, when using an <\/span><b>array<\/b><span style=\"font-weight: 400;\">, we would load the list of files into the array and then, via <\/span><b>foreach<\/b><span style=\"font-weight: 400;\">, reload and send them again. The code looks like this:<\/span><\/p>\n<table>\n<tbody>\n<tr>\n<td>\n<pre>&lt;?php\r\n$dir = '\/path\/to\/dir\/';\r\n$listFiles = scandir($dir);\r\nforeach ($listFiles as $fileName) {\r\n\u00a0\u00a0\u00a0$file = $dir . $file;\r\n\u00a0\u00a0\u00a0if (is_file(#file)) {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0$fileContent = file_get_contents($dir . $file);\r\n\u00a0 \u00a0 \u00a0 \u00a0sendFileSomewhere($fileContent);\r\n\u00a0\u00a0\u00a0}\u00a0\u00a0\u00a0\r\n}<\/pre>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><span style=\"font-weight: 400;\">When using the <\/span><b>Iterator<\/b><span style=\"font-weight: 400;\"> interface, the code is a bit simpler:<\/span><\/p>\n<table>\n<tbody>\n<tr>\n<td>\n<pre>&lt;?php\r\n $dir = '\/path\/to\/dir\/';\r\n $directoryIterator = new DirectoryIterator($dir);\r\nforeach ($directoryIterator as $fileInfo) {\r\n\u00a0 \u00a0if ($fileInfo-&gt;isFile()) {\r\n\u00a0 \u00a0 \u00a0 \u00a0$fileContent = file_get_contents($fileInfo-&gt;getRealPath());\r\n\u00a0 \u00a0 \u00a0 \u00a0sendFileSomewhere($fileContent);\r\n\u00a0 \u00a0} \u00a0\u00a0\r\n}<\/pre>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h2><b>How to create generators in PHP?<\/b><\/h2>\n<p><span style=\"font-weight: 400;\">Iterators are used in PHP generators. These are functions that allow you to return a series of values from another function without having to create an entire array of values in memory. Unlike common functions that return values using <\/span><b>return<\/b><span style=\"font-weight: 400;\">, generators use the keyword <\/span><b>yield<\/b><span style=\"font-weight: 400;\">.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">We can create a generator simply by using the <\/span><b>function<\/b><span style=\"font-weight: 400;\"> clause and the <\/span><b>yield<\/b><span style=\"font-weight: 400;\"> keyword mentioned above. A simple example of a generator that returns several values:<\/span><\/p>\n<table>\n<tbody>\n<tr>\n<td>\n<pre>&lt;?php\r\n\r\n function generator() {\r\n\u00a0 yield \"hodnota 1\";\r\n\u00a0 yield \"hodnota 2\";\r\n\u00a0 yield \"hodnota 3\";\r\n}<\/pre>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><span style=\"font-weight: 400;\">This generator, when called, creates and returns three different values. In this case, they are &#8220;value 1&#8221;, &#8220;value 2&#8221; and &#8220;value 3&#8221;. Each value is returned using the keyword <\/span><b>yield<\/b><span style=\"font-weight: 400;\">. We can use this generator in the <\/span><b>foreach<\/b><span style=\"font-weight: 400;\"> cycle to get each of the values it generates:<\/span><\/p>\n<table>\n<tbody>\n<tr>\n<td>\n<pre>&lt;?php\r\n  foreach (generator() as $value) {\r\n  echo $value . \"&lt;br&gt;\";\r\n}<\/pre>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><span style=\"font-weight: 400;\">This code writes &#8220;value 1&#8221;, &#8220;value 2&#8221; and &#8220;value 3&#8221; on the screen.<\/span><\/p>\n<p><b>However, generators in PHP aren&#8217;t limited to generating fixed values. We may also use them to generate values based on conditions or requirements.\u00a0<\/b><\/p>\n<p><span style=\"font-weight: 400;\">Example of a generator that returns random values between 1 and 10:<\/span><\/p>\n<table>\n<tbody>\n<tr>\n<td>\n<pre>&lt;?php\r\n function random_numbers() {\r\n \u00a0while (true) {\r\n \u00a0 \u00a0 \u00a0yield rand(1, 10);\r\n \u00a0 }\r\n }<\/pre>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><span style=\"font-weight: 400;\">This generator will return random numbers between 1 and 10 until it&#8217;s finished. Therefore, when calling the generator, we&#8217;ll receive various random numbers.<\/span><\/p>\n<h3><b>Nested generators from PHP 7<\/b><\/h3>\n<p><span style=\"font-weight: 400;\">Since PHP 7, the <\/span><b>yield from<\/b><span style=\"font-weight: 400;\"> upgrade is also available, allowing for an additional level of generator nesting. Simply put, it allows us to use nested generators and simplifies the work with multiple iterators.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">An example of how we can use <\/span><b>yield from<\/b><span style=\"font-weight: 400;\"> to create a nested generator:<\/span><\/p>\n<table>\n<tbody>\n<tr>\n<td>\n<pre>&lt;?php\r\n function myGenerator() {\r\n\u00a0\u00a0\u00a0\u00a0yield 'foo';\r\n\u00a0\u00a0\u00a0\u00a0yield 'bar';\r\n}\r\n function myNestedGenerator() {\r\n\u00a0\u00a0\u00a0\u00a0yield 'hello';\r\n\u00a0\u00a0\u00a0\u00a0yield from myGenerator();\r\n\u00a0\u00a0\u00a0\u00a0yield 'world';\r\n}\r\n foreach (myNestedGenerator() as $value) {\r\n\u00a0\u00a0\u00a0\u00a0echo \"$value \";\r\n}<\/pre>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><span style=\"font-weight: 400;\">In this example, we&#8217;ve defined two generators<\/span><b>: myGenerator()<\/b><span style=\"font-weight: 400;\"> and <\/span><b>myNestedGenerator().<\/b><span style=\"font-weight: 400;\"> The <\/span><b>myNestedGenerator()<\/b><span style=\"font-weight: 400;\"> uses <\/span><b>yield from myGenerator()<\/b><span style=\"font-weight: 400;\"> to return elements from the <\/span><b>myGenerator()<\/b><span style=\"font-weight: 400;\"> nested generator along with other elements. Using <\/span><b>yield from<\/b><span style=\"font-weight: 400;\"> allows us to simplify the code and unify the output from multiple generators.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Using <\/span><b>yield from<\/b><span style=\"font-weight: 400;\"> can also be useful for processing recursive data structures or for processing tree structures where we need to navigate multiple levels.\u00a0<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Thus the use of <\/span><b>yield from<\/b><span style=\"font-weight: 400;\"> allows us to work with multiple generators within a single generator, thus simplifying and streamlining our code.<\/span><\/p>\n<h3><b>Obtaining a return value<\/b><\/h3>\n<p><span style=\"font-weight: 400;\">The <\/span><b>getReturn()<\/b><span style=\"font-weight: 400;\"> method is used to retrieve a value that was returned from the generator when the generator ends. This value is usually returned using the return in the generator.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Using this method allows us to get the return value from the generator without having to iterate through all its elements. This property can be useful when we want to get the return value of the generator, but we aren&#8217;t interested in the output sequence of the elements.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">An example of how we can use <\/span><b>getReturn()<\/b><span style=\"font-weight: 400;\"> to get the return value from the generator:<\/span><\/p>\n<table>\n<tbody>\n<tr>\n<td>\n<pre>&lt;?php\r\nfunction myGenerator() {\r\n\u00a0\u00a0\u00a0\u00a0yield 'foo';\r\n\u00a0\u00a0\u00a0\u00a0yield 'bar';\r\n\u00a0\u00a0\u00a0\u00a0return 'baz';\r\n}\r\n$gen = myGenerator();\r\nforeach ($gen as $value) {\r\n\u00a0\u00a0\u00a0\u00a0echo \"$value \";\r\n}\r\necho $gen-&gt;getReturn();<\/pre>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><span style=\"font-weight: 400;\">In this example, we&#8217;ve defined a <\/span><b>myGenerator() <\/b><span style=\"font-weight: 400;\">that returns three elements, &#8220;foo&#8221;, &#8220;bar&#8221; and &#8220;baz&#8221; using yield and return. Then we created an instance of the generator and used foreach to iterate through the elements. Finally, we used the <\/span><b>getReturn()<\/b><span style=\"font-weight: 400;\"> method to get the &#8220;baz&#8221; value that was returned from the generator.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">The <\/span><b>getReturn()<\/b><span style=\"font-weight: 400;\"> method should be called only after the iteration through the generator has ended, otherwise it may cause unexpected behavior.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Using this method allows us to get the return value from the generator without having to iterate through all its elements.\u00a0<\/span><\/p>\n<h2><b>How to use generators in PHP<\/b><\/h2>\n<p><span style=\"font-weight: 400;\">Generators in PHP can be used in a variety of ways. As we&#8217;ve already mentioned, we can use the <\/span><b>foreach<\/b><span style=\"font-weight: 400;\"> cycle to go through the individual values that the generator returns. However, we can also use the <\/span><b>yield<\/b><span style=\"font-weight: 400;\"> keyword within the function that calls the generator to generate values based on requirements or conditions.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">An example of a function that calls a generator based on the number of generated values:<\/span><\/p>\n<table>\n<tbody>\n<tr>\n<td>\n<pre>&lt;?php\r\nfunction generate_numbers($count) {\r\n\u00a0\u00a0$generator = random_numbers();\r\n\u00a0\u00a0for ($i = 0; $i &lt; $count; $i++) {\r\n\u00a0\u00a0\u00a0\u00a0yield $generator-&gt;current();\r\n\u00a0\u00a0\u00a0\u00a0$generator-&gt;next();\r\n\u00a0\u00a0}\r\n}<\/pre>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><span style=\"font-weight: 400;\">This function creates a new generator using the <\/span><b>random_numbers()<\/b><span style=\"font-weight: 400;\"> function. Subsequently, using the for cycle, it calls the generator as many times as required and returns each value that the generator returns. After each generator call, we call the <\/span><b>next()<\/b><span style=\"font-weight: 400;\"> function, which moves the internal indicator position of the generator to the next value.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">The generator can also be used to generate large amounts of data. For example, if we wanted to generate a million random numbers between 1 and 10, we could do it this way:<\/span><\/p>\n<table>\n<tbody>\n<tr>\n<td>\n<pre>&lt;?php\r\nfunction generate_numbers($count) {\r\n\u00a0\u00a0$generator = random_numbers();\r\n\u00a0\u00a0for ($i = 0; $i &lt; $count; $i++) {\r\n\u00a0\u00a0\u00a0\u00a0yield $generator-&gt;current();\r\n\u00a0\u00a0\u00a0\u00a0$generator-&gt;next();\r\n\u00a0\u00a0}\r\n}\r\nforeach (generate_numbers(1000000) as $number) {\r\n\u00a0\u00a0echo $number . \"&lt;br&gt;\";\r\n}<\/pre>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><span style=\"font-weight: 400;\">This code generates a million random numbers between 1 and 10 and writes them on the screen. <\/span><b>Interestingly, this code uses only a small amount of memory. If we used an array that contains a million random numbers instead of a generator, the memory requirement would be much greater, because we would need to allocate space for the entire array at once.<\/b><\/p>\n<p><span style=\"font-weight: 400;\">Thanks to generators in PHP, we can easily work with files and efficiently load large files into memory. We can create a generator that runs a file by rows and generates each row individually, thereby minimizing memory demands.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">For example, we can create a generator that runs a file by a row and returns each row as a string:<\/span><\/p>\n<table>\n<tbody>\n<tr>\n<td>\n<pre>&lt;?php\r\nfunction readLines($filename) {\r\n\u00a0\u00a0\u00a0\u00a0$file = fopen($filename, 'r');\r\n\u00a0\u00a0\u00a0\u00a0while (!feof($file)) {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0yield fgets($file);\r\n\u00a0\u00a0\u00a0\u00a0}\r\n\u00a0\u00a0\u00a0\u00a0fclose($file);\r\n}<\/pre>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><span style=\"font-weight: 400;\">In this example, we created a generator that loads a file and runs through it by rows using the <\/span><b>fgets()<\/b><span style=\"font-weight: 400;\"> function. It returns each row as a string using <\/span><b>yield<\/b><span style=\"font-weight: 400;\">. This approach allows us to load large files and work with them simply and efficiently.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">You can also use the generator to write data to a file. For example, we can create a generator that accepts an array of values and writes them to a file one by one:<\/span><\/p>\n<table>\n<tbody>\n<tr>\n<td>\n<pre>&lt;?php\r\nfunction writeData($filename, $data) {\r\n\u00a0\u00a0\u00a0\u00a0$file = fopen($filename, 'w');\r\n\u00a0\u00a0\u00a0\u00a0foreach ($data as $value) {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0fwrite($file, $value . \"\\n\");\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0yield;\r\n\u00a0\u00a0\u00a0\u00a0}\r\n\u00a0\u00a0\u00a0\u00a0fclose($file);\r\n}<\/pre>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><span style=\"font-weight: 400;\">In this example, we created a generator that accepts an array of <\/span><b>$data<\/b><span style=\"font-weight: 400;\"> values and writes them into a file using the <\/span><b>fwrite()<\/b><span style=\"font-weight: 400;\"> function. Finish each entry in the file with <\/span><b>yield<\/b><span style=\"font-weight: 400;\">. This approach allows us to write large amounts of data to the file gradually and efficiently.<\/span><\/p>\n<p><b>Therefore, the use of generators allows us to easily work with files and minimize memory requirements, which is very useful when working with large files.<\/b><\/p>\n<p><span style=\"font-weight: 400;\">Using iterators in PHP, we can browse and process data in parts, saving memory resources and increasing the efficiency of our code. <\/span><b>The use of iterators in combination with generators can be very useful for processing large files or datasets.<\/b><\/p>\n<p><span style=\"font-weight: 400;\">One way to create an iterator using a generator is to create a generator that returns individual elements of a dataset, and then define the class of iterator that will iterate and process those elements.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">An example of how to create an iterator using a generator:<\/span><\/p>\n<table>\n<tbody>\n<tr>\n<td>\n<pre>&lt;?php\r\nclass MyIterator implements Iterator {\r\n\u00a0\u00a0\u00a0\u00a0private $data;\r\n\u00a0\u00a0\u00a0\u00a0public function __construct($data) {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0$this-&gt;data = $data;\r\n\u00a0\u00a0\u00a0\u00a0}\r\n\u00a0\u00a0\u00a0\u00a0public function rewind() {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0reset($this-&gt;data);\r\n\u00a0\u00a0\u00a0\u00a0}\r\n\u00a0\u00a0\u00a0\u00a0public function current() {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return current($this-&gt;data);\r\n\u00a0\u00a0\u00a0\u00a0}\r\n\u00a0\u00a0\u00a0\u00a0public function key() {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return key($this-&gt;data);\r\n\u00a0\u00a0\u00a0\u00a0}\r\n\u00a0\u00a0\u00a0\u00a0public function next() {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return next($this-&gt;data);\r\n\u00a0\u00a0\u00a0\u00a0}\r\n\u00a0\u00a0\u00a0\u00a0public function valid() {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return ($this-&gt;current() !== false);\r\n\u00a0\u00a0\u00a0\u00a0}\r\n}\r\nfunction myGenerator($data) {\r\n\u00a0\u00a0\u00a0\u00a0foreach ($data as $item) {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0yield $item;\r\n\u00a0\u00a0\u00a0\u00a0}\r\n}\r\n$data = array(1, 2, 3, 4, 5);\r\n$generator = myGenerator($data);\r\n$iterator = new MyIterator($generator);\r\nforeach ($iterator as $key =&gt; $value) {\r\n\u00a0\u00a0\u00a0\u00a0echo \"Key: $key, Value: $value\\n\";\r\n}<\/pre>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><span style=\"font-weight: 400;\">In this example, we have created a <\/span><b>MyIterator<\/b><span style=\"font-weight: 400;\"> class that implements the <\/span><b>Iterator<\/b><span style=\"font-weight: 400;\"> interface. This class allows iteration through data and its processing. Subsequently, we created <\/span><b>myGenerator<\/b><span style=\"font-weight: 400;\">, which returns individual elements from the array. Finally, we used a generator to create an iterator and iterated through all the elements using a foreach cycle.<\/span><\/p>\n<p><b>The use of generators in combination with iterators allows us to create flexible and powerful iterable classes and is very useful for processing large files where memory overflow problems could otherwise occur. In addition, the use of iterators allows us to process data flexibly and efficiently in parts, thereby achieving better results when processing large data sets.<\/b><\/p>\n<h2><b>Other benefits of using generators<\/b><\/h2>\n<p><span style=\"font-weight: 400;\">It&#8217;s also very useful to use the <\/span><b>send()<\/b><span style=\"font-weight: 400;\"> generator method, which allows values to be passed back to the generator as <\/span><b>yield<\/b><span style=\"font-weight: 400;\">. This changes the one-way communication (from a generator to a caller) to a two-way channel between them.\u00a0<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Example of using a data logging tool via the<\/span><b> send() <\/b><span style=\"font-weight: 400;\">function:<\/span><\/p>\n<table>\n<tbody>\n<tr>\n<td>\n<pre>&lt;?php\r\n function createLogger($file)): Generator {\u00a0\u00a0\u00a0\u00a0$f = fopen($file, 'a');\r\n \u00a0\u00a0\u00a0\u00a0while (true) {\r\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0$line = yield;\r\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0fwrite($f, $line. \"\\n\");\r\n \u00a0\u00a0\u00a0\u00a0}\r\n }\r\n $log = createLogger('\/path\/to\/log\/file.log');\r\n $log-&gt;send(\"First\");\r\n $log-&gt;send(\"Second\");\r\n $log-&gt;send(\"Third\");<\/pre>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>&nbsp;<\/p>\n<p><span style=\"font-weight: 400;\">Two-way communication between the caller and the generator using the <\/span><b>send()<\/b><span style=\"font-weight: 400;\"> method can be used to implement cooperative multitasking. This basically means switching between multiple tasks \u2013 starting one task at a time and switching it with another task. I recommend<\/span> <a href=\"https:\/\/www.npopov.com\/2012\/12\/22\/Cooperative-multitasking-using-coroutines-in-PHP.html\"><span style=\"font-weight: 400;\">a<\/span><span style=\"font-weight: 400;\"> great blog<\/span><\/a><span style=\"font-weight: 400;\"> on how to implement cooperative multitasking using <\/span><b>co-routines<\/b><span style=\"font-weight: 400;\"> using PHP generators.<\/span><\/p>\n<p><b>It&#8217;s also important to emphasize that generators aren&#8217;t suitable for every situation \u2013 we should use the right tools for the right tasks. For example, when we need to store a larger amount of data in memory, it may be more convenient to use an array or a list instead of a generator.<\/b><\/p>\n<p><b>I would also like to mention that the use of generators can affect the performance of the code, as the generator must be created and controlled during the running of the program. Therefore, it&#8217;s important to remember that generators should be used with common sense.<\/b><\/p>\n<h2><b>Conclusion<\/b><\/h2>\n<p><span style=\"font-weight: 400;\">Generators in PHP are very useful for generating large amounts of data that we don&#8217;t need to store in memory at once. They have very low memory requirements and can be used to generate values based on requirements or conditions. Therefore, the use of generators in PHP allows us to generate large amounts of data efficiently and with low memory requirements.<\/span><\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"Generators are very useful features in PHP that allow you to generate and return large amounts of data&hellip;","protected":false},"author":42,"featured_media":7056,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":"","csco_display_header_overlay":false,"csco_singular_sidebar":"","csco_page_header_type":""},"categories":[199],"tags":[312,390,293,321],"_links":{"self":[{"href":"https:\/\/blog.bart.sk\/en\/wp-json\/wp\/v2\/posts\/7049"}],"collection":[{"href":"https:\/\/blog.bart.sk\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.bart.sk\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.bart.sk\/en\/wp-json\/wp\/v2\/users\/42"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.bart.sk\/en\/wp-json\/wp\/v2\/comments?post=7049"}],"version-history":[{"count":1,"href":"https:\/\/blog.bart.sk\/en\/wp-json\/wp\/v2\/posts\/7049\/revisions"}],"predecessor-version":[{"id":7050,"href":"https:\/\/blog.bart.sk\/en\/wp-json\/wp\/v2\/posts\/7049\/revisions\/7050"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.bart.sk\/en\/wp-json\/wp\/v2\/media\/7056"}],"wp:attachment":[{"href":"https:\/\/blog.bart.sk\/en\/wp-json\/wp\/v2\/media?parent=7049"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.bart.sk\/en\/wp-json\/wp\/v2\/categories?post=7049"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.bart.sk\/en\/wp-json\/wp\/v2\/tags?post=7049"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}