0

I'm doing a system to log users' actions, such as the purchases it made, friends it added, among anothers. For example, when a user purchase some products, the following message should appear in your profile:

Foo bought the products A, B, C, D and F.

I could save the whole string in the database, but the site will have more than one language, which will make unviable keep a record for each language. My idea is to have a string with the template of the action taken and pass it to the sprintf function, however, the amount of products may change, so the number of arguments as well. In this situation, how should I proceed?

Edit #1: My question is not about the database schema, the schema I'm using is this: Databases: Making a Log of actions, how to handle various references?, The question is how to make a string to be used with sprintf that can receive as many arguments as needed. Something like this: "%s bought the products [magic here]"

2 Answers 2

2

Have a unique code for each action. Store the action in a number of fields in a table called log:

user      action      products
-----------------------------------
Foo       BUY         A|B|C|D

Map BUY to human-readable descriptions in your application as required.

You could separate out the individual products if required, to achieve full normalisation... though if you don't need anything more with them and their representations are concise IDs (with no | in them!) then tokenisation will do fine.

Sign up to request clarification or add additional context in comments.

4 Comments

Yep, I'm using this schema: stackoverflow.com/questions/1989100/…, but the question is how to make a string to be used with sprintf that can receive as many arguments as needed.
sprintf() doesn't work that way. Build the string externally and then pass it into sprintf as a single %s.
@Marc B I thought there would be another way to do this, but apparently the way you're saying is the only way. :(
sprintf's are take X, format it as Y type things. None of its arguments allow take four values A,B,C,D and conver them to a single Y. They're 1:1 conversions only. If you want many:1, you'll have to do it externally.
0

sprintf() is a good choice for buiding the output string because it will afford the separation of the literal characters from the dynamic content in a most-readable way.

$verbMap = ['buy' => 'bought', 'sell' => 'sold'];
$words = explode(',', $row['items']);

return sprintf(
    '%s %s the products %s.',
    $row['user'],
    $verbMap[$row['action']] ?? 'did who-knows-what', // translate verbs to correct tense
    implode(', ', $words + ['last' => implode(' and ', array_splice($words, -2))]) // implode items with proper English grammar
);

There are a myriad of different techniques which can be used to convert delimited items or an array of items to proper English.

Ideally, multiple values shouldn't be stored as a comma-separated string in a database. Regardless of how you store the values, the above script is well-suited to implode an array into proper English.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.