PHP string concat

I have a url and a couple of php variables inside a string. The issue is that the word threads becomes a non string. Anyone know how to properly write the syntax to make this work?

'https://api.site.net/v2/conversations/'.$lf_conversation_id.'/threads/'.$lf_thread_id.'/attachments';

Solution, I added one space before the first /threads

'https://api.site.net/v2/conversations/'.$lf_conversation_id.' /threads/'.$lf_thread_id.'/attachments';

:thinking:

That doesn’t sound right. Regardless of how you’re concatenating, the end result will be a string. So there’s something definitely wrong with your variables. Make sure they aren’t objects, arrays or null.

<?php
$lf_conversation_id = (int)123123131;
$lf_thread_id = (int)6464616;

print 'https://api.site.net/v2/conversations/'.$lf_conversation_id.'/threads/'.$lf_thread_id.'/attachments';

Gives me

https://api.site.net/v2/conversations/123123131/threads/6464616/attachments

I’m deliberately type casting aka forcing them to be an integer just to show you having numbers in there doesn’t change the fact the end result will be a string or have any issues.

And if I do something like this

<?php
$lf_conversation_id = (int)123123131;
$lf_thread_id = (int)6464616;

$url = 'https://api.site.net/v2/conversations/'.$lf_conversation_id.'/threads/'.$lf_thread_id.'/attachments';

print gettype($url); // gettype() will output the data type of the variable

I get

spaceshiptrooper@localhost:~$ php url.php
string

i also dont see how adding a space inside something that was already a string magically solved anything.

I suspect OP’s quote marks tripped them up, and in trying to fix it with the space, they accidentally corrected the error.

1 Like

Just to clarify, I eventually found out that inside the PHP file, I had missing “.” where I was concatenating other variables inside a JSON. “‘.$var.’”

It was causing unknown issues further down the script.

1 Like

Well this is the reason why you shouldn’t put everything into 1 file like that. They call that “spaghetti code” since it’s a mixture of 100 (exaggerating) languages all intertwined into 1 single line of code or even in a single file. Mix matching all sorts of nonsense is an utter mess and makes it extremely difficult to maintain and debug.

My suggestion is

  • Don’t stick random variables where they don’t make sense.
  • Don’t just do random concatenations where it doesn’t make sense i.e. ""$helloWorld"."$foo""."$bar"".
  • If you must use concatenations, this is personal preference, but I prefer to use single quotes because it doesn’t make the code look like I’ve got 2 single quotes when really, it would be 1 double quote.
    • As part of this bullet, if you must use concatenations, do something like this

      echo $helloWorld . $foo . $bar

      It makes perfect sense in this case because all we’re using are variables. If we really wanted to add a hardcoded string in there, then it would look something like

      echo $helloWorld . ' Concat this ' . $foo . ' string ' . $bar

      No unnecessary trailing quotes and no unnecessary random quotes. Just straight to the point.

  • Always add spacings whenever you’re concatenating to help you determine if you need to end the concatenation or not.
  • Don’t do this echo "$helloWorld"."" or echo "$helloWorld".$foo."". None of that makes any sense because you don’t need trailing concatenations nor random quotes because all you’re doing is concatenating 2 variables together. Do you really need quotes in there? I’m betting not.

I much prefer sprintf over concatenation:

$var = sprintf(
    'https://api.site.net/v2/conversations/%s/threads/%s/attachments',
    $lf_conversation_id,
    $lf_thread_id,
);

The first %s will be replaced by the value of $lf_conversation_id, the second %s will be replaced by the value of $lf_thread_id.

I use %s here, because I want the string value. You can also use %d for digits, %f for floats, and more.

3 Likes

If you are making an API call and the API requires a specific format, it makes it easier to just plug in your variables into a preformatted JSON instead of rebuilding the entire JSON from scratch. Otherwise, I would build it from scratch. But if you have over 100 different APIs you’re working with, it just makes more sense to concat.

So if the API is expecting double quotes around a property or value then I find using single quotes and . inside the double quotes works. E.G.

"key": "'.$var.'"

So you are manually creating JSON strings by concating strings?
Wouldn’t it be simpler to put the values into an array or object, then json_encode() it?

2 Likes

I agree. It doesn’t make sense to concatenate JSON strings because you can properly do that by creating an stdClass object of items you want. Then use json_encode() on that object which then formats object properly into a JSON string. So not entirely sure why one would “want” to concatenate or “build” a JSON string when you can do that properly using other methods.

Well,

I’m all ears if you have a better way. But if I have to write over a hundred API calls between 30 different companies, then it’s easier to extract the expected JSON format and simply concat my values. It requires less time. If someone requires square brackets then a named array, followed by a nested JSON as a value, it makes it much simpler to simply plug in your variables. It’s really a case-by-case thing but the expected JSON is up to the company and so are my values.

<?php
// Create the objects here
$objects = [];

$object1 = new stdClass();
$object1->id = 1;
$object1->name = 'Demo Account';
$object1->email = 'demo@localhost.com';

$object2 = new stdClass();
$object2->id = 2;
$object2->name = 'Admin Account';
$object2->email = 'admin@localhost.com';

// Add objects to the array
$objects[] = $object1;
$objects[] = $object2;

// Transform the array into a JSON object
$encodedJson = json_encode($objects, JSON_PRETTY_PRINT);

// Output the JSON object for demonstration purposes
print "Encoded JSON string\r\n" . $encodedJson . "\r\n\r\n";

// Decode the JSON object for demonstration purposes
$decodedJson = json_decode($encodedJson);

// Loop through the decoded JSON object
foreach($decodedJson AS $json) {
	print 'Id: ' . $json->id;
	print "\r\n";
	print 'Name: ' . $json->name;
	print "\r\n";
	print 'Email: ' . $json->email;
	print "\r\n";
}

That returns

Encoded JSON string
[
    {
        "id": 1,
        "name": "Demo Account",
        "email": "demo@localhost.com"
    },
    {
        "id": 2,
        "name": "Admin Account",
        "email": "admin@localhost.com"
    }
]

Id: 1
Name: Demo Account
Email: demo@localhost.com
Id: 2
Name: Admin Account
Email: admin@localhost.com

So if you wanted to get say the 2nd user’s email only, you can put something like

if($key == 1) {
	print 'Email: ' . $json->email;
	print "\r\n";
} else {
	... Do something else
}

Where $key is the index of that array object or you can even do if you want to be consistent and use the object itself rather than the index key.

if($json->id == 2) {
	print 'Email: ' . $json->email;
	print "\r\n";
} else {
	... Do something else
}

This is by “far” the best and easiest way to work with JSON strings in PHP because you’re not trying to do random regexs or even random modifications on the JSON string itself. If you wanted more fields added to that JSON string, all you need to do is add those fields to the $object1 or $object2 variables.


In the case you’re talking about, all you would do is something along the lines of

$decodeJson = json_decode($encodedJsonStringHere);

print $decodeJson->email;

And if you wanted to replace that value, you overwrite the value and then encode back into a JSON string. Simple as that.

So something like

$decodeJson = json_decode($encodedJsonStringHere);

// Old email
print $decodeJson->email; // returns demo@localhost.com if we were targeting the first object in the array, if not then it would return all emails if this was used in the foreach loop

$decodeJson->email = 'NewEmail@email.com';

// New email
print $decodeJson->email; // returns NewEmail@email.com
2 Likes

I see what you are saying. Your JSON is pretty straightforward. Many API’s JSON are not that pretty. Try adding some nested arrays inside some of your values, then JSON encode that stdClass().

By the time you have properly formatted and built your JSON for the one API, I could have moved on to another one. For you, I think your example is more efficient but for me, I like a simple concatenation.

If I control the JSON formatting then obviously I would not concat but use your approach.

I think in general it is always best to build the JSON as you are doing. For me, with my particular needs, concat is just faster and I’m okay with it.

Simplicity isn’t always the best. It can sometimes cause more problems and wastes more time than you really wanted. You’ll spend more time debugging why PHP is throwing you an unexpected " at line blah blah if you’re not watching your concatenations. It’s even worse when you’ve got an entire book all in 1 single line. That makes everything extremely difficult to debug because at that point it’s complaining about an error occurring at line 1 when there’s only 1 line that’s an entire book long.

Manually creating JSON strings in PHP is a nightmare, and it only gets more difficult, the more complex the data structure is. Jumping in and out of quotes to concat, while dealing the the quotes, brackets, etc, that are part of the string will drive you insane.
I can confess to having done this, years ago when I didn’t know any better.

The very simplest way is to build the data structure in a PHP native manner, that is arrays and/or objects.
Once you have that whole structure, json_encode() and all the formatting is done for you. It’s so easy.
Having done it this way I would never go back to manually building a string.

You seem to think using the encoding method will get more difficult with more comlex data. The truth is the contcat method is the way that gets more difficult.
But we can lead a horse to water…

How hard can it be?

$foo = ['a', 'b', 'c'];
$bar = ['d', 'e', 'f'];
$baz = ['g', 'h', 'i'];
$nestArray = [$foo, $bar, $baz];

$object1->list = $nestArray ;
.

The encode part is no more difficult regardles of the complexity of the data, as it’s just a case of calling that function and passing the data to it. It takes care of all the formatting, so long as the structure is correctly built.

How you build the data is up to you, or depends upon the source, but dealing with arrays and objects has to be easier than all that string concat.

Adding onto this, if you’re trying to output data you get back from the database into the JSON response, all you would need to do is

print json_encode($data, JSON_PRETTY_PRINT);

Where $data is the returned variable you get when you run your database query. Could be a single object, could be an array. Doesn’t matter, PHP handles all of that for you.

So pesudo code to demonstrate that would be something like

public function getUsers(): array {
	$sql = 'SELECT id, name, email FROM users';
	$prepare = $this->db->prepare($sql);
	$prepare->execute();

	if($prepare->rowCount()) {
		return $prepare->fetchAll();
	} else {
		return [];
	}
}

And then to get that data, you would just do

// Get user data
$data = $this->getUsers();

// Transform data into JSON object
print json_encode($data, JSON_PRETTY_PRINT);

That would return this same result.

[
    {
        "id": 1,
        "name": "Demo Account",
        "email": "demo@localhost.com"
    },
    {
        "id": 2,
        "name": "Admin Account",
        "email": "admin@localhost.com"
    }
]

You guys are the experts and I appreciate your insights. Thanks for sharing your code examples. Perhaps when in the future I am as proficient in PHP as all of you, I will take your approach. I do prefer to do everything the correct way even if it takes longer and requires more knowledge, but I did need to get moving along with my project, with my current knowledgebase.