What is the simplest way to extract a URL from a .bib entry for use in \href{}{} (probably using Biblatex)?

Using some of biblatex's on-board technologies we can make the code a bit shorter. (And I'm really not a fan of constructs such as \citeauthor{#2}, \citetitle{#2}, \citeyear{#2}, they go horribly wrong when several works are cited and they don't deal with pre- and postnotes that well. Granted, that might not be a problem here, but still ...)

Note first that the starred version of \DeclareCiteCommand produces a starred macro. So with \DeclareCiteCommand*{\citeimg} we define \citeimg*.

We also define a field format that gives us the link, but this time it takes any text and links that to the URL of the entry

\DeclareFieldFormat{imglink}{\href{\thefield{url}}{#1}}

It will be used as \printtext[imglink]{foo} later.

A bit fancier is

\makeatletter
\DeclareFieldFormat{imglink}{%
  \iffieldundef{url}
    {{#1}%
     \blx@warning@noline{you want to citeimg a work without URL,
     please check the entry '\thefield{entrykey}'}}
    {\ifhyperref
      {\href{\thefield{url}}{#1}}
      {#1}}}
\makeatother

that checks for URLs first and doesn't use \href if hyperref isn't loaded.

Then the macro that prints the data is

\newbibmacro*{cfr:imgcite}{%  
  \printnames{labelname}%
  \setunit{\addcomma\space}%
  \printfield[citetitle]{labeltitle}%
  \setunit{\addcomma\space}%
  \printfield{year}%
}

Finally, we can define the end-user cite commands

\DeclareCiteCommand*{\citeimg}
  {\boolfalse{citetracker}%
   \boolfalse{pagetracker}%
   \usebibmacro{prenote}}
  {\printtext[imglink]{\usebibmacro{cfr:imgcite}}}
  {\multicitedelim}
  {\usebibmacro{postnote}}

\DeclareCiteCommand{\citeimg}
  {\boolfalse{citetracker}%
   \boolfalse{pagetracker}%
   \usebibmacro{prenote}}
  {\usebibmacro{cfr:imgcite}}
  {\multicitedelim}
  {\usebibmacro{postnote}}

\makeatletter
\newrobustcmd*{\Citeimg}{%
  \@ifstar{\bibsentence\citeimg*}{\bibsentence\citeimg}}
\makeatother

MWE

\documentclass{article}
\usepackage[backend=biber]{biblatex}
\usepackage{hyperref}
\addbibresource{biblatex-examples.bib}


\makeatletter
\DeclareFieldFormat{imglink}{%
  \iffieldundef{url}
    {{#1}%
     \blx@warning@noline{you want to citeimg a work without URL,
     please check the entry '\thefield{entrykey}'}}
    {\ifhyperref
      {\href{\thefield{url}}{#1}}
      {#1}}}

\newbibmacro*{cfr:imgcite}{%  
  \printnames{labelname}%
  \setunit{\addcomma\space}%
  \printfield[citetitle]{labeltitle}%
  \setunit{\addcomma\space}%
  \printfield{year}%
}

\DeclareCiteCommand*{\citeimg}
  {\boolfalse{citetracker}%
   \boolfalse{pagetracker}%
   \usebibmacro{prenote}}
  {\printtext[imglink]{\usebibmacro{cfr:imgcite}}}
  {\multicitedelim}
  {\usebibmacro{postnote}}

\DeclareCiteCommand{\citeimg}
  {\boolfalse{citetracker}%
   \boolfalse{pagetracker}%
   \usebibmacro{prenote}}
  {\usebibmacro{cfr:imgcite}}
  {\multicitedelim}
  {\usebibmacro{postnote}}


\newrobustcmd*{\Citeimg}{%
  \@ifstar{\bibsentence\citeimg*}{\bibsentence\citeimg}}
\makeatother

\begin{document}
  \citeimg{markey}

  \citeimg*{brandt}

  \citeimg*{markey}

  \Citeimg{markey}

  \Citeimg*{markey}
\end{document}

example output


OK. I came up with something which seems to work - that is, it survives absolutely minimal testing, but will no doubt break as soon as I try to use it in a real document.

I am sure, however, that this cannot possibly be the simplest solution. There must be a more straightforward way of extracting the URL for use as a hyperlink target, mustn't there?

I declared a new 'field format' which consists of a hodgepodge of hodges and podges from biblatex.def. This is imglink and it is supposed to create a hyperlink with the text of the link made up of the name-title-year fields from whichever-entry-Biblatex-is-currently-processing.

    \DeclareFieldFormat{imglink}{%
      \href{#1}{%
        \printnames{labelname}, \printfield[citetitle]{labeltitle}, \thefield{year}%
      }%
    }%

I then hodged and podged some more stuff from biblatex.def to declare a new citation command, \citeurlimg.

    \DeclareCiteCommand{\citeurlimg}{%
      \boolfalse{citetracker}%
      \boolfalse{pagetracker}%
      \usebibmacro{prenote}%
    }{%
      \printfield[imglink]{url}%
    }{%
      \multicitedelim
    }{%
      \usebibmacro{postnote}%
    }%

I don't really have a use for all the bows and whistles here, but I supposed it wouldn't do any harm to leave the possibility of pre- and post- notes for now.

A bit more hodging (or podging) and mangling and tangling of stuff from biblatex.def suggested this way of defining \Citeurlimg. (I didn't ask for this in the question because I figured I'd just need to change \citeauthor to \Citeauthor. But since I'm not using that directly here, I needed a different approach for the capitalised version.)

    \newrobustcmd*{\Citeurlimg}{%
      \bibsentence\citeurlimg
    }%

This then means I can define \citeimg*{<bibkey>} and \Citeimg*{<bibkey>} as simple wrappers around \citeurlimg and \Citeurlimg in the starred cases, and as in my original code for the unstarred cases.

    \NewDocumentCommand\citeimg{ s m }{%
      \IfBooleanTF{#1}{%
        \citeurlimg{#2}%
      }{%
        \citeauthor{#2}, \citetitle{#2}, \citeyear{#2}%
      }%
    }%
    \NewDocumentCommand\Citeimg{ s m }{%
      \IfBooleanTF{#1}{%
        \Citeurlimg{#2}%
      }{%
        \Citeauthor{#2}, \citetitle{#2}, \citeyear{#2}%
      }%
    }%

Complete example:

\documentclass{beamer}
\usepackage{xparse}
\makeatletter
\AtBeginDocument{%
  \@ifpackageloaded{biblatex}{%
    \DeclareFieldFormat{imglink}{%
      \href{#1}{%
        \printnames{labelname}, \printfield[citetitle]{labeltitle}, \thefield{year}%
      }%
    }%
    \DeclareCiteCommand{\citeurlimg}{%
      \boolfalse{citetracker}%
      \boolfalse{pagetracker}%
      \usebibmacro{prenote}%
    }{%
      \printfield[imglink]{url}%
    }{%
      \multicitedelim
    }{%
      \usebibmacro{postnote}%
    }%
    \newrobustcmd*{\Citeurlimg}{%
      \bibsentence\citeurlimg
    }%
    \NewDocumentCommand\citeimg{ s m }{%
      \IfBooleanTF{#1}{%
        \citeurlimg{#2}%
      }{%
        \citeauthor{#2}, \citetitle{#2}, \citeyear{#2}%
      }%
    }%
    \NewDocumentCommand\Citeimg{ s m }{%
      \IfBooleanTF{#1}{%
        \Citeurlimg{#2}%
      }{%
        \Citeauthor{#2}, \citetitle{#2}, \citeyear{#2}%
      }%
    }%
  }{}%
}
\makeatother
\usepackage[backend=biber]{biblatex}
\bibliography{biblatex-examples}
\begin{document}
\begin{frame}

  \citeimg{markey}

  \citeimg*{markey}

  \Citeimg{markey}

  \Citeimg*{markey}

\end{frame}
\end{document}

EDIT

Just for completeness, here's what I've actually got right now. It is pretty much moewe's answer but tries to avoid \def.

\AtBeginDocument{%
  \@ifpackageloaded{biblatex}{%
    % moewe's answer at https://tex.stackexchange.com/a/290681/
    \@ifpackageloaded{hyperref}{%
      \DeclareFieldFormat{imglink}{%
        \iffieldundef{url}
        {%
          {#1}%
          \blx@warning@noline{citeimg cannot hyperlink entry '\thefield{entrykey}' as it lacks field url}%
        }{%
          \href{\thefield{url}}{#1}%
        }%
      }%
    }{%
      \DeclareFieldFormat{imglink}{#1}%
    }%
    \newbibmacro*{cfr:imgcite}{%
      \printnames{labelname}%
      \setunit{\addcomma\space}%
      \printfield[citetitle]{labeltitle}%
      \setunit{\addcomma\space}%
      \printfield{year}%
    }%
    \DeclareCiteCommand*{\citeimg}{%
      \boolfalse{citetracker}%
      \boolfalse{pagetracker}%
      \usebibmacro{prenote}%
    }{%
      \printtext[imglink]{\usebibmacro{cfr:imgcite}}%
    }{%
      \multicitedelim
    }{%
      \usebibmacro{postnote}%
    }%
    \DeclareCiteCommand{\citeimg}{%
      \boolfalse{citetracker}%
      \boolfalse{pagetracker}%
      \usebibmacro{prenote}%
    }{%
      \usebibmacro{cfr:imgcite}%
    }{%
      \multicitedelim
    }{%
      \usebibmacro{postnote}%
    }%
    \newrobustcmd*{\Citeimg}{%
      \bibsentence\@ifstar{\citeimg*}{\citeimg}%
    }%
  }{}%
}

What I might do is take out the conditional dependency on the load of Biblatex and just add the following to my biblatex.cfg, which I think will work:

    \@ifpackageloaded{hyperref}{%
      \DeclareFieldFormat{imglink}{%
        \iffieldundef{url}
        {%
          {#1}%
          \blx@warning@noline{citeimg cannot hyperlink entry '\thefield{entrykey}' as it lacks field url}%
        }{%
          \href{\thefield{url}}{#1}%
        }%
      }%
    }{%
      \DeclareFieldFormat{imglink}{#1}%
    }%
    \newbibmacro*{cfr:imgcite}{%
      \printnames{labelname}%
      \setunit{\addcomma\space}%
      \printfield[citetitle]{labeltitle}%
      \setunit{\addcomma\space}%
      \printfield{year}%
    }%
    \DeclareCiteCommand*{\citeimg}{%
      \boolfalse{citetracker}%
      \boolfalse{pagetracker}%
      \usebibmacro{prenote}%
    }{%
      \printtext[imglink]{\usebibmacro{cfr:imgcite}}%
    }{%
      \multicitedelim
    }{%
      \usebibmacro{postnote}%
    }%
    \DeclareCiteCommand{\citeimg}{%
      \boolfalse{citetracker}%
      \boolfalse{pagetracker}%
      \usebibmacro{prenote}%
    }{%
      \usebibmacro{cfr:imgcite}%
    }{%
      \multicitedelim
    }{%
      \usebibmacro{postnote}%
    }%
    \newrobustcmd*{\Citeimg}{%
      \bibsentence\@ifstar{\citeimg*}{\citeimg}%
    }%

This is actually the only reason there's a conditional dependency on hyperref being loaded. As it is now, it only gets used with Beamer, which loads the package anyway. But if I put it in my .cfg, which might be handy, I need it to work also in the usual case when hyperref is not loaded.

[I tried to use the conditional Biblatex provides, \ifhyperref, but the sequence didn't seem to be recognised, so maybe I've misunderstood its intended usage.]