Laravel / Excel Parsing / RegExp not firing - php

I'm using Laravel and the using MaatWebsite/Laravel-Excel module to read in an Excel file, processes rows, assign variables and put into a database.
Because the input files vary, slightly (different column orders, not always the same number of columns), I've put together this code that tries to make those details unnecessary.
Note: this script works most of the time (other files) and is currently processing a particular file (structure below) but the values are somehow getting assigned improperly.
I'm showing the relevant portions of my code:
Excel::filter('chunk')->load($filename)->chunk(50, function($results) {
foreach($rows as $row) {
foreach(array_keys($row) as $k) {
switch (1) {
case preg_match('/attended/i', $k):
break;
// many other cases
case (preg_match('/morning/i', $k)):
// dd($row[$k]); // doesn't run here either
if($row[$k] !== null){
$morning = $row[$k];
dd($row[$k]);
}
break;
case (preg_match('/afternoon/i', $k)):
if($row[$k] !== null ){
$afternoon = $row[$k];
dd($row[$k]);
}
break;
}
// processing of the row
}
});
I have slipped lines of dd($something); into places to prove that what I'm expecting to see is, in fact, being seen.
The following is the array that I get by looking at the first row of data in the file:
array:49 [▼
"attended" => "Yes"
"salutation" => "Mr"
"first_name" => "First"
"last_name" => "Last"
"suffix" => null
"email" => "email#address.com"
"ticket" => "Non Member - Friday Only"
"seats" => 1.0
"registered_on" => "3/14/2017"
"registered_by" => "Full Name"
"payment" => "At the Door"
"confirmation_code" => "PRO - 60240/1"
"payment_received" => "Yes"
"status" => "Active"
"cancelled_on" => null
"cost" => 0.0
"cc_charge" => 0.0
"handling_fee" => 0.0
"your_amount" => 0.0
"disc_code" => "Sponsor"
"disc_description" => "Sponsor"
"disc_amount" => -375.0
"morning_keynote_friday_815_am_945_am" => null
"breakout_1_friday_1000_am_1130_am" => null
"breakout_2_friday_130_pm_300_pm" => null
"breakout_3_friday_315_pm_415_pm" => null
"networking_and_cocktail_session_500_pm_600_pm" => null
"friday_evening_dinner_with_speaker_600_pm_830_pm" => null
"breakout_1_saturday_800_am_900_am" => null
"breakout_2_saturday_915_am_1215_pm" => null
"breakout_3_saturday_215_pm_445_pm" => null
"please_list_any_dietary_requirements_gluten_free_lactose_vegetarian_etc" => null
"would_you_like_your_name_and_company_name_added_to_the_roster_made_available_to_participants" => "Yes"
"what_is_your_company_name" => null
"select_your_chapter_affiliation" => "Not a current member"
"please_list_any_special_arrangements_required_to_attend_this_event_wheelchair_access_etc" => null
"do_not_use_2" => null
"do_not_use_3" => null
"do_not_use" => null
"do_not_use_4" => null
"do_not_use_5" => null
"what_morning_session_are_you_attending" => null
"what_afternoon_session_are_you_attending_if_in_all_day_class_please_select_the_same" => null
"which_morning_session_are_you_attending2" => null
"which_afternoon_session_are_you_attending2" => null
"what_morning_session_are_you_attending3" => "Session Name I want to capture"
"what_afternoon_session_are_you_attending3" => "Another Session Name I want to capture"
Because of the inefficient way that the data was captured, I'm looking for a "morning" value that could appear in any of those final 3 values and I also want an "afternoon" value.
I'm finding that, though clearly a regexp should trigger for morning and/or afternoon, the dd() statements I've inserted above do not ever get triggered.
Any insight the mistake occurring here?

Related

Laravel updateOrcreate missing value

I do parsing matches for DotA 2. Through a third-party API, I get current, future and past matches. But the problem how i understand, it's updateOrCreate function does not work. When parsing starts, it saves the values, but does not update the current ones. Here is an example of the answer that I get https://pastebin.com/KCcG6rJc, in this answer there is what teams are playing now, there are match_id of teams, if the teams are competing with each other, this value is the same. Using the example of this parsing result, I received the following record in the Database:
The maches table, the match_id value got there - 560004, that's right. But in the teams table, where these commands are indicated, match_id is null.
At my parser i has this code:
foreach ($live_matches as $live) {
if ($live->tournament_id != $tournament->id) {
continue;
}
$filtered_matches[] = $live;
foreach ($teams as &$team) {
if (false !== strpos($live->slug, $team->slug)) {
$team->match_id = $live->id;
$logo = $team->image_url;
var_dump($team);
exit;
}
}
}
var_dump($team); exit; say me:
object(stdClass)#1222 (8) {
["acronym"]=>
string(8) "ThunderP"
["id"]=>
int(2671)
["image_url"]=>
string(93) "https://cdn.pandascore.co/images/team/image/2671/87033C79D6D1A70A66941BC8649EA5988D74582C.png"
["location"]=>
string(2) "PE"
["modified_at"]=>
string(20) "2020-04-30T01:51:51Z"
["name"]=>
string(16) "Thunder Predator"
["slug"]=>
string(16) "thunder-predator"
["match_id"]=>
int(560004)
}
i.e. I get match_id, but at database it's not add.
And here is my full function, which update or create:
public function saveUpdate(int $tournament_id, array $tournament_teams, string $full_name, array $matches)
{
$tournament = Tournament::updateOrCreate([
'tournament_id' => $tournament_id,
'league_name' => $full_name
]);
foreach ($matches as $match) {
if ($match->status == 'not_started') {
$status = 0;
}
if ($match->status == 'running') {
$status = 1;
}
if ($match->status == 'finished') {
$status = 2;
}
$team = Tournament_teams::where('team_id', $match->winner_id)->first();
Tournament_matches::updateOrCreate([
'name' => $match->name,
'started_at' => Carbon::parse("$match->begin_at,")->setTimezone('Europe/Berlin'),
'ended_at' => $match->end_at,
'winner_id' => $team->id ?? null,
'status' => $status,
'match_id' => $match->id,
'live' => $match->live_url,
]);
}
foreach ($tournament_teams as $team) {
Tournament_teams::updateOrCreate([
'tournaments_id' => $tournament->id,
'team' => $team->name,
'slug' => $team->slug,
'logo' => $team->image_url,
'team_id' => $team->id,
], [
'match_id' => $team->match_id ?? null,
]);
}
}
For example, if I delete 1 column value from the teams table and start parsing, then the value in this column will not be created. That is, it creates data, but does not update.
And now teams with match_id 560334 are playing and the tournament_teams table doesn’t have such match_id, I searched for playing teams by name and found that there are 1 of the playing teams in the database 3 times in a row. That is, one record has match_id = null, the others of the same match_id commands have old ones. For some reason, the data on the current is not updated and empty values are received in the database, although 50% of the values are. Here is screenshot with highlighted commands for which for example data is not updated:
Where could my mistake be? Why does var_dump pass me match_id, but this value does not get into the database? Where could my mistake be? I use Laravel 5.1. If you need to clarify any details - ask, thank you for your help.
You are using wrongly the updateOrCreate() method.
As the documentation says:
You may also come across situations where you want to update an existing model or create a new model if none exists.
// If there's a flight from Oakland to San Diego, set the price to $99.
// If no matching model exists, create one.
$flight = App\Flight::updateOrCreate(
['departure' => 'Oakland', 'destination' => 'San Diego'],
['price' => 99, 'discounted' => 1]
);
If I understood well your problem, you are doing it in the opposite way:
Tournament_teams::updateOrCreate([
'match_id' => $team->match_id ?? null,
], [
'tournaments_id' => $tournament->id,
'team' => $team->name,
'slug' => $team->slug,
'logo' => $team->image_url,
'team_id' => $team->id,
]);
Also, for this you don't need to use updateOrCreate() but firstOrCreate() for example:
$tournament = Tournament::firstOrCreate([
'tournament_id' => $tournament_id,
'league_name' => $full_name
]);
PS: If it is possible, I recommend you to use a newer Laravel version.

How to make some checkbox options selected by default in ChoiceType Symfony Form Builder?

I am building a checkbox form that has 4 possible choices.
What would be the method of making 2 and 3 (Green and Blue)
checked by default but leaving the remaining two items unchecked
by default?
I believe the "data" item of the $builder array might
be the correct answer, but I am not sure how...
Any help would be appreciated! Thank you!
$builder->add(
"What color do you like?",
ChoiceType::class,
[
'label' => "What color do you like?",
'choices' => [1 => "Red", 2 => "Green", 3 => "Blue", 4=>"Orange"],
'expanded' => true,
'multiple' => true,
'required' => true,
'help' => "Pick as many as you like!",
]
);
I expect that I should be able to code in something like "2=1,3=1" somewhere to indicate that both of my choices should be checked by default, but it is not clear how I would indicate that those two choices should be checked by default.
First off, the array passed to choices should be in the form label => value, so your values and keys have to be flipped.
Then to add attributes to specific choices you can use the choice_attr option:
'choice_attr' => function($opt, $k, $v) {
if ($v == '2' || $v == '3') {
return ['checked' => 'checked'];
}
},
ChoiceType functionality can sometimes be (or seem) quite weird and can be hard to work with. It took me some time to figure out how to set default values. Here is how I did it.
DaysType.php
->add('days', ChoiceType::class, [
'multiple' => true,
'expanded' => true,
'choices' => [
"Mo" => "Mo",
"Tu" => "Tu",
"We" => "We",
"Th" => "Th",
"Fr" => "Fr",
"Sa" => "Sa",
"Su" => "Su",
],
])
Be aware that the first "Mo" before the => is the title/label you will see next to your checkbox. Like you can see in my picture.
The "Mo" after the => is the data that will be send back to your controller once the user submits the form. Its also the value you can see on your input field its value attribute.
Now how to make them checked by default:
DaysController.php
$days = new Days();
// Used to set the default selected values. Options are: Ma, Di, Wo, Do, Vr, Za, Zo.
$days->setDays([
"Mo", "Tu", "We", "Sa"
]);
// Create form
$form = $this->createForm(DaysType::class, $days);
$form->handleRequest($request);
// ... render page etc.
So now by default Mo, Tu, We and Sa are checked.
This is how the data looks like when the user submits the form without changing the checks:
-days: array:4 [▼
0 => "Mo"
1 => "Tu"
2 => "We"
3 => "Sa"
]
I do not know how to get an array returned with all possibilities. And with true/false but this works for me. I will probably json_encode the array and save it like that in the database.

Laravel 5.2 Eloquent column name conflict

I have the following method in my user class:
/**
* Get all organisations for user (if owner)
*
* #param
*/
public function getOrganisationsOwned()
{
// If the user is owner of any one or many organisations then return this list
return Organisation::leftJoin('subscription_plans', 'organisations.subscription_plan_id', '=', 'subscription_plans.id')
->where('organisations.owner_id', '=', $this->id)
->select('organisations.*', 'subscription_plans.*')
->get();
}
The method essentially queries and joins two tables. Each table has a column called title.
The output from the above generates the rows as desired with the right info, but returns only one title column, from the right table (subscription_plans) but not the column title from the left table (organisations). I also notice it is dropping the timestamps from one table also, as these are of the same column name.
I understood that
->select('organisations.*', 'subscription_plans.*')
would make the query return both columns. What am I missing? Happy new year!
PS: below is a copy of the dd() contents for the collection, with title only appearing once.
#attributes: array:44 [▼
"id" => 1
"title" => "Monthly Subscription"
"address_1" => "34 Florence Street"
"address_2" => ""
"suburb" => "Hornsby"
"state" => "NSW"
"postcode" => "2077"
"country_id" => 12
"currency_id" => 12
"time_zone_id" => 109
"phone" => "0392144497"
"website" => "http://www.Tremblay.com/est-aspernatur-et-ut-provident.html"
"business_id" => "82297955560"
"tax_registration" => 1
"logo" => "8aa656de-2bc2-4e14-dddd-e02fbcd2b76f"
"quote_terms_days" => 14
"invoice_terms_days" => 14
"fiscal_start_id" => 7
"industry_id" => 4
"company_size_id" => 3
"date_format_id" => 2
"date_time_format_id" => 20
"owner_id" => 1
"gateway_id" => "1"
"gateway_username" => "xxx"
"gateway_password" => "xxx"
"gateway_signature" => "xxx"
"gateway_accepted_cards" => "[1, 2, 3]"
"subscription_plan_id" => 1
"trial_ends_at" => "2015-11-07"
"grace_ends_at" => "2016-02-10"
"subscription_ends_at" => "2016-01-11"
"latitude" => "-33.70433500"
"longitude" => "151.10161900"
"registration" => "done"
"deleted_at" => null
"created_at" => "2016-01-01 14:59:47"
"updated_at" => "2016-01-01 14:59:47"
"amount" => "9.09"
"gst" => "0.91"
"gst_amount" => "10.00"
"billing_cycle" => "MONTH"
"trial_period_days" => 30
"grace_period_days" => 30
]
The "missing" title column contains:
'title' => 'ABC Electrical'
There is some misunderstanding as to what I suggested: instead of using *, you could list the field names one by one and provide aliases for the 2 title fields. This does not mean that you should keep the 'organisations.*', 'subscription_plans.*' and add the 2 title fields to the select list with aliases because this way you select both title fields twice, wasting memory and processor time.
You should not include the * forms in the select list, but list each field individually, with the 2 title fields marked with aliases:
public function getOrganisationsOwned()
{
// If the user is owner of any one or many organisations then return this list
return Organisation::leftJoin('subscription_plans', 'organisations.subscription_plan_id', '=', 'subscription_plans.id')
->where('organisations.owner_id', '=', $this->id)
->select('organisations.id', 'organisations.title AS org_title', ..., 'subscription_plans.subscription_plan_id', 'subscription_plans.title AS plan_title', ...)
->get();
}
Yeah, I know, listing so many field one by one is a pain in the ***, however, each field is retrieved once and only once, at it is clear that you are fetching what is needed.
#Shadow's suggestion worked, although you should note, this method allows you to select all the fields, but only "rename" columns or rather alias them so you can still access the proper value when using joins. The old value will still be overridden, but now you can use your alias with the correct value.
The below is now working:
public function getOrganisationsOwned()
{
// If the user is owner of any one or many organisations then return this list
return Organisation::leftJoin('subscription_plans', 'organisations.subscription_plan_id', '=', 'subscription_plans.id')
->where('organisations.owner_id', '=', $this->id)
->select('organisations.*', 'organisations.title AS org_title', 'subscription_plans.*', 'subscription_plans.title AS plan_title')
->get();
}

Yodlee AddSiteAccount and GetItemSummaries don't return expected results

So, we've been using the Yodlee RESTful API with a PHP implementation, but we're getting an inconsistent issue when adding site accounts, which results in further issues with item summaries returning "Api execution successful. No data found for the API."
Sometimes, only sometimes, when getting a response from the "SiteAccountManagement/addSiteAccount1" Yodlee API call, the first time it's called, the return data looks like so:
...
siteRefreshInfo => object(stdClass) {
siteRefreshStatus => object(stdClass) {
siteRefreshStatusId => (int) 1
siteRefreshStatus => 'REFRESH_TRIGGERED'
}
siteRefreshMode => object(stdClass) {
refreshModeId => (int) 2
refreshMode => 'NORMAL'
}
updateInitTime => (int) 1405406124
nextUpdate => (int) 1405407024
code => (int) 801
suggestedFlow => object(stdClass) {
suggestedFlowId => (int) 2
suggestedFlow => 'REFRESH'
}
noOfRetry => (int) 0
}
...
Which will later result in the "DataService/getItemSummariesForSite" API call returning "Api execution successful. No data found for the API.".
However, upon a making a new call to these API functions (by just refreshing the page), the return data for "SiteAccountManagement/addSiteAccount1" will look like this:
...
siteRefreshInfo => object(stdClass) {
siteRefreshStatus => object(stdClass) {
siteRefreshStatusId => (int) 10
siteRefreshStatus => 'SITE_CANNOT_BE_REFRESHED'
}
siteRefreshMode => object(stdClass) {
refreshModeId => (int) 2
refreshMode => 'NORMAL'
}
updateInitTime => (int) 0
nextUpdate => (int) 1405575826
code => (int) 0
suggestedFlow => object(stdClass) {
suggestedFlowId => (int) 1
suggestedFlow => 'NOT_REFRESHABLE'
}
itemRefreshInfo => array(
(int) 0 => object(stdClass) {
memItemId => (int) 11529165
itemSuggestedFlow => object(stdClass) {
suggestedFlowId => (int) 1
suggestedFlow => 'NOT_REFRESHABLE'
}
itemSuggestedFlowReason => object(stdClass) {
suggestedFlowReasonId => (int) 5
suggestedFlowReason => 'RECENTLY_REFRESHED'
}
errorCode => (int) 0
retryCount => (int) 0
}
)
noOfRetry => (int) 0
}
...
What could be causing the addition of sites to be returning a code 801, and what does said code represent?
We've followed the recommended Yodlee API procedures in the quickstart guide, and most of the time, things are working well.
Actually the status code 801 represents
"Request In Progress: Please wait while we update your account."
So when you refresh your page for the next time the refresh of the add site account might get completed so that you will get the list of added account details.
Refer the link below for the representation of different status codes.
Error Codes

making sure a generated array key is unique

I have this array
$array = array(
"one" => "bar",
"two" => "21",
"three" => "22",
"four" => "25",
"five" => array(
"xxxxxxxxxxxxxxxxxx" => array(
"ar1" => "food",
"ar2" => "dr",
"ar3" => "ch",
"ar4" => "ju"
),
"yyyyyyyyyyyyyyyyyyyy" => array(
"ar1" => "food",
"ar2" => "dr",
"ar3" => "ch",
"ar4" => "ju"
)),
"six" => "et",
"seven" => "op",
"eight" => "hjs",
"nine" => array(
"1" => array(
"ar5" => "food",
"ar87" => "dr",
"ar21" => "ch",
"ar443" => "ju"
),
"2" => array(
"73" => "food",
"82" => "dr",
"90" => "ch",
"2123" => "ju"
)),
"ten" => "bar",
"eleven" => "bar",
"twelve" => "bar"
);
and i want to make sure that every new array added must have a unique array key.To do that,i first get all the keys of the others i.e $array['nine'] in my case then run a function until a unique key is found.
To add a new array to $array['nine'] and to get all the keys in nine
$keyedd = array_keys($array['nine']);
$appendThis[''.unique_array_key($keyedd).''] = array(
"73" => "nitrous",
"82" => "oxide",
"90" => "laughing",
"2123" => "gas"
);
$array['nine'] = $array['nine'] + $appendThis;
This is the function
function unique_array_key($the_array){
$r = rand();
if (array_key_exists("$r", $the_array)) {
unique_array_key($the_array);
}
else if(!array_key_exists("$r", $the_array)) {
echo $r;
}
}
Once i run this
[nine] => Array
(
[1] => Array
(
[ar5] => food
[ar87] => dr
[ar21] => ch
[ar443] => ju
)
[2] => Array
(
[73] => food
[82] => dr
[90] => ch
[2123] => ju
)
[] => Array
(
[73] => nitrous
[82] => oxide
[90] => laughing
[2123] => gas
)
)
the newly added array do not have an array key.However,unique_array_key($keyedd); on its own seems to work fine.Why is the function not adding a unique key?.
I would prefer internal PHP functionality for unique key generation:
$appendThis[uniqid()] = array(
"73" => "nitrous",
"82" => "oxide",
"90" => "laughing",
"2123" => "gas"
);
No needs to reinvent wheel. Check documentation for uniqid() function.
Update
If you have web-cluster running your application simultaneously on several hosts with shared data storage, and more than 10000 ID generations in one second just use:
uniqid(php_uname('n'), true)
for ID generation. Your solution with rand() ID generation have only mt_getrandmax() variations. Usually it is 2147483647. With 10000 ID generations in sec you'll get exceed available ID's limit in 2.4 days, and your code will run in infinite loop because every key check in array will have true result and recursively call new ID generation again and again.
Also, your solution make the application performance dependent on data amount. Than more data you'll have, than higher chance of additional loops for ID generation because of duplicates. For example, if you'll have N already stored arrays with unique ID's, there is a chance next ID will be generated for N+1 cycles.
If your project not highload, will be enough uniqid() or uniqid('', true) if you need additional entropy.
Replace echo $r; with return $r;:
function unique_array_key($the_array){
$r = rand();
if (array_key_exists("$r", $the_array)) {
return unique_array_key($the_array);
} else {
return $r;
}
}
}

Categories