Asked  8 Months ago    Answers:  5   Viewed   83 times

I would like to display data, two columns per row during my foreach. I would like my result to look like the following:

 <table>
 <tr><td>VALUE1</td><td>VALUE2</td></tr>
 <tr><td>VALUE3</td><td>VALUE4</td></tr>
 <tr><td>VALUE5</td><td>VALUE6</td></tr>
 </table>

Any help would be greatly appreciated.

 Answers

59
$i=0;
foreach ($x as $key=>$value)
  {
  if (fmod($i,2)) echo '<tr>';
  echo '<td>',$value,'</td>';
  if (fmod($i,2)) echo '</tr>';
  $i++;
  }

this will output TR (row) each second time

ps: i haven't tested the code, so maybe you will need to add ! sign before fmod, if it doesn't output TR on first iteration, but on second iteration in the beginning...

Wednesday, March 31, 2021
 
Yrtymd
answered 8 Months ago
82

I finally found my solution here. I had to slightly change the code, and here are the changes. Now, if I can fully support multiple ranges, it'll be complete.

(I'm sharing this because all I see are incomplete answers. Hopefully, it will also help someone too.)

$file = $basePath . $media->getFileName();
$fileSize = filesize($file);
$fileTime = date('r', filemtime($file));
$fileHandle = fopen($file, 'r');

$rangeFrom = 0;
$rangeTo = $fileSize - 1;
$etag = md5(serialize(fstat($fileHandle)));
$cacheExpires = new DateTime();


if (isset($_SERVER['HTTP_RANGE'])) {
    if (!preg_match('/^bytes=d*-d*(,d*-d*)*$/i', $_SERVER['HTTP_RANGE'])) {
        $statusCode = 416;
    } else {
        $ranges = explode(',', substr($_SERVER['HTTP_RANGE'], 6));
        foreach ($ranges as $range) {
            $parts = explode('-', $range);

            $rangeFrom = intval($parts[0]); // If this is empty, this should be 0.
            $rangeTo = intval($parts[1]); // If this is empty or greater than than filelength - 1, this should be filelength - 1.

            if (empty($rangeTo)) $rangeTo = $fileSize - 1;

            if (($rangeFrom > $rangeTo) || ($rangeTo > $fileSize - 1)) {
                $statusCode = 416;
            } else {
                $statusCode = 206;
            }
        }
    }
} else {
    $statusCode = 200;
}

if ($statusCode == 416) {
    $response = $this->getResponse();

    $response->setStatusCode(416);  // HTTP/1.1 416 Requested Range Not Satisfiable
    $response->addHeaderLine('Content-Range', "bytes */{$fileSize}");  // Required in 416.

} else {

    fseek($fileHandle, $rangeFrom);

    set_time_limit(0); // try to disable time limit

    $response = new Stream();
    $response->setStream($fileHandle);
    $response->setStatusCode($statusCode);
    $response->setStreamName(basename($file));

    $headers = new Headers();
    $headers->addHeaders(array(
        'Pragma' => 'public',
        'Expires' => $cacheExpires->format('Y/m/d H:i:s'),
        'Cache-Control' => 'no-cache',
        'Accept-Ranges' => 'bytes',
        'Content-Description' => 'File Transfer',
        'Content-Transfer-Encoding' => 'binary',
        'Content-Disposition' => 'attachment; filename="' . basename($file) .'"',
        'Content-Type' => 'audio/mpeg, audio/x-mpeg, audio/x-mpeg-3, audio/mpeg3',  // $media->getFileType(),
        'Content-Length' => $fileSize,
        'Last-Modified' => $fileTime,
        'Etag' => $etag,
        'X-Pad' => 'avoid browser bug',
    ));

    if ($statusCode == 206) {
        $headers->addHeaderLine('Content-Range', "bytes {$rangeFrom}-{$rangeTo}/{$fileSize}");
    }

    $response->setHeaders($headers);
}

return $response;
Wednesday, March 31, 2021
 
Keat
answered 8 Months ago
84

Your problem is the lack of AJAX to connect Javascript and PHP. The way your PHP script works is by manually running the script, so only the device hitting that script will see the notification. There is nothing that actually sends that info to your other device right now.

To better explain the problem, your desktop may have allowed access to the notifications, but it doesn't automatically pull in those notifications. The code you have provided will need to use AJAX to hit the script URL, instead of using it as a cron job.

First off, you need to start a repeating request to the PHP script to see if there has been any updated notification. If there is a new notification, then you need to create a new notification object using the returned response.

Second, you need to alter the PHP script to output a JSON string rather instead of the notification script.

JSON output example:

{
  {
    title: 'new blog!',
    options: {
      body: 'come read my new blog!',
      icon: 'same icon as before or maybe a new one!'
    }
  },
  {
    title: 'another blog item!',
    options: {
      body: 'come read my second blog!',
      icon: 'hooray for icons!'
    }
  }
}

Your notifyUsers() should take title and option as arguments instead of hardcoding them:

function notifyUser(title, options) { ... }

Using jQuery, get the PHP response and create the notification:

function checkNotifications(){
  $.get( "/path/to/script.php", function( data ) {
    // data is the returned response, let's parse the JSON string
    json = JSON.parse(data);

    // check if any items were returned
    if(!$.isEmptyObject(json)){
      // send each item to the notify function
      for(var i in json){
        notifyUser(json[i].title, json[i].options);
      }
    }
  });

  setTimeout(checkNotifications, 60000); // call once per minute
}

Now, you just need to kickstart the AJAX polling, so add this to your webpage:

$(document).ready(checkNotifications);

That's pretty much it! You were just missing the part when your desktop needed to pull in the notifications. Heads up though, this isn't tested and you may need to tweek something.

Wednesday, March 31, 2021
 
nighter
answered 8 Months ago
57

https://plnkr.co/edit/umL80bh0WKr8aPEueCxZ?p=preview

You can create pipe to get pairs values:

@Pipe({ name: 'pairs' })
export class PairsPipe implements PipeTransform {
  transform(array) {
    return array.reduce((result, item, index) => (
      index % 2 ? result : [...result, [item, array[index + 1]]]
    ), []);
  }
}

add pipe to Module:

@NgModule({
  imports: [ BrowserModule ],
  declarations: [ App , PairsPipe],
  bootstrap: [ App ]
})

and use in *ngFor:

 <tr *ngFor="let item of data | pairs">
Tuesday, August 3, 2021
 
MDDY
answered 3 Months ago
78

There's a divisibleby tag.

So you can do something (ugly) like:

<table><tr>
{% for field in form %}
   <td>{{ field }}</td>
   {% if forloop.last %}
     </tr>
   {% else %}
     {% if forloop.counter|divisibleby:"3" %}
       </tr><tr>
     {% endif %}
   {% endif %}
{% endfor %}
</table>

Alternatively, you could give your form class a table_print method that returns a html string (wrapped in mark_safe).

Wednesday, August 11, 2021
 
tim_d
answered 3 Months ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :
 
Share