Disclaimer: Both solution is naive. You should always check the returned value of preg_match_all and strpos.
Readable regex solution:
Try to use preg_match_all
$fullstring = "this is [tag]dog[/tag], [tag]cat[/tag], [tag]lion[/tag]";
preg_match_all("'\[tag\](.*?)\[\/tag\]'si", $fullstring, $match);
foreach($match[1] as $val){
    echo $val, ' ';
}
// result: dog cat lion
To get only the content of the second tag (which is cat now)
echo $match[1][1]
// result: cat
Not readable string split solution:
$fullstring = 'this is [tag]dog[/tag], [tag]cat[/tag], [tag]lion[/tag]';
function get_strings_between(string $string, string $start, string $end): array {
    $r = [];
    $startLen = strlen($start);
    $endLen = strlen($end);
    while (!empty($string)) {
        $startPosition = strpos($string, $start);
        if ($startPosition === false) {
            return $r;
        }
        $contentStart = $startPosition + $startLen;
        $contentEnd = strpos($string, $end, $contentStart);
        $len = $contentEnd - $contentStart;
        $r[] = substr($string, $contentStart, $len);
        $endPosition = $contentEnd + $endLen;
        $string = substr($string, $endPosition);
    }
    return $r;
}
$match = get_strings_between($fullstring, '[tag]', '[/tag]');
// result: dog cat lion
To get only the content of the second tag (which is cat now)
echo $match[1]
// result: cat