I use preg_match_all to find the usernames in the 'body' and save them in a database. How can I find the usernames in several input fields, for example: body, title and article? And how can I save the found references to the database without saving duplicate entries?
if ($post) {
preg_match_all('/\B#(\w+)/', $request->get('body'), $mentionedUsers);
foreach ($mentionedUsers[1] as $mentionedUser) {
$foundUser = User::where('username', $mentionedUser)->first();
if(!$foundUser){
continue;
}
$foundUserId = $foundUser->id;
$mentionedUser_save = new Mentioned_post_user;
$mentionedUser_save->user_id_lead = Auth::user()->id;
$mentionedUser_save->user_id = $foundUserId;
$mentionedUser_save->post_id = $post->id;
$mentionedUser_save->save();
}
}
You can utilize whereIn('user_name', $mentionedUsers) instead of running foreach.
if ($post) {
// assuming this line works and mentioned users are in $mentionedUsers[1]
preg_match_all('/\B#(\w+)/', $request->get('body'), $mentionedUsers);
$foundUsers = User::whereIn('username', $mentionedUsers[1])->get();
if ($foundUsers) {
foreach ($foundUsers as $foundUser) {
$foundUserId = $foundUser->id;
$mentionedUser_save = new Mentioned_post_user;
$mentionedUser_save->user_id_lead = Auth::user()->id;
$mentionedUser_save->user_id = $foundUserId;
$mentionedUser_save->post_id = $post->id;
$mentionedUser_save->save();
}
}
}
Otherwise, you'd need to get unique values of $mentionedUsers[1] with array_unique(). (I'd suggest the solution above)
Edit: Sorry a thought your problem was different. For your solution, the approach I'd use is combine all inputs.
$theString = "$request->body $request->title $request->article";
preg_match_all('/\B#(\w+)/', $theString, $mentionedUsers);
$userNamesArray = array_unique($mentionedUsers[1]);
$foundUsers = User::whereIn('username', $userNamesArray)->get();
Related
Basically I want the same result that this SQL would return:
SELECT id FROM property_group_option opt
LEFT JOIN property_group_option_translation tra
ON opt.id = tra.property_group_option_id
WHERE opt.property_group_id = <id> AND tra.name = "<name>"
The way to go described in the Shopware documentation does not seem to get the right result. I have tried the following:
$criteria = (new Criteria())
->addFilter(new EqualsFilter('property_group_id', $propertyGroupId))
->getAssociation('property_group_option_translation')
->addFilter(new EqualsFilter('name', $value));
$result = $this->propertyGroupOptionRepository->search($criteria, Context::createDefaultContext())->first()->getId();
I did find a workaround which does not seem to be the way to go (and is also not the best performing), but it did return the right result.
$criteria = (new Criteria());
$criteria->addFilter(new EqualsFilter('name', $value));
$criteria->getAssociation('property_group_option')
->addFilter(new EqualsFilter('groupId', $propertyGroupId));
$translation = $this->propertyGroupOptionTranslationRepository->search($criteria, Context::createDefaultContext())->first()
if($translation !== null) {
$criteria = (new Criteria([$translation->get('propertyGroupOptionId')]));
$result = $this->propertyGroupOptionRepository->search($criteria, Context::createDefaultContext())->first()->getId();
}
is there a proper solution for that?
You are using the table name. Try to use the model name instead.
You have to use addAssociation() first - getAssociation() seems to return a new Criteria instance which is later not used in the actual query, if the association did not exist before:
See in the code.
public function getAssociation(string $path): Criteria
{
$parts = explode('.', $path);
$criteria = $this;
foreach ($parts as $part) {
if ($part === 'extensions') {
continue;
}
if (!$criteria->hasAssociation($part)) {
$criteria->associations[$part] = new Criteria(); // this is returned, but not stored
}
$criteria = $criteria->associations[$part];
}
return $criteria;
}
Can someone help me figure out what I'm doing wrong here. Basically, this script is looping through $replies from a query and adding values to the object. However, its overwriting the ->replies with the last one.
$store->{$f->id}->replies = $store->{$f->id}->replies ?? (object)[];
$store->{$f->id}->replies->{$reply->id} = $reply;
If this was to loop through 3 replies, it should store:
$store->{$f->id}->replies->one = 'reply 1';
$store->{$f->id}->replies->two = 'reply 2';
$store->{$f->id}->replies->three = 'reply 3';
Instead it only stores the third one:
$store->{$f->id}->replies->three
Here is full code of the loop:
while($f = $q->fetch()) {
$reply = static::chatter_message_format($f);
$store->{$f->id} = $f;
//If checking for posts from friends, user_id will be array
if(is_array($user_id)) {
if($reply) {
$store->{$f->id}->replies = $store->{$f->id}->replies ?? (object)[];
$store->{$f->id}->replies->{$reply->id} = $reply;
}
}
}
If I echo $reply in the loop, I see each reply. The $store is being written to a cache file but it seems to only save the last reply for each post.
I code in python mostly but have inherited this project in PHP - a lot of it is over my head but I'm learning rapidly :) I will be rebuilding this using an API-first approach soon but trying to salvage what I can for prototype.
Ah, figured it out. Issue in the loop, this fixed it:
if(is_array($user_id)) {
if(!isset($store->{$f->id})) {
$store->{$f->id} = $f; //Was creating a new object here before the isset check.
}
if($reply) {
$store->{$f->id}->replies = $store->{$f->id}->replies ?? (object)[];
$store->{$f->id}->replies->{$reply->id} = $reply;
}
I got this result and i want extraction first image from folder clear just the first
Example of the result
http://i.i.com.com/cnwk.1d/i/tim/2012/07/12/Les_Horribles_Cernettes_in_1992_620x350.jpg
http://i.i.com.com/cnwk.1d/i/tim/2012/07/03/IBM-350-publicdomain_220x157.jpg
http://cbsdigitalmedia.112.2o7.net/b/ss/cbscbsnewscomatlantisuat/1/H.21--NS.png
http://dw.com.com/clear/c.gif
http://i.i.com.com/cnwk.1d/i/tim/2012/07/03/IBM-350-publicdomain_220x157.jpg
http://dw.com.com/clear/test2.gif
http://cbsdigitalmedia.112.2o7.net/b/ss/cbscbsnewscomatlantisuat/1/H.21--NS.png
http://dw.com.com/clear/test.gif
The image i want
http://dw.com.com/clear/c.gif
OK, so I was actually quite intrigued by your question.. So I came up with a little something...
$firstFile;
//This is the array with your URL values
$imgUrls[0] = "http://i.i.com.com/cnwk.1d/i/tim/2012/07/12/Les_Horribles_Cernettes_in_1992_620x350.jpg";
$imgUrls[1] = "http://i.i.com.com/cnwk.1d/i/tim/2012/07/03/IBM-350-publicdomain_220x157.jpg";
$imgUrls[2] = "http://cbsdigitalmedia.112.2o7.net/b/ss/cbscbsnewscomatlantisuat/1/H.21--NS.png";
$imgUrls[3] = "http://dw.com.com/clear/c.gif";
$imgUrls[4] = "http://i.i.com.com/cnwk.1d/i/tim/2012/07/03/IBM-350-publicdomain_220x157.jpg";
$imgUrls[5] = "http://dw.com.com/clear/test2.gif";
$imgUrls[6] = "http://cbsdigitalmedia.112.2o7.net/b/ss/cbscbsnewscomatlantisuat/1/H.21--NS.png";
$imgUrls[7] = "http://dw.com.com/clear/test.gif";
//This foreach loop goes through the array and checks the containing directory
foreach($imgUrls as $value){
$urlParts = explode("/",$value);
if($urlParts[count($urlParts)-2] == "clear"){
$firstFile = $value;
break;
}
}
//After setting $firstFile as the Image URL, echo it out.
echo $firstFile;
TL;DR
I have this data: var_export and print_r.
And I need to narrow it down to: http://pastebin.com/EqwgpgAP ($data['Stock Information:'][0][0]);
How would one achieve it? (dynamically)
I'm working with vTiger 5.4.0 CRM and am looking to implement a function that would return a particular field information based on search criteria.
Well, vTiger is pretty weakly written system, looks and feels old, everything comes out from hundreds of tables with multiple joins (that's actually not that bad) etc., but job is job.
The need arose from getting usageunit picklist from Products module, Stock Information block.
Since there is no such function as getField();, I am looking forward to filter it out from Blocks, that is actually gathering the information about fields also.
getBlocks(); then calls something close to getFields();, that again something close to getValues(); and so on.
So...
$focus = new $currentModule(); // Products
$displayView = getView($focus->mode);
$productsBlocks = getBlocks($currentModule, $displayView, $focus->mode, $focus->column_fields); // in theory, $focus->column_fields should/could be narrowed down to my specific field, but vTiger doesn't work that way
echo "<pre>"; print_r($productsBlocks); echo "</pre>"; // = http://pastebin.com/3iTDUUgw (huge dump)
As you can see, the array under the key [Stock Information:], that actually comes out from translations (yada, yada...), under [0][0] contains information for usageunit.
Now, I was trying to array_filter(); the data out from there, but only thing I've managed to get is $productsBlocks stripped down to only contain [Stock Information:] with all the data:
$getUsageUnit = function($value) use (&$getUsageUnit) {
if(is_array($value)) return array_filter($value, $getUsageUnit);
if($value == 'usageunit') return true;
};
$productsUsageUnit = array_filter($productsBlocks, $getUsageUnit);
echo "<pre>"; print_r($productsUsageUnit); echo "</pre>"; // = http://pastebin.com/LU6VRC4h (not that huge of a dump)
And, the result I'm looking forward to is http://pastebin.com/EqwgpgAP, that I've manually got by print_r($productsUsageUnit['Stock Information:'][0][0]);.
How do I achieve this? (dynamically...)
function helper($data, $query) {
$result = array();
$search = function ($data, &$stack) use(&$search, $query) {
foreach ($data as $entry) {
if (is_array($entry) && $search($entry, $stack) || $entry === $query) {
$stack[] = $entry;
return true;
}
}
return false;
};
foreach ($data as $sub) {
$parentStack = array();
if ($search($sub, $parentStack)) {
$result[] = $parentStack[sizeof($parentStack) - 2];
}
}
return $result;
}
$node = helper($data, 'usageunit');
print_r($node);
In my app I have a textarea, which my users are meant to enter data in the format:
Forename, Surname, YYYY-MM-DD, Company
Forename, Surname, YYYY-MM-DD, Company
on each line. My intention is to then loop through each row, exploding at the comma and trimming any white space.
I then need to pass the exploded array in to an associative array. I'm doing this manually at the moment, on the assumption that the user has entered the data in the correct order and format; which does work, but does rely on the user not messing things up.
What would you suggest as being a better way of doing this? I think the way I'm checking each index to see if it's empty or not seems rather clunky, as well as error prone.
Any suggestions or things to consider?
/************************************
* sample data from textarea:
* Name, Surname, 1980-02-22, Company
* Foo, Bar, 1970-05-12, Baz
************************************/
$data = preg_split('/\r\n|\n/', $_POST['data'],
-1, PREG_SPLIT_NO_EMPTY);
$item = array();
// loop through the data
foreach($data as $row) :
// trim and explode each line in to an array
$item[] = array_map('trim', explode(',', $row));
endforeach;
$k=0;
foreach($item as $user) :
$processed_data[$k]['first_name'] = !empty($user[0]) ? $user[0] : NULL;
$processed_data[$k]['last_name'] = !empty($user[1]) ? $user[1] : NULL;
if(!empty($user[2])) :
$dob = strtotime($user[2]);
if($dob) {
$processed_data[$k]['dob'] = $user[2];
} else {
$processed_data[$k]['dob'] = NULL;
}
else:
$processed_data[$k]['dob'] = NULL;
endif;
$processed_data[$k]['company'] = !empty($user[3]) ? $user[3] : NULL;
$k++;
endforeach;
// print_r($processed_data);
you are from the old school :)
Well, as you say above you expect the user to enter the data correctly in the text area. Well if your app is working currently in a robust system don't touch it, but otherwise you should consider to add different parameters in your post request (one for each filed you want to explode)...
you can do like this to solve the problem you have now:
// The algorithm below believe user send data correctly
// Forename, Surname, YYYY-MM-DD, Company
$names = array('first_name', 'last_name', 'dob', 'company_name');
$lines = explode("\n", $_POST['data']);
$result = array();
foreach ($lines as $ line)
{
$exploded_line = explode(",", $line);
$row = array();
foreach ($exploded_line as $key=>$item) { $row[$names[$key]]= trim($item); }
$result[]=$row;
}
// Now in result there is an array like this
// result[0][first_name]
// result[0][last_name]
// result[0][dob]
// result[0][company_name]
// result[1][first_name]
// [ ... ]
You can encapsulate the parsing and the validation into classes of it's own. Additionally you could do the same for the datastructure holding the tabular data.
class TableParser
{
private $string;
public function __construct($string)
{
$this->string = (string) $string;
}
public function parse()
{
$buffer = $this->string;
$rows = explode("\n", $buffer);
$rows = array_map('trim', $rows);
return $this->parseRows($rows);
}
private function parseRows(array $rows)
{
foreach($rows as &$row)
{
$row = $this->parseRow($row);
}
return $rows;
}
private function parseRow($row)
{
$keys = array('forename', 'surname', 'date', 'company');
$keyCount = count($keys)
$row = explode(',', $row, $keyCount);
if (count($row) != $keyCount)
{
throw new InvalidArgumentException('A row must have 4 columns.');
}
$row = array_map('trim', $row);
$row = array_combine($keys, $row);
return $row;
}
}
This parser is still quite rough. You can improve it over time, e.g. providing better error handling, given information which line failed and such. Such a component can then be easier integrated into your normal application flow as you can return that information back to the user so to enable her to make changes to the input.
Additionally you can put apart the validation into a second class and only do the exploding / trimming in the parser, but validation against count, specifying the array keys as well as validating the date format / value in the second class to keep things more apart.