1

How would I amend the following foreach loop so each link displays the keys from each nested query, and not just the values? I am creating my own social sharing links, included using get-template-part, and very nearly have it, I think.

E.g. Twitter currently returns: https://twitter.com/intent/tweet?TITLE&PERMALINK
Instead of: https://twitter.com/intent/tweet?text=TITLE&url=PERMALINK (Note: text= and url= )

I have tried ( $social_links as $key => $value ) and
( $social_links as $social_link && $social_link as $key => $value )

Neither of which is obviously correct.

<?php
    // Setup the links
    $social_links = array(
        'facebook'  => array(
            'title' => 'Facebook',
            'base'  => 'https://www.facebook.com/sharer/sharer.php',
            'query' => array(
                'u'     => get_permalink(),
                't'     => get_the_title(),
            ),
        ),
        'twitter'   => array(
            'title' => 'Twitter',
            'base'  => 'https://twitter.com/intent/tweet',
            'query' => array(
                'text'  => get_the_title(),
                'url'   => get_permalink(),
            ),
        ),

        'pinterest' => array(
            'title' => 'Pinterest',
            'base'  => 'http://www.pinterest.com/pin/create/button/',
            'query' => array(
                'url'         => get_permalink(),
                'media'       => get_the_post_thumbnail_url(),
                'description' => get_the_title(),
            ),
        ),
        'linked-in' => array(
            'title' => 'LinkedIn',
            'base'  => 'https://www.linkedin.com/shareArticle',
            'query' => array(
                'mini'  => 'true',
                'url'   => get_permalink(),
                'title' => get_the_title(),
            ),
            // append '?refresh' to force new scrape
        ),              
    );
?>

<ul class="links-social">
<?php 
    // Loop through the links
    foreach( $social_links as $social_link ) : ?>
        <li>
            <a target="_blank" href="<?php echo $social_link['base']  . '?' . implode( '&', $social_link['query'] ); ?>">
                <?php echo $social_link['title']; ?>
            </a>
        </li>
<?php   
    endforeach;
?>
</ul>
1

Your issue has nothing to do with the foreach. The problem is this part:

implode( '&', $social_link['query'] )

implode() only connects the values. There's nothing in this code that adds the keys or an =.

If you want to add an array of key/values as a query string to a URL, WordPress provides a function for this called add_query_arg(), it accepts an array of key values and a URL to add them to.

In your case you'd use it like this:

<a target="_blank" href="<?php echo esc_url( add_query_arg( $social_link['query'], $social_link['base'] ) ); ?>">
    <?php echo $social_link['title']; ?>
</a>

Note my use of esc_url. As the documentation states:

Important: The return value of add_query_arg() is not escaped by default. Output should be late-escaped with esc_url() or similar to help prevent vulnerability to cross-site scripting (XSS) attacks.

Another thing to consider is that the values in the query string need to be URL encoded. You can do this with the urlencode() PHP function:

'title' => urlencode( get_the_title() ),

However you'll need to do this for every value if you do it like that. A way do to this with less code would be to use array_map() to apply urlencode() to every value just before putting into add_query_arg():

foreach( $social_links as $social_link ) :
    $query_args = array_map( 'urlencode', $social_link['query'] );
    ?>

    <li>
        <a target="_blank" href="<?php echo esc_url( add_query_arg( $query_args, $social_link['base'] ) ); ?>">
            <?php echo $social_link['title']; ?>
        </a>
    </li>

    <?php
endforeach;
  • I'd not come across add_query_arg() before, thanks Jacob! One slight concern, from my code, is that titles are returned with spaces. Do you happen to know of a way to introduce "%" or something similar to the string? – the-first-man Mar 1 '18 at 3:51
  • 1
    I've updated my answer. – Jacob Peattie Mar 1 '18 at 4:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.