TransWikia.com

Get a key value from a JSON asset in PHP

Craft CMS Asked on January 10, 2021

I’m using the Apple News plugin to try and display a tweet that’s been added as a JSON asset in a matrix field. The JSON looks something like this

{
    "title": "https://twitter.com/TehseenLadha/status/1291773476877959169",
    "description": null,
    "url": "https://twitter.com/TehseenLadha/status/1291773476877959169",
    ...
}

According to the Apple News Publisher docs, all you need is the tweet’s URL. I’m trying to get it by converting the JSON file to a string with file_get_contents and then using json_decode, but it’s not working. This is what I have in MyNewsArticle.php:

case 'tweet':
  $asset = $block->tweet->one()->getUrl();
  $string = file_get_contents($asset);
  $jsonArr = json_decode($string, true);
  $tweetUrl = $jsonArr['url'];

  if ($tweetUrl) {
    $components[] = [
      'role' => 'tweet',
      'layout' => 'tweetLayout',
      'URL' => $tweetUrl,
    ];
  }
break;

It’s grabbing the correct URL of the asset, but fails with failed to open stream: Operation timed out on the $string = file_get_contents($asset); line. Apparently this is something to do with IPv4 vs IPv6? I’m not certain how to get around it though.

One Answer

I assume that $block->tweet->one() returns an Asset element in your matrix block called tweet. I suggest that you use the getContents() method on Craft's Asset element type to retrieve the string content of the actual file. Your code block would look something like this:

case 'tweet':
  $tweetFileContent = $block->tweet->one()->getContents();
  $tweetJson = json_decode($tweetFileContent, true);
  $tweetUrl = $tweetJson['url'];

  if ($tweetUrl) {
    $components[] = [
      'role' => 'tweet',
      'layout' => 'tweetLayout',
      'URL' => $tweetUrl,
    ];
  }
break;

However, I would recommend extending your code as follows to address empty state and potential exception:

case 'tweet':
  if (empty($block->tweet)) {
    // return early or do something else
  }
  try {
    $tweetFileContent = $block->tweet->one()->getContents();
    $tweetJson = json_decode($tweetFileContent, true);
    $tweetUrl = $tweetJson['url'];

    if ($tweetUrl) {
      $components[] = [
        'role' => 'tweet',
        'layout' => 'tweetLayout',
        'URL' => $tweetUrl,
      ];
    }
  } catch ($e) {
    // getContents() throws 
    // InvalidConfigException if [[volumeId]] is missing or invalid,
    // AssetException if a stream could not be created
  }
break;

Correct answer by Johannes on January 10, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP