问:
How to create a proper merge commit in git which is also squashed
I'm trying to solve a problem with my git history.

I have two branches, lets call them a and b, a is the source branch for my repository, and b was branched off it. Many merged pull requests (a mix of merge commits, and squashed commits) happen to a, and b is not rebased, neither are these PRs re-opened against b. In order to update b, I (naively) resort to cherry-picking the merge commits from a that are applicable to b.

Over time as the code is tested and approved in a, b is now equal to a, with an empty diff, but the history shows, (as expected) a divergence in commits. (b is seen as many commits ahead of a in Github).

I would like to eliminate this divergence, if I perform merge commits from either one into the other, I get a long string of commits with no changes (except in some cases on Github where it gets confused), which would pollute the history of either branch if allowed onto them.

e.g. git merge a from b or git merge b from a shows a long string of commits in the log. (Edit: this is with --no-ff).

If I perform a squash, I get a nice message listing those commits with no changes.

e.g. git merge a --squash from b or git merge b --squash from a requires git commit --allow-empty.

But that does not prevent the "this branch is ahead/behind" situation.

So my question is how do I produce a single commit (can be in either or both branches) to prevent the "ahead/behind" situation.

Edit: This is mainly for ease of tracing whats happened on Github, I know how git works and know how to do this by destroying the history of one or the other branches by force pushing, but I'm trying to preserve both in a way that is easily introspectable.

答:
The only real answer here is that you don't.

What Git has—what it stores—is a graph of commits.  Each commit has its own unique hash ID, never to be used by any other commit in this or any other repository.1  Each commit also points (backwards) to its parent commit(s); this is what forms the graph.

That is, given a linear chain of commits, using uppercase letters to stand in for their actual big ugly hash IDs, we can draw them like this:

```<code>... <-F <-G <-H ...
</code>```

The commit whose hash is H contains the hash ID of commit G, so that H points to G.  The commit whose hash is G contains the hash ID of commit F: G points to F.  This goes on all the way back to an initial commit, that doesn't point backwards any further.  (Usually there is just one such commit, the root commit, though Git permits multiple root commits.)

A branch name like master or develop or whatever just points to one specific commit.  That commit is the last commit in that branch.  In situations like this:

```<code>          I--J   <-- branch1
         /
...--G--H
         \
          K--L   <-- branch2
</code>```

we need two branch names to find all the commits, because Git works by having a branch name point to the last commit that we'll call "part of the branch".  Commit J is the last commit on branch1.  J points back to I, which points back to H.  Meanwhile the name branch2 points to commit L, which points back to K, which points back to H.  Note that commit H is on both branches (as are commits G and earlier).

If H has a name pointing to it:

```<code>          I--J   <-- branch1
         /
...--G--H   <-- master
         \
          K--L   <-- branch2
</code>```

that's fine: commit H i the last commit of branch master, and H is on all three branches.

Commits are called reachable from some point if, by following the internal backwards-pointing arrows, we can walk from that point (whatever it is) to the commit we're calling reachable.  So H is reachable from all three branches, but I and J are reachable only from branch1.

When Git says that one branch name is "ahead of" another, this is because there are commits that are only reached from that one branch name.  Hence branch1 is 2 commits ahead of master, and two commits ahead of branch2.  master is not at all ahead of either of the other names, but branch2 is 2 commits ahead of both master and branch1.

A regular git merge operation combines changes and makes a new commit, and the new commit points back to both earlier commits:

```<code>          I--J
         /    \
...--G--H      M   <-- branch1 (HEAD)
         \    /
          K--L   <-- branch2
</code>```

The multiple backwards arrows coming out of M, pointing to both J and L, mean that branch1 is now three commits ahead of branch2: from branch1 we can reach commits M, J, and I, as well as L and K and of course H and earlier.  From branch2, we can reach L and K and H and earlier, but we cannot go forward from H to I.

Using git merge --squash, Git will make a new commit with the same content as the merge M, but instead of two backwards arrows, you get just one:

```<code>          I--J
         /    \
...--G--H      M   <-- branch1 (HEAD)
         \
          K--L   <-- branch2
</code>```

It is no longer possible to move from M to L, so branch2 remains two commits "ahead of" branch1.

Note, however, that commit M has anything good from K and L in it.  So what you can do is simply delete the name branch2 entirely:

```<code>...--G--H--I--J--M   <-- branch1 (HEAD)
         \
          K--L   [abandoned]
</code>```

If there is no name by which you can find commit L, you'll never see it again.  Since commit L was the method you used to find commit K, you will never see that one again either.  They remain in your Git repository for a while—exactly how long is hard to predict as it depends on both any hidden (reflog-only) names that still find commit L, and on how soon the maintenance git gc command get around to sweeping up unused commits and really removing them.  But deleting the name branch2 deletes the branch2 reflog, so the only reflog that probably still remembers L's raw hash ID is that for HEAD.

(If you have other branch and/or tag names that remember commits L and/or K, they'll still be findable that way, and won't ever be collected by the git gc garbage collector.)

Usually, after git merge --squash, the right thing to do is to delete the other branch name, and totally forget that those commits ever existed.

1Technically, any Git repositories that never "meet" could re-use IDs from each other harmlessly.  In practice, they just don't anyway.  The chance of one Git object having the same hash ID as some Git object is, on its own, one in 2160.  Because of the Birthday paradox, this chance rises pretty fast as the number of objects increases, but it's still on the order of 1 in 10-17 when you have fewer than many trillions of objects.  See also Git hash duplicates.

Body:
The only real answer here is that you don't.

What Git has—what it stores—is a graph of commits.  Each commit has its own unique hash ID, never to be used by any other commit in this or any other repository.1  Each commit also points (backwards) to its parent commit(s); this is what forms the graph.

That is, given a linear chain of commits, using uppercase letters to stand in for their actual big ugly hash IDs, we can draw them like this:

... <-F <-G <-H ...

The commit whose hash is H contains the hash ID of commit G, so that H points to G.  The commit whose hash is G contains the hash ID of commit F: G points to F.  This goes on all the way back to an initial commit, that doesn't point backwards any further.  (Usually there is just one such commit, the root commit, though Git permits multiple root commits.)

A branch name like master or develop or whatever just points to one specific commit.  That commit is the last commit in that branch.  In situations like this:

          I--J   <-- branch1
         /
...--G--H
         \
          K--L   <-- branch2

we need two branch names to find all the commits, because Git works by having a branch name point to the last commit that we'll call "part of the branch".  Commit J is the last commit on branch1.  J points back to I, which points back to H.  Meanwhile the name branch2 points to commit L, which points back to K, which points back to H.  Note that commit H is on both branches (as are commits G and earlier).

If H has a name pointing to it:

          I--J   <-- branch1
         /
...--G--H   <-- master
         \
          K--L   <-- branch2

that's fine: commit H i the last commit of branch master, and H is on all three branches.

Commits are called reachable from some point if, by following the internal backwards-pointing arrows, we can walk from that point (whatever it is) to the commit we're calling reachable.  So H is reachable from all three branches, but I and J are reachable only from branch1.

When Git says that one branch name is "ahead of" another, this is because there are commits that are only reached from that one branch name.  Hence branch1 is 2 commits ahead of master, and two commits ahead of branch2.  master is not at all ahead of either of the other names, but branch2 is 2 commits ahead of both master and branch1.

A regular git merge operation combines changes and makes a new commit, and the new commit points back to both earlier commits:

          I--J
         /    \
...--G--H      M   <-- branch1 (HEAD)
         \    /
          K--L   <-- branch2

The multiple backwards arrows coming out of M, pointing to both J and L, mean that branch1 is now three commits ahead of branch2: from branch1 we can reach commits M, J, and I, as well as L and K and of course H and earlier.  From branch2, we can reach L and K and H and earlier, but we cannot go forward from H to I.

Using git merge --squash, Git will make a new commit with the same content as the merge M, but instead of two backwards arrows, you get just one:

          I--J
         /    \
...--G--H      M   <-- branch1 (HEAD)
         \
          K--L   <-- branch2

It is no longer possible to move from M to L, so branch2 remains two commits "ahead of" branch1.

Note, however, that commit M has anything good from K and L in it.  So what you can do is simply delete the name branch2 entirely:

...--G--H--I--J--M   <-- branch1 (HEAD)
         \
          K--L   [abandoned]

If there is no name by which you can find commit L, you'll never see it again.  Since commit L was the method you used to find commit K, you will never see that one again either.  They remain in your Git repository for a while—exactly how long is hard to predict as it depends on both any hidden (reflog-only) names that still find commit L, and on how soon the maintenance git gc command get around to sweeping up unused commits and really removing them.  But deleting the name branch2 deletes the branch2 reflog, so the only reflog that probably still remembers L's raw hash ID is that for HEAD.

(If you have other branch and/or tag names that remember commits L and/or K, they'll still be findable that way, and won't ever be collected by the git gc garbage collector.)

Usually, after git merge --squash, the right thing to do is to delete the other branch name, and totally forget that those commits ever existed.

1Technically, any Git repositories that never "meet" could re-use IDs from each other harmlessly.  In practice, they just don't anyway.  The chance of one Git object having the same hash ID as some Git object is, on its own, one in 2160.  Because of the Birthday paradox, this chance rises pretty fast as the number of objects increases, but it's still on the order of 1 in 10-17 when you have fewer than many trillions of objects.  See also Git hash duplicates.


来源: stackexchange

问:
FLTK: which button is pressed - passing a number to a button's callback (lambda)
I have N buttons on an FLTK window. I'd like to know which button has been pressed by the user. How can I pass a number to each button's lambda callback function? So far, I tried this:

```<code>int main(int argc, char **argv) {
  Fl_Window *w_main = new Fl_Window(640, 480);

  std::vector<int> nums;
  for (int i = 0; i < 5; i++) {
    nums.push_back(i);

    Fl_Button *btn1 = new Fl_Button(50 * i, 0, 50, 50);
    char const *num = std::to_string(i).c_str();
    btn1->label(num);
    btn1->callback(
        [](Fl_Widget *w, void *data) { std::cout << "Clicked on: " << (int)data << std::endl; },
        &nums[i]);
  }
  w_main->show();
  return Fl::run();
}
</code>```

Unfortunately, I get random-like numbers on the output (I assume some random memory garbage interpreted as integers.)

Could you please help me find a solution? Thanks!

答:
When you register your callback:

```<code>btn1->callback(
        ...,
        &nums[i]);
</code>```

You are passing the address of nums[i] as your callback argument (as opposed to the value itself). So you need to interpret data as said address, and dereference it to access the underlying number.

That means:

```<code>btn1->callback(
        [](Fl_Widget *w, void *data) { std::cout << "Clicked on: " << *reinterpret_cast<int*>(data) << std::endl; },
        &nums[i]);
</code>```

The "random" numbers you see are anything but random. They represent the exact location in memory where your number is located. Explicitely converting an address into a numerical value is perfectly valid code, and that's exactly what you did.

ContentLicense: CC BY-SA 4.0

Body:
I have N buttons on an FLTK window. I'd like to know which button has been pressed by the user. How can I pass a number to each button's lambda callback function? So far, I tried this:

int main(int argc, char **argv) {
  Fl_Window *w_main = new Fl_Window(640, 480);

  std::vector<int> nums;
  for (int i = 0; i < 5; i++) {
    nums.push_back(i);

    Fl_Button *btn1 = new Fl_Button(50 * i, 0, 50, 50);
    char const *num = std::to_string(i).c_str();
    btn1->label(num);
    btn1->callback(
        [](Fl_Widget *w, void *data) { std::cout << "Clicked on: " << (int)data << std::endl; },
        &nums[i]);
  }
  w_main->show();
  return Fl::run();
}

Unfortunately, I get random-like numbers on the output (I assume some random memory garbage interpreted as integers.)

Could you please help me find a solution? Thanks!

Body:
When you register your callback:

btn1->callback(
        ...,
        &nums[i]);

You are passing the address of nums[i] as your callback argument (as opposed to the value itself). So you need to interpret data as said address, and dereference it to access the underlying number.

That means:

btn1->callback(
        [](Fl_Widget *w, void *data) { std::cout << "Clicked on: " << *reinterpret_cast<int*>(data) << std::endl; },
        &nums[i]);

The "random" numbers you see are anything but random. They represent the exact location in memory where your number is located. Explicitely converting an address into a numerical value is perfectly valid code, and that's exactly what you did.


问:
How to fix stripe payment in flutter
i have the issue on flutter_stripe_payment i am getting this error MissingPluginException (MissingPluginException(No implementation found for method setPublishableKey on channel stripe_payment))

i have trid on MainActivity extend from FlutterActivity to FlutterFragmentActivity.

i changing from minSdkVersion 16 to minSdkVersion 21 inside build.gradle in android > app

i added ext.kotlin_version = '1.2.71' inside build.gradle in Android folder

    import 'package:app/UiHelper/AppBarHelper.dart';
    import 'package:app/UiHelper/ColorHelper.dart';
    import 'package:flutter/cupertino.dart';
    import 'package:flutter/material.dart';
    import 'package:stripe_payment/stripe_payment.dart';

    class MenuBookingScreen extends StatelessWidget {
       @override
       Widget build(BuildContext context) {
        return DrawWidget();
      }
    }

    class _ViewState extends State<DrawWidget> {
      @override
      void initState() {
        super.initState();
        initAction();
        // this part throw error while hot reload
        StripeSource.setPublishableKey("mykey");
      }

      initAction() async {}

      @override
      Widget build(BuildContext context) {
        return Scaffold(
            appBar: AppBarHelper().appBarGenerator(context),
            backgroundColor: ColorHelper().appBackground,
            body: Material(
                color: ColorHelper().appBody, child: uIDomElement(context)));
      }

      Widget uIDomElement(BuildContext context) {
        var _size = MediaQuery.of(context).size;
        return Container(
          width: _size.width,
          child: RaisedButton(
            color: Colors.indigo,
            textColor: Colors.white,
            disabledColor: Colors.grey,
            disabledTextColor: Colors.black,
            padding: EdgeInsets.all(13),
            splashColor: Colors.blueAccent,
            shape: RoundedRectangleBorder(borderRadius:BorderRadius.circular(5.0)),
            onPressed: () {
              // Add Card
            },
            child: Row(
              children: <Widget>[
                Icon(Icons.credit_card),
                SizedBox(
                  width: 15,
                ),
                Text("Add Card")
              ],
            ),
          ),
        );
      }
    }

    class DrawWidget extends StatefulWidget {
      @override
      _ViewState createState() => _ViewState();
    }
```

答: Probably too late, but in case someone else bumps into this problem. 'flutter clean' did the trick for me..</p>

Title: How to fix stripe payment in flutter


问:
ColdFusion allow user to download CSV file
I am trying to allow the user to download a CSV file from the app. I have googled this a lot and as with almost any coldfusion issue I can't find much. Here is what I am trying:

```<code><cfset yourFileName="\\10.21.2.187\devintranet\WebSite\Audit_Web\AuditWeb\temp\file.csv">
<cffile action="read" file="#yourFileName#" variable="myFile">

<cfheader name="content-disposition" value="attachment; filename=#listLast(myFile, "\")# />
<cfcontent type="application/msexcel" variable="#myFile#" reset="true" />
</code>```

This is the correct filepath:

```<code>temp/file.csv
</code>```

and this is the file name:

Right now I am getting the error: 403 forbidden.
I have no idea what is wrong and what is right about this. I'm just using code I found online. Any advice at all would be greatly appreciated.

答:
Determine which file you want to download:

```<code><cfset yourFileName="\\10.21.2.187\devintranet\WebSite\Audit_Web\AuditWeb\temp\file.csv">
</code>```

Read the file into a CF variable:

```<code><cffile action="read" file="#yourFileName#" variable="myFile">
</code>```

Send the file to the browser using the correct mime-type and file name:

```<code><cfheader name="content-disposition" value="attachment; filename=#listLast(myFile, '\')#" />
<cfcontent type="application/msexcel" variable="#myFile#" reset="true" />
</code>```

Then there's no need for <cflocation>, the request will end once the file has been pushed to the browser.

Update: According to CFDocs, text/csv isn't an allowed type. It should allow any proper mime-type, apparently it doesn't. Check that link for allowed values for type.

Update 2: text/csv was just fine. The value attribute of cfheader wasn't closed correctly. Had to change the listLast() to use single quotes and add a closing double quote.

Body:
I am trying to allow the user to download a CSV file from the app. I have googled this a lot and as with almost any coldfusion issue I can't find much. Here is what I am trying:

<cfset yourFileName="\\10.21.2.187\devintranet\WebSite\Audit_Web\AuditWeb\temp\file.csv">
<cffile action="read" file="#yourFileName#" variable="myFile">

<cfheader name="content-disposition" value="attachment; filename=#listLast(myFile, "\")# />
<cfcontent type="application/msexcel" variable="#myFile#" reset="true" />

This is the correct filepath:

temp/file.csv

and this is the file name:

Right now I am getting the error: 403 forbidden.
I have no idea what is wrong and what is right about this. I'm just using code I found online. Any advice at all would be greatly appreciated.

Body:
Determine which file you want to download:

<cfset yourFileName="\\10.21.2.187\devintranet\WebSite\Audit_Web\AuditWeb\temp\file.csv">

Read the file into a CF variable:

<cffile action="read" file="#yourFileName#" variable="myFile">

Send the file to the browser using the correct mime-type and file name:

<cfheader name="content-disposition" value="attachment; filename=#listLast(myFile, '\')#" />
<cfcontent type="application/msexcel" variable="#myFile#" reset="true" />

Then there's no need for <cflocation>, the request will end once the file has been pushed to the browser.

Update: According to CFDocs, text/csv isn't an allowed type. It should allow any proper mime-type, apparently it doesn't. Check that link for allowed values for type.

Update 2: text/csv was just fine. The value attribute of cfheader wasn't closed correctly. Had to change the listLast() to use single quotes and add a closing double quote.


问:
I want to add a form to my Angular 8 app that takes a zip code and uses it to format a URL, which is used for an API call
An issue has been that when I click submit, the page reloads without using the zip code to format the URL.

Basically, I want to take the zip code in the form, format a URL, make an API call on that URL, and then print data from the JSON to the screen.

I'm already formatting a URL and getting the data I need.
The problem is that I can't get the form data to store in a variable, and use that to format my URL.

Here's component.ts:

```<code>import { WeatherdataService } from '../services/weatherdata.service';
import { THIS_EXPR } from '@angular/compiler/src/output/output_ast';
import { FormControl,FormGroup } from '@angular/forms';
@Component({
  selector: 'app-dailyda',
  templateUrl: './dailyda.component.html',
  styleUrls: ['./dailyda.component.scss']
})
export class DailydaComponent implements OnInit {

  zipForm = new FormGroup({
    zipCode:new FormControl('37064') //Default value in quotes
  })
  zipcode = 60610;
  onSubmit() {
    this.zipcode = this.zipForm.value.zipCode;
    console.log(this.zipcode);
  }
  weather;
  temp;
  press;
  dry_da;
  //Crunch your numbers here, store it in a variable called result, etc.,
  //And in the template, {{ result }} will display that number.
  ISAT = 288.15;
  ISAP = 1013.25;
  expon = 0.234978134;
  // lapse_rate = 0.0065;
  // R = 8.3144598; Replaced all this with expon
  // g = 9.80665;
  // M = 0.028964; // This is the molar mass of DRY air.

  constructor(private weatherdataService: WeatherdataService) { }

  ngOnInit() {
    this.weatherdataService.getWeather(this.zipcode).subscribe((data)=>{
       // add zip code to .getWeather call
      this.weather = data;
      this.temp = this.weather.main.temp;
      this.press = this.weather.main.pressure;
      this.dry_da = Math.round(3.28084 * this.ISAT/0.0065 *(1 - ((this.press/this.ISAP)/(this.temp/this.ISAT))** (this.expon)));
    }
    )};

};
</code>```

Here's compnonent.html:
(I tried using ngSubmit(), but the submit button reloads my page, and nothing shows up.

```<code>    <label>
        Zip Code:
        <input type="text" [formControl]='zipCode'>
    </label>
    <button type="button" (click)="onSubmit()">Submit</button>
</form>
<div *ngIf = 'zipForm'>
    <p>Current Zip: {{ zipCode.value }}</p>
</div>
<div *ngIf = "weather"> <!-- *ngIf prevents errors, because of the
delay in retrieving JSON from the API. Once weather has a value, this
div is displayed.-->
    <h4> Density Altitude (assumes dry air): </h4>
    <h2><strong>{{ dry_da }} ft</strong></h2>
    <h4> Temp in Kelvins: </h4>
    <h2><strong>{{ temp }}</strong></h2>
    <h4> Static Atmospheric Pressure in hPa: </h4>
    <h2><strong>{{ press }}</strong></h2>
</div>
</code>```

Here's the service.ts:

```<code>import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Injectable({
  providedIn: 'root'
})
export class WeatherdataService {
  API_KEY = 'blahblahblah';

  constructor(private httpClient: HttpClient) { }

  public getWeather(zipcode){ // getWeather(zipcode)
    return this.httpClient.get(
`https://api.openweathermap.org/data/2.5/weather?zip=${zipcode}&appid=${this.API_KEY}`
);  // where to format with zip code
  }
}

</code>```

答:
Based on your code example, you are creating the URL during ngOnInit(), which occurs before you click your button to call onSubmit()

You would need to try something like this.

```<code> onSubmit() {
    this.zipcode = this.zipForm.value.zipCode;
    console.log(this.zipcode);

    this.weatherdataService.getWeather(this.zipcode).subscribe(data => {
      // add zip code to .getWeather call
      this.weather = data;
      this.temp = this.weather.main.temp;
      this.press = this.weather.main.pressure;
      this.dry_da = Math.round(
        ((3.28084 * this.ISAT) / 0.0065) *
          (1 - (this.press / this.ISAP / (this.temp / this.ISAT)) ** this.expon)
      );
    });

  }
</code>```

Body:
An issue has been that when I click submit, the page reloads without using the zip code to format the URL.

Basically, I want to take the zip code in the form, format a URL, make an API call on that URL, and then print data from the JSON to the screen.

I'm already formatting a URL and getting the data I need.
The problem is that I can't get the form data to store in a variable, and use that to format my URL.

Here's component.ts:

import { WeatherdataService } from '../services/weatherdata.service';
import { THIS_EXPR } from '@angular/compiler/src/output/output_ast';
import { FormControl,FormGroup } from '@angular/forms';
@Component({
  selector: 'app-dailyda',
  templateUrl: './dailyda.component.html',
  styleUrls: ['./dailyda.component.scss']
})
export class DailydaComponent implements OnInit {

  zipForm = new FormGroup({
    zipCode:new FormControl('37064') //Default value in quotes
  })
  zipcode = 60610;
  onSubmit() {
    this.zipcode = this.zipForm.value.zipCode;
    console.log(this.zipcode);
  }
  weather;
  temp;
  press;
  dry_da;
  //Crunch your numbers here, store it in a variable called result, etc.,
  //And in the template, {{ result }} will display that number.
  ISAT = 288.15;
  ISAP = 1013.25;
  expon = 0.234978134;
  // lapse_rate = 0.0065;
  // R = 8.3144598; Replaced all this with expon
  // g = 9.80665;
  // M = 0.028964; // This is the molar mass of DRY air.

  constructor(private weatherdataService: WeatherdataService) { }

  ngOnInit() {
    this.weatherdataService.getWeather(this.zipcode).subscribe((data)=>{
       // add zip code to .getWeather call
      this.weather = data;
      this.temp = this.weather.main.temp;
      this.press = this.weather.main.pressure;
      this.dry_da = Math.round(3.28084 * this.ISAT/0.0065 *(1 - ((this.press/this.ISAP)/(this.temp/this.ISAT))** (this.expon)));
    }
    )};

};

Here's compnonent.html:
(I tried using ngSubmit(), but the submit button reloads my page, and nothing shows up.

        Zip Code:
        <input type="text" [formControl]='zipCode'>

    <button type="button" (click)="onSubmit()">Submit</button>
</form>

Current Zip: {{ zipCode.value }}

 Density Altitude (assumes dry air):

{{ dry_da }} ft

 Temp in Kelvins:

{{ temp }}

 Static Atmospheric Pressure in hPa:

{{ press }}

Here's the service.ts:

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Injectable({
  providedIn: 'root'
})
export class WeatherdataService {
  API_KEY = 'blahblahblah';

  constructor(private httpClient: HttpClient) { }

  public getWeather(zipcode){ // getWeather(zipcode)
    return this.httpClient.get(
`https://api.openweathermap.org/data/2.5/weather?zip=${zipcode}&appid=${this.API_KEY}`
);  // where to format with zip code
  }
}

Body:
Based on your code example, you are creating the URL during ngOnInit(), which occurs before you click your button to call onSubmit()

You would need to try something like this.

 onSubmit() {
    this.zipcode = this.zipForm.value.zipCode;
    console.log(this.zipcode);

    this.weatherdataService.getWeather(this.zipcode).subscribe(data => {
      // add zip code to .getWeather call
      this.weather = data;
      this.temp = this.weather.main.temp;
      this.press = this.weather.main.pressure;
      this.dry_da = Math.round(
        ((3.28084 * this.ISAT) / 0.0065) *
          (1 - (this.press / this.ISAP / (this.temp / this.ISAT)) ** this.expon)
      );
    });

  }


问:
JSON: Update base64 string using url JSON
I'm new to JSON Code. I want to learn about the update function. Currently, I successfully can update data to the database. Below is the code.

```<code><?php

    require_once "../config/configPDO.php";

    $photo_after = 'kk haha';
    $report_id = 1;

    $url = "http://172.20.0.45/TGWebService/TGWebService.asmx/ot_maintainReport?taskname=&reportStatus=&photoBefore=&photoAfter=". urlencode($photo_after) . "&reportID=$report_id";
    $data = file_get_contents($url);
    $json = json_decode($data);
    $query = $json->otReportList;

    if($query){
        echo "Data Save!";
    }else{
        echo "Error!! Not Saved";
    }

?>
</code>```

the problem is, if the value of $photo_after is base64 string, which is too large string, it will give the error:

1) PHP Warning:  file_get_contents.....

2) PHP Notice:  Trying to get property 'otReportList' of non-object in C:

BUT

when I change the code to this,

```<code><?php

    require_once "../config/configPDO.php";

    $photo_after = 'mama kk';
    $report_id = 1;

    $sql = "UPDATE ot_report SET photo_after ='$photo_after', time_photo_after = GETDATE(), ot_end = '20:30:00' WHERE report_id = '$report_id'";
    $query = $conn->prepare($sql);
    $query->execute();

    if($query){
        echo "Data Save!";
    }else{
        echo "Error!! Not Saved";
    }

?>
</code>```

The data will updated including when the value of $photo_after is in base 64 string.

Can I know what is the problem? Any solution to allow the base64 string update thru json link?

Thanks

答:
<pre class="lang-php prettyprint-override"><code>// ...
// It's likely that the following line failed
$data = file_get_contents($url);
// ...
</code>```

<p>If the length of <code>$url</code> is more than 2048 bytes, that could cause <code>file_get_contents($url)</code> to fail. See What is the maximum length of a URL in different browsers?.</p>

<p>Consequent to such failure, you end up with a value of <code>$json</code> which is not an object. Ultimately, the property <code>otReportList</code> would not exist in <code>$json</code> hence the error: <em><code>...trying to get property 'otReportList' of non-object in C...</code></em>.</p>

<p>To surmount the URL length limitation, it would be best to embed the value of <code>$photo_after</code> in the request <code>body</code>. As requests made with <code>GET</code> method <em>should not</em> have a <code>body</code>, using <code>POST</code> method would be appropriate.</p>

<p>Below is a <em>conceptual</em> adjustment of your code to send the data with a <code>POST</code> method:</p>

<pre class="lang-php prettyprint-override"><code><?php

require_once "../config/configPDO.php";

# You must adapt backend behind this URL to be able to service the
# POST request
$url = "http://172.20.0.45/TGWebService/TGWebService.asmx/ot_maintainReport";

$report_id = 1;
$photo_after = 'very-long-base64-encoding-of-an-image';

$request_content = <<<CONTENT
    {
        "taskname": $taskname,
        "report_id": $report_id,
        "photoBefore": $photoBefore,
        "photo_after": $photo_after,
        "reportStatus": $reportStatus
    }
CONTENT;
$request_content_length = strlen($request_content);

# Depending on your server configuration, you may need to set
# $request_headers as an associative array instead of a string.
$request_headers = <<<HEADERS
Content-type: application/json
Content-Length: $request_content_length
HEADERS;

$request_options = array(
    'http' => array(
        'method' => "POST",
        'header' => $request_headers,
        'content' => $request_content
    )
);
$request_context = stream_context_create($request_options);

$data = file_get_contents($url, false, $request_context);

# The request may fail for whatever reason, you should handle that case.
if (!$data) {
    throw new Exception('Request failed, data is invalid');
}

$json = json_decode($data);
$query = $json->otReportList;

if ($query) {
    echo "Data Save!";
} else {
    echo "Error!! Not Saved";
}

?>
</code>```

Body:
I'm new to JSON Code. I want to learn about the update function. Currently, I successfully can update data to the database. Below is the code.

<?php

    require_once "../config/configPDO.php";

    $photo_after = 'kk haha';
    $report_id = 1;

    $url = "http://172.20.0.45/TGWebService/TGWebService.asmx/ot_maintainReport?taskname=&reportStatus=&photoBefore=&photoAfter=". urlencode($photo_after) . "&reportID=$report_id";
    $data = file_get_contents($url);
    $json = json_decode($data);
    $query = $json->otReportList;

    if($query){
        echo "Data Save!";
    }else{
        echo "Error!! Not Saved";
    }

?>

the problem is, if the value of $photo_after is base64 string, which is too large string, it will give the error:

1) PHP Warning:  file_get_contents.....

2) PHP Notice:  Trying to get property 'otReportList' of non-object in C:

BUT

when I change the code to this,

<?php

    require_once "../config/configPDO.php";

    $photo_after = 'mama kk';
    $report_id = 1;

    $sql = "UPDATE ot_report SET photo_after ='$photo_after', time_photo_after = GETDATE(), ot_end = '20:30:00' WHERE report_id = '$report_id'";
    $query = $conn->prepare($sql);
    $query->execute();

    if($query){
        echo "Data Save!";
    }else{
        echo "Error!! Not Saved";
    }

?>

The data will updated including when the value of $photo_after is in base 64 string.

Can I know what is the problem? Any solution to allow the base64 string update thru json link?

Thanks

Body:
// ...
// It's likely that the following line failed
$data = file_get_contents($url);
// ...

If the length of $url is more than 2048 bytes, that could cause file_get_contents($url) to fail. See What is the maximum length of a URL in different browsers?.

Consequent to such failure, you end up with a value of $json which is not an object. Ultimately, the property otReportList would not exist in $json hence the error: ...trying to get property 'otReportList' of non-object in C....

To surmount the URL length limitation, it would be best to embed the value of $photo_after in the request body. As requests made with GET method should not have a body, using POST method would be appropriate.

Below is a conceptual adjustment of your code to send the data with a POST method:

<?php

require_once "../config/configPDO.php";

# You must adapt backend behind this URL to be able to service the
# POST request
$url = "http://172.20.0.45/TGWebService/TGWebService.asmx/ot_maintainReport";

$report_id = 1;
$photo_after = 'very-long-base64-encoding-of-an-image';

$request_content = <<<CONTENT
    {
        "taskname": $taskname,
        "report_id": $report_id,
        "photoBefore": $photoBefore,
        "photo_after": $photo_after,
        "reportStatus": $reportStatus
    }
CONTENT;
$request_content_length = strlen($request_content);

# Depending on your server configuration, you may need to set
# $request_headers as an associative array instead of a string.
$request_headers = <<<HEADERS
Content-type: application/json
Content-Length: $request_content_length
HEADERS;

$request_options = array(
    'http' => array(
        'method' => "POST",
        'header' => $request_headers,
        'content' => $request_content
    )
);
$request_context = stream_context_create($request_options);

$data = file_get_contents($url, false, $request_context);

# The request may fail for whatever reason, you should handle that case.
if (!$data) {
    throw new Exception('Request failed, data is invalid');
}

$json = json_decode($data);
$query = $json->otReportList;

if ($query) {
    echo "Data Save!";
} else {
    echo "Error!! Not Saved";
}

?>


问:
traefik loadbalancer server port
i have a few services in my docker-compose file using traefik labels.

now i would like to clean this file and start using traefik yaml files.

the problem is that i could not find the equivalent to traefik.http.services.dnsmasq-traefik.loadbalancer.server.port=5380

and there arent any examples in the docs

the labels (this works perfectly)

```<code>- "traefik.http.routers.dnsmasq.rule=Host(`dnsmasq.docker.localdomain`)"
- "traefik.http.routers.dnsmasq.service=dnsmasq-traefik@docker"
- "traefik.http.services.dnsmasq-traefik.loadbalancer.server.port=5380"
</code>```

the yaml (not working, gives me a Gateway Timeout)

```<code>http:
    routers:
        dnsmasq-preauth:
            entryPoints: [http]
            middlewares: [redirect-to-http]
            service: dnsmasq-preauth
            rule: Host(`dnsmasq.docker.localdomain`)

    services:
        dnsmasq-preauth:
            loadBalancer:
                servers:
                    - url: "http://dnsmasq.docker.localdomain:5380"
</code>```

答:
Whenever I get this Gateway timeout issue I immediately look in two places:

The Traefik Config needs to be exposedByDefault - docs here

```<code>providers:
  docker:
    exposedByDefault: false
    # ...
</code>```

If exposedByDefault is false then you need to do #2 in this list.

On your specific container you need to set the docker labels

```<code>- traefik.enable=true
</code>```

Title: traefik loadbalancer server port

Body:
i have a few services in my docker-compose file using traefik labels.

now i would like to clean this file and start using traefik yaml files.

the problem is that i could not find the equivalent to traefik.http.services.dnsmasq-traefik.loadbalancer.server.port=5380

and there arent any examples in the docs

the labels (this works perfectly)

- "traefik.http.routers.dnsmasq.rule=Host(`dnsmasq.docker.localdomain`)"
- "traefik.http.routers.dnsmasq.service=dnsmasq-traefik@docker"
- "traefik.http.services.dnsmasq-traefik.loadbalancer.server.port=5380"

the yaml (not working, gives me a Gateway Timeout)

http:
    routers:
        dnsmasq-preauth:
            entryPoints: [http]
            middlewares: [redirect-to-http]
            service: dnsmasq-preauth
            rule: Host(`dnsmasq.docker.localdomain`)

    services:
        dnsmasq-preauth:
            loadBalancer:
                servers:
                    - url: "http://dnsmasq.docker.localdomain:5380"

Body:
Whenever I get this Gateway timeout issue I immediately look in two places:

The Traefik Config needs to be exposedByDefault - docs here

providers:
  docker:
    exposedByDefault: false
    # ...

If exposedByDefault is false then you need to do #2 in this list.

On your specific container you need to set the docker labels

- traefik.enable=true


问:
Symfony: Override plugin-model in other plugin
we are building a new website, which will reuse an existing symfony-software used by another website. I'm moving reusable components into a plugin ("app-plugin"), in order to avoid duplicating code and data. The plugin will be configured as svn-external in the websites' svn repositories.

The existing symfony instance contains overridden doctrine classes (models, forms, form-filters) which are originally defined in other plugins (e.g. sfDoctrineGuardPlugin). The overridden classes can be reused by both symfony-instances, therefore I'm going to move them to the "app-plugin". But this causes problems:

If someone, for instance, runs symfony doctrine:build-forms, the moved files will be re-created by the task inside lib/form/doctrine and will contain empty class-definitions. The reason is very clear to me: How was symfony supposed to know that the "app-plugin" is already defining those form-classes? The only way would be to autoload all classes before executing the task and checking whether classes are already available.

A workaround would be to exclude those classes in the app-plugin's config/autoload.yml. But is there a better way?

Edit

I'm using the term "app-plugin" to avoid confusion between normal plugin (e.g. sfGuard) and our plugin which contains shared components.

Before:

After:

答: What is this "app-plugin" you are talking about ? Normally, all you have to do is leave your overriden classes where they are, and move the code they contain in the parent classes, which are supposed to be in the plugin. And if you want to change the behavior for a particular symfony app, then you may edit these overriden classes.</p>

ContentLicense: CC BY-SA 3.0


问:
How to extract specified numbers from a HTML source and merge them?
There is a site that gives 3 numbers as pictures that you have to copy and write in a specified box and press continue.I want to write a code to do it for me.I looked at the HTML source and the png files are named same as the number so I just need to extract them ,merge and write it down.

I've used Selenium to make a bot and access the site after I login it fills the specified area with "123" as a test so I know how to write down the numbers if I somehow get them.I used Beatifulsoup to turn it into text for but it gave me an error

```<code>  File "C:\Users\user\Desktop\money.py", line 20
    soup = BeautifulSoup(driver)
UserWarning: No parser was explicitly specified, so I'm using the best available HTML parser for this system ("lxml"). This usually isn't a problem, but if you run this code on another system, or in a different virtual environment, it may use a different parser and behave differently.

The code that caused this warning is on line 20 of the file C:\Users\user\Desktop\money.py. To get rid of this warning, pass the additional argument 'features="lxml"' to the BeautifulSoup constructor.

Traceback (most recent call last):
  File "C:\Users\user\Desktop\money.py", line 20, in <module>
    soup = BeautifulSoup(driver)
  File "C:\Users\user\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.7_qbz5n2kfra8p0\LocalCache\local-packages\Python37\site-packages\bs4\__init__.py", line 287, in __init__
    elif len(markup) <= 256 and (
TypeError: object of type 'WebDriver' has no len()
</code>```

I'd appreciate if you have a different method or can fix the issue.
I haven't figured out how to press the continue button automatically but will press it myself if needed.
My code not even close to being done so feel free to suggest anything.

```<code>import time
import re
from bs4 import BeautifulSoup
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By

driver = webdriver.Chrome(executable_path = "C:/Users/user/Desktop/Personal/PythonScripts/chromedriver.exe")
driver.get('URL I USED')

time.sleep(20)
driver.refresh()
try :
 driver.find_element_by_tag_name('input').send_keys('123')
except :
    print('Fail')

soup = BeautifulSoup(driver ,"lxml")

images = list()
try :
 re.findall(r'\d+', soup)
 images.append(new)
except:
    print('Fail')
html_source = driver.page_source
print(html_source)```

```

答:
You forgot .page_source in BeautifulSoup(driver.page_source, "lxml")

As for numebers if you use BeautifulSoup then use all of its functionality - use find_all() to find all  and get attributes src. And then you can get char from src (which is string) as string[-5]

if there are more images then you could use other attributes in find_all() - ie. width="35"

You should read documentation for BeautifulSoup - it has many useful functions.

```<code>html = '''<img width="35" height="55" src="images/capchs/6.png">
<img width="35" height="55" src="images/capchs/3.png">
<img width="35" height="55" src="images/capchs/1.png">'''

from bs4 import BeautifulSoup as BS

soup = BS(html, 'lxml')

all_items = soup.find_all('img')
#all_items = soup.find_all('img', width='35')
for item in all_items:
    print('char:', item['src'][-5])

number = [item['src'][-5] for item in all_items]
number = "".join(number)

print('number:', number)
</code>```

Result

```<code>char: 6
char: 3
char: 1
number: 631
</code>```

You could do this even without BeautifulSoup because Selenium has many function find_elements_by_... (ie. find_elements_by_xpath()) and it has also get_attribute()

Read Selenium documentation: Locating Elements, get_attribute

Not tested

```<code>all_items = driver.find_elements_by_tag_name('img')
for item in all_items:
    print('char:', item.get_attribute('src')[-5])

number = [item.get_attribute('src')[-5] for item in all_items]
number = "".join(number)

print('number:', number)
</code>```

Body:
There is a site that gives 3 numbers as pictures that you have to copy and write in a specified box and press continue.I want to write a code to do it for me.I looked at the HTML source and the png files are named same as the number so I just need to extract them ,merge and write it down.

I've used Selenium to make a bot and access the site after I login it fills the specified area with "123" as a test so I know how to write down the numbers if I somehow get them.I used Beatifulsoup to turn it into text for but it gave me an error

  File "C:\Users\user\Desktop\money.py", line 20
    soup = BeautifulSoup(driver)
UserWarning: No parser was explicitly specified, so I'm using the best available HTML parser for this system ("lxml"). This usually isn't a problem, but if you run this code on another system, or in a different virtual environment, it may use a different parser and behave differently.

The code that caused this warning is on line 20 of the file C:\Users\user\Desktop\money.py. To get rid of this warning, pass the additional argument 'features="lxml"' to the BeautifulSoup constructor.

Traceback (most recent call last):
  File "C:\Users\user\Desktop\money.py", line 20, in <module>
    soup = BeautifulSoup(driver)
  File "C:\Users\user\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.7_qbz5n2kfra8p0\LocalCache\local-packages\Python37\site-packages\bs4\__init__.py", line 287, in __init__
    elif len(markup) <= 256 and (
TypeError: object of type 'WebDriver' has no len()

I'd appreciate if you have a different method or can fix the issue.
I haven't figured out how to press the continue button automatically but will press it myself if needed.
My code not even close to being done so feel free to suggest anything.

import time
import re
from bs4 import BeautifulSoup
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By

driver = webdriver.Chrome(executable_path = "C:/Users/user/Desktop/Personal/PythonScripts/chromedriver.exe")
driver.get('URL I USED')

time.sleep(20)
driver.refresh()
try :
 driver.find_element_by_tag_name('input').send_keys('123')
except :
    print('Fail')

soup = BeautifulSoup(driver ,"lxml")

images = list()
try :
 re.findall(r'\d+', soup)
 images.append(new)
except:
    print('Fail')
html_source = driver.page_source
print(html_source)```

Body:
You forgot .page_source in BeautifulSoup(driver.page_source, "lxml")

As for numebers if you use BeautifulSoup then use all of its functionality - use find_all() to find all <img> and get attributes src. And then you can get char from src (which is string) as string[-5]

if there are more images then you could use other attributes in find_all() - ie. width="35"

You should read documentation for BeautifulSoup - it has many useful functions.

html = '''<img width="35" height="55" src="images/capchs/6.png">
<img width="35" height="55" src="images/capchs/3.png">
<img width="35" height="55" src="images/capchs/1.png">'''

from bs4 import BeautifulSoup as BS

soup = BS(html, 'lxml')

all_items = soup.find_all('img')
#all_items = soup.find_all('img', width='35')
for item in all_items:
    print('char:', item['src'][-5])

number = [item['src'][-5] for item in all_items]
number = "".join(number)

print('number:', number)

Result

char: 6
char: 3
char: 1
number: 631

You could do this even without BeautifulSoup because Selenium has many function find_elements_by_... (ie. find_elements_by_xpath()) and it has also get_attribute()

Read Selenium documentation: Locating Elements, get_attribute

Not tested

all_items = driver.find_elements_by_tag_name('img')
for item in all_items:
    print('char:', item.get_attribute('src')[-5])

number = [item.get_attribute('src')[-5] for item in all_items]
number = "".join(number)

print('number:', number)


问:
using spread syntax with ternary operator inside object literal
Consider following code, where one object is composed from two parts: values and their corresponding descriptions:

let flagConfigObj = {};

const features = {
  f1: {
    value: 1,
    type: 'type1'
  },
  f2: {
    value: 2,
    type: 'type2'
  }
};

let featuresDescription = {
  f1: {
    description: 'desc 1'
  },
  f2: {
    description: 'desc 2'
  }
};

Object.keys(features).forEach(key => {
  flagConfigObj[key] = {
    ...features[key],
    ...(featuresDescription[key] || { some: 'backup' })
  };
});

console.log(flagConfigObj);

```

<p>As you might notice, when composite is constructed, there is <code>||</code> operator preventing form spreading non-existing object and replacing it with some default templates. And so, output for this code will be:</p>

```{
  f1: { value: 1, type: 'type1', description: 'desc 1' },
  f2: { value: 2, type: 'type2', description: 'desc 2' }
}
```

<p>But when corresponding description field in <code>featuresDescription</code> is missing, it's replaced to:</p>

```{
  f1: { value: 1, type: 'type1', description: 'desc 1' },
  f2: { value: 2, type: 'type2', some: 'backup' }
}
```

<p><strong>The question</strong></p>

<p>How to replace <code>||</code> syntax with ternary operator <code>?:</code>?
I've tried some funny combinations like </p>

```featuresDescription[key] ? ...featuresDescription[key] : {some: 'backup'}
{featuresDescription[key]} ? ...featuresDescription[key] : {some: 'backup'}
```

But all of them gives syntax error, and I'm feeling now like just blindly randomizing positions of [,],},{,... instead of truly understanding it...

Any help as always is appreciated!

答:
I think this might be the syntax you are looking for;

Object.keys(features).forEach(key => {
        flagConfigObj[key] = {
            ...features[key],
            ...(featuresDescription[key] ? featuresDescription[key] : {some: 'backup'})
    }
})
```

Body:
Consider following code, where one object is composed from two parts: values and their corresponding descriptions:

let flagConfigObj = {};

const features = {
  f1: {
    value: 1,
    type: 'type1'
  },
  f2: {
    value: 2,
    type: 'type2'
  }
};

let featuresDescription = {
  f1: {
    description: 'desc 1'
  },
  f2: {
    description: 'desc 2'
  }
};

Object.keys(features).forEach(key => {
  flagConfigObj[key] = {
    ...features[key],
    ...(featuresDescription[key] || { some: 'backup' })
  };
});

console.log(flagConfigObj);

As you might notice, when composite is constructed, there is || operator preventing form spreading non-existing object and replacing it with some default templates. And so, output for this code will be:

{
  f1: { value: 1, type: 'type1', description: 'desc 1' },
  f2: { value: 2, type: 'type2', description: 'desc 2' }
}

But when corresponding description field in featuresDescription is missing, it's replaced to:

{
  f1: { value: 1, type: 'type1', description: 'desc 1' },
  f2: { value: 2, type: 'type2', some: 'backup' }
}

The question

How to replace || syntax with ternary operator ?:?
I've tried some funny combinations like

featuresDescription[key] ? ...featuresDescription[key] : {some: 'backup'}
{featuresDescription[key]} ? ...featuresDescription[key] : {some: 'backup'}

But all of them gives syntax error, and I'm feeling now like just blindly randomizing positions of [,],},{,... instead of truly understanding it...

Any help as always is appreciated!


问:
Resolution for 2d pixel art games
I'm having problems to set the right resolution on unity to not have pixel distortion on my pixel art assets. When I create an tile grid, on the preview tab the assets look terrible.

I have an tilemap with 64x32 resolution for each tile.

I'm using 64 pixels per unit.

The camera size is set to 5 in a 640x360 resolution (using the following formula: vertical resolution / PPU / 2).

What I'm doing wrong and what I'm missing?

答:
To solve this problem and get an "pixel perfect" view, you need to apply the following formula:

Camera size = height of the screen resolution / PPU (pixels per unit) / 2

This will do the job!

Title: Resolution for 2d pixel art games


问:
Kill processes from shell in Android
I try to find some way to kill unnecessary services/processes in Android from shell.
The problem is that after killing the process it starts again after few seconds!

for example I tried to kill batterywarning, but it keep starting again:

```<code>root@w812a_kk:/ # ps  | grep batteryw
shell     17986 1     1044   364   c00601dc b6e9f094 S /system/bin/batterywarning
1|root@w812a_kk:/ # ps  | grep batteryw
shell     17781 1     1044   364   c00601dc b6ee6094 S /system/bin/batterywarning
root@w812a_kk:/ # busybox killall batterywarning
root@w812a_kk:/ # ps  | grep batteryw
1|root@w812a_kk:/ # ps  | grep batteryw
shell     17986 1     1044   364   c00601dc b6e9f094 S /system/bin/batterywarning
</code>```

I did find several methods to kill service/process in the following link, yet the process is starting again.

Android ADB stop application command like "force-stop" for non rooted device.

Is it something that can only be done in init.rc ?

Thanks,

答:
kill a process when you have the process name (basically you don't have to search 'ps' for the process ID and then kill it with PID):

adb shell kill $(pidof com.android.phone)

Title: Kill processes from shell in Android

Body:
I try to find some way to kill unnecessary services/processes in Android from shell.
The problem is that after killing the process it starts again after few seconds!

for example I tried to kill batterywarning, but it keep starting again:

root@w812a_kk:/ # ps  | grep batteryw
shell     17986 1     1044   364   c00601dc b6e9f094 S /system/bin/batterywarning
1|root@w812a_kk:/ # ps  | grep batteryw
shell     17781 1     1044   364   c00601dc b6ee6094 S /system/bin/batterywarning
root@w812a_kk:/ # busybox killall batterywarning
root@w812a_kk:/ # ps  | grep batteryw
1|root@w812a_kk:/ # ps  | grep batteryw
shell     17986 1     1044   364   c00601dc b6e9f094 S /system/bin/batterywarning

I did find several methods to kill service/process in the following link, yet the process is starting again.

Android ADB stop application command like "force-stop" for non rooted device.

Is it something that can only be done in init.rc ?

Thanks,


问:
how to iterate over array[string] in spark scala?
enter image description herehere is my sample input:

```<code>val list=List("a;bc:de;f","uvw:xy;z","123:456")
</code>```

I am applying following operation

val upper=list.map(x=>x.split(":")).map(x=>x.split(";"))

but it is throwing error-
error: value split is not a member of Array[String]

can anyone help how to use both split so that i can get answer!

Thank you in advance.

答:
You can use split with multiple delimiters in one map iteration :

```<code>val upper = list.map(x => x.split("[:;]"))

//upper: List[Array[String]] = List(Array(a, bc, de, f), Array(uvw, xy, z), Array(123, 456))
</code>```

Body:
enter image description herehere is my sample input:

val list=List("a;bc:de;f","uvw:xy;z","123:456")

I am applying following operation

val upper=list.map(x=>x.split(":")).map(x=>x.split(";"))

but it is throwing error-
error: value split is not a member of Array[String]

can anyone help how to use both split so that i can get answer!

Thank you in advance.

Body:
You can use split with multiple delimiters in one map iteration :

val upper = list.map(x => x.split("[:;]"))

//upper: List[Array[String]] = List(Array(a, bc, de, f), Array(uvw, xy, z), Array(123, 456))


问:
What this function on redraws and reflows is doing?
The JS code is meant to minimizethe number of redraws and reflows required. I'm quite new to the concept so i'm not to sure what the function is doing....specifically the for loop.</p>

```<code>(function() {
    var element,
        index,
        length,
        content = document.getElementById("content"),
        html = "",
        data = [{
            id: 1,
            name: "John",
            color: "green"
        }, {
            id: 2,
            name: "Sally",
            color: "pink"
        }, {
            id: 3,
            name: "Andrew",
            color: "blue"
        }, {
            id: 4,
            name: "Katie",
            color: "purple"
        }];

    for (index = 0; index < data.length; index++) {
        html +=
            '<li id="' + data[index].id + '" style="color: ' + data[index].color + '">' +
                '<strong>' + data[index].name + '</strong>' +
            '</li>';
    }

    content.innerHTML = html;
 })();
</code>```

答: The for loop is simply concatenating strings for each element of the array. The purpose of this is to put all the HTML for the list into a single string, and then put that into the DOM once, rather than appending to the HTML each time through the loop. This is more efficient because the HTML only has to be rendered once instead of multiple times.

Body:
The JS code is meant to minimizethe number of redraws and reflows required. I'm quite new to the concept so i'm not to sure what the function is doing....specifically the for loop.

(function() {
    var element,
        index,
        length,
        content = document.getElementById("content"),
        html = "",
        data = [{
            id: 1,
            name: "John",
            color: "green"
        }, {
            id: 2,
            name: "Sally",
            color: "pink"
        }, {
            id: 3,
            name: "Andrew",
            color: "blue"
        }, {
            id: 4,
            name: "Katie",
            color: "purple"
        }];

    for (index = 0; index < data.length; index++) {
        html +=
            '
' +
                '' + data[index].name + '' +
            '
';
    }

    content.innerHTML = html;
 })();


问:
trying to use an regex inside firebase .where() to fillter users but only get an error message
Basicly i am working on an whatsapp clone and i went into an problem when searching over the contacts of the current user.

here's the first code

this._user.getContacts(this.el.inputSearchContacts.value);
```

<p>this one is inside an function that when you press any letter or number while the input is focused it start to send what is inside the input to the "getContacts" function</p>

<pre class="lang-js prettyprint-override"><code>getContacts(fillter = ""){

        return new Promise((resolve, reject)=>{

        User.getContactsRef(this.email).where("nameLowerCase", ">=", (fillter)? fillter.match( /([a-z])\+w/gi) : fillter).onSnapshot(docs=>{
          here goes the rest of the function
        }
</code>```

here is where an fillter is applied what it should do is get the name you put in the input and match it with the contacts names in the user contacts list to only show the ones that match, but here's where this error appear:

```<code>Uncaught (in promise) FirebaseError: Invalid query. Null supports only equality comparisons.
    at new FirestoreError (webpack:///./node_modules/@firebase/firestore/dist/index.cjs.js?:351:28)
    at Function.FieldFilter.create (webpack:///./node_modules/@firebase/firestore/dist/index.cjs.js?:9830:23)
    at CollectionReference.Query.where (webpack:///./node_modules/@firebase/firestore/dist/index.cjs.js?:22151:34)
    at eval (webpack:///./src/model/User.js?:87:41)
    at new Promise (<anonymous>)
    at User.getContacts (webpack:///./src/model/User.js?:85:14)
    at HTMLInputElement.eval (webpack:///./src/controller/WhatsAppController.js?:401:20)
FirestoreError @ index.cjs.js:351
FieldFilter.create @ index.cjs.js:9830
Query.where @ index.cjs.js:22151
eval @ User.js:87
getContacts @ User.js:85
eval @ WhatsAppController.js:401
</code>```

so, can someone tell me what i'm doing wrong?

答:
What you're trying to do isn't supported.  Firestore doesn't offer regex searches at all.  You can only compare strings with >=, ==, and <=.

The error message is telling you that your trinary expression:

```<code>(fillter)? fillter.match( /([a-z])\+w/gi) : fillter
</code>```

yielded a null value, which isn't a valid value for the >= comparison you're asking Firestore to perform on the field.

Body:
Basicly i am working on an whatsapp clone and i went into an problem when searching over the contacts of the current user.

here's the first code

this._user.getContacts(this.el.inputSearchContacts.value);

this one is inside an function that when you press any letter or number while the input is focused it start to send what is inside the input to the "getContacts" function

getContacts(fillter = ""){

        return new Promise((resolve, reject)=>{

        User.getContactsRef(this.email).where("nameLowerCase", ">=", (fillter)? fillter.match( /([a-z])\+w/gi) : fillter).onSnapshot(docs=>{
          here goes the rest of the function
        }

here is where an fillter is applied what it should do is get the name you put in the input and match it with the contacts names in the user contacts list to only show the ones that match, but here's where this error appear:

Uncaught (in promise) FirebaseError: Invalid query. Null supports only equality comparisons.
    at new FirestoreError (webpack:///./node_modules/@firebase/firestore/dist/index.cjs.js?:351:28)
    at Function.FieldFilter.create (webpack:///./node_modules/@firebase/firestore/dist/index.cjs.js?:9830:23)
    at CollectionReference.Query.where (webpack:///./node_modules/@firebase/firestore/dist/index.cjs.js?:22151:34)
    at eval (webpack:///./src/model/User.js?:87:41)
    at new Promise (<anonymous>)
    at User.getContacts (webpack:///./src/model/User.js?:85:14)
    at HTMLInputElement.eval (webpack:///./src/controller/WhatsAppController.js?:401:20)
FirestoreError @ index.cjs.js:351
FieldFilter.create @ index.cjs.js:9830
Query.where @ index.cjs.js:22151
eval @ User.js:87
getContacts @ User.js:85
eval @ WhatsAppController.js:401

so, can someone tell me what i'm doing wrong?

Body:
What you're trying to do isn't supported.  Firestore doesn't offer regex searches at all.  You can only compare strings with >=, ==, and <=.

The error message is telling you that your trinary expression:

(fillter)? fillter.match( /([a-z])\+w/gi) : fillter

yielded a null value, which isn't a valid value for the >= comparison you're asking Firestore to perform on the field.


问:
Laravel Eloquent disable automatic lazy loading
Laravel by default has this automatic eager loading which may cause some multiple query issue Eg:

```<code>// If do something like this
$posts = Post::published()->get();
// then
foreach ($posts as $p) {
    echo $p->author->name;
}
// Eloquent will query the author for every post
</code>```

Is it possible to disable this behavior?

答:
In the example you provided, the relationship data is "lazy loaded" not "eager loaded". This means the relationship data is not actually loaded until you first access the property.

However, Eloquent can "eager load" relationships at the time you query the parent model. Eager loading alleviates the N + 1 query problem.

To eager load a relationship, you can use eloquent with() method:

$posts = Post::published()->with('author')->get();
```

<p>Now each <code>post</code> will be eagger loaded with the <code>author</code> model, thus avoiding the N + 1 problem.</p>

<p>You can also specify if you would like to eager load specific columns only:</p>

<pre class="lang-php prettyprint-override"><code>$posts = Post::published()->with('author:id,name')->get();
</code>```

And if you want to always load a relationship when retrieving a model, you can define a $with property on the model:

class Post extends Model
{
    /**
     * The relationships that should always be loaded.
     *
     * @var array
     */
    protected $with = ['author'];

    /**
     * Get the author that wrote the book.
     */
    public function author()
    {
        return $this->belongsTo('App\Author');
    }
}

```

More information: https://laravel.com/docs/6.x/eloquent-relationships#eager-loading

Body:
Laravel by default has this automatic eager loading which may cause some multiple query issue Eg:

// If do something like this
$posts = Post::published()->get();
// then
foreach ($posts as $p) {
    echo $p->author->name;
}
// Eloquent will query the author for every post

Is it possible to disable this behavior?

Body:
In the example you provided, the relationship data is "lazy loaded" not "eager loaded". This means the relationship data is not actually loaded until you first access the property.

However, Eloquent can "eager load" relationships at the time you query the parent model. Eager loading alleviates the N + 1 query problem.

To eager load a relationship, you can use eloquent with() method:

$posts = Post::published()->with('author')->get();

Now each post will be eagger loaded with the author model, thus avoiding the N + 1 problem.

You can also specify if you would like to eager load specific columns only:

$posts = Post::published()->with('author:id,name')->get();

And if you want to always load a relationship when retrieving a model, you can define a $with property on the model:

class Post extends Model
{
    /**
     * The relationships that should always be loaded.
     *
     * @var array
     */
    protected $with = ['author'];

    /**
     * Get the author that wrote the book.
     */
    public function author()
    {
        return $this->belongsTo('App\Author');
    }
}

More information: https://laravel.com/docs/6.x/eloquent-relationships#eager-loading


答:
You could wrap the default expression in parenthese before spreading the object.

let flagConfigObj = {};

const features = { f1: { value: 1, type: 'type1' }, f2: { value: 2, type: 'type2' } };
let featuresDescription = { f1: { description: 'desc 1' }, f2: { description: 'desc 2' } };

Object.keys(features).forEach(key => {
  flagConfigObj[key] = {
    ...features[key],
    ...(featuresDescription[key] || { some: 'backup' })
  }
})

console.log(flagConfigObj)```

Title: using spread syntax with ternary operator inside object literal


问:
Python Vscode extension - can't change remote jupyter notebook kernel
I've got the updated Python VSCode extension installed and it works great. I'm able to use the URL with the token to connect to a remote Jupyter notebook. I just cannot seem to figure out how to change the kernel on the remote notebook for use in VSCode.

If I connect to the remote notebook through a web browser, I can see my two environments through the GUI and change kernels.  Is there a similar option in the VSCode extension?

答:
Run the following command in vscode:

Python: Select interpreter to start Jupyter server

It will allow you to choose the kernel that you want.


问:
Azure DevOps Build Pipeline Triggers too EAGER?
I have multiple projects in my git repo on Azure DevOps. I have build pipelines setup to trigger when commit occurs on the "staging" branch (which is our Develop branch). But I added an additional trigger that I thought would filter on a sub-folder of the repo. Currently there are three pipelines all set to trigger on commit and sub-folder. And all three run even when there is a commit with files from only one of the target sub-folders.
See the screen shot of one of my triggers:

Seems like the triggers are setup like an OR not an AND. So, in other words any commit to staging will trigger all three builds, but there are times when I don't want all three to build and publish. Just the one that I fixed should be built and published.

Is there any way to fix this?

答:
You're right in that both Branch and Path apply.  See here: https://learn.microsoft.com/en-us/azure/devops/pipelines/build/triggers?view=azure-devops&tabs=yaml#multiple-pipelines-triggered-on-the-same-repository

Consider migrating to yaml based builds, and set up each build in a different yaml file with it's own path triggers.  Not only will this solve your issue, but you'll have the benefits of checked-in pipelines.


问:
How to use htmlunit + jsoup to scrape websites that uses javascript to load content dynamically
https://www.reddit.com/r/buildapcsales/top/ takes like 3~ seconds to load all the content. Currently using jsoup I can only scrape the first 7 threads since the other threads are loaded after a few seconds. I'm trying to make htmlunit load the entire page then use jsoup to scrape all the thread titles.

```<code>        WebClient webClient = new WebClient(BrowserVersion.CHROME);
        webClient.getOptions().setJavaScriptEnabled(true);
        Page page = webClient.getPage(url.toString());
        WebResponse response = page.getWebResponse();
        String content = response.getContentAsString();

      //  webClient.getOptions().setJavaScriptEnabled(true);
      //  webClient.getOptions().setThrowExceptionOnScriptError(true);
       // webClient.waitForBackgroundJavaScript(50000);
       // webClient.wait(5000);
       // HtmlPage page = webClient.getPage(url.toString());
</code>```

I keep getting a million errors whenever I setJavascriptEnabled to true, but if I turn it false. It doesn't error out, however I still get the 7 threads with jsoup.

WARNING: Script is not JavaScript (type: 'application/json', language: ''). Skipping execution.
Feb 09, 2020 4:54:36 PM com.gargoylesoftware.htmlunit.javascript.DefaultJavaScriptErrorListener scriptException
SEVERE: Error during JavaScript execution
======= EXCEPTION START ========
Exception class=[net.sourceforge.htmlunit.corejs.javascript.EvaluatorException]
com.gargoylesoftware.htmlunit.ScriptException: syntax error (https://www.redditstatic.com/desktop2x/vendors~Governance~Reddit.791bf381e13bfdc452ab.js#1)
    at com.gargoylesoftware.htmlunit.javascript.JavaScriptEngine$HtmlUnitContextAction.run(JavaScriptEngine.java:882)
    at net.sourceforge.htmlunit.corejs.javascript.Context.call(Context.java:624)
    at net.sourceforge.htmlunit.corejs.javascript.ContextFactory.call(ContextFactory.java:537)
    at com.gargoylesoftware.htmlunit.javascript.HtmlUnitContextFactory.callSecured(HtmlUnitContextFactory.java:354)
    at com.gargoylesoftware.htmlunit.javascript.JavaScriptEngine.compile(JavaScriptEngine.java:713)
    at com.gargoylesoftware.htmlunit.javascript.JavaScriptEngine.compile(JavaScriptEngine.java:679)
    at com.gargoylesoftware.htmlunit.javascript.JavaScriptEngine.compile(JavaScriptEngine.java:103)
    at com.gargoylesoftware.htmlunit.html.HtmlPage.loadJavaScriptFromUrl(HtmlPage.java:1104)
    at com.gargoylesoftware.htmlunit.html.HtmlPage.loadExternalJavaScriptFile(HtmlPage.java:984)
    at com.gargoylesoftware.htmlunit.html.HtmlScript.executeScriptIfNeeded(HtmlScript.java:361)
    at com.gargoylesoftware.htmlunit.html.HtmlScript$2.execute(HtmlScript.java:234)
    at com.gargoylesoftware.htmlunit.html.HtmlPage.initialize(HtmlPage.java:301)
    at com.gargoylesoftware.htmlunit.WebClient.loadWebResponseInto(WebClient.java:560)
    at com.gargoylesoftware.htmlunit.WebClient.getPage(WebClient.java:419)
    at com.gargoylesoftware.htmlunit.WebClient.getPage(WebClient.java:336)
    at com.gargoylesoftware.htmlunit.WebClient.getPage(WebClient.java:488)
    at com.gargoylesoftware.htmlunit.WebClient.getPage(WebClient.java:469)
    at RedditScraper.main(RedditScraper.java:40)

These are some of the first few errors

答: I was having a hard time with trying to run javascript inside of HtmlUnit. Then I tried Selenium, and it worked like a charm.

Body:
https://www.reddit.com/r/buildapcsales/top/ takes like 3~ seconds to load all the content. Currently using jsoup I can only scrape the first 7 threads since the other threads are loaded after a few seconds. I'm trying to make htmlunit load the entire page then use jsoup to scrape all the thread titles.

        WebClient webClient = new WebClient(BrowserVersion.CHROME);
        webClient.getOptions().setJavaScriptEnabled(true);
        Page page = webClient.getPage(url.toString());
        WebResponse response = page.getWebResponse();
        String content = response.getContentAsString();

      //  webClient.getOptions().setJavaScriptEnabled(true);
      //  webClient.getOptions().setThrowExceptionOnScriptError(true);
       // webClient.waitForBackgroundJavaScript(50000);
       // webClient.wait(5000);
       // HtmlPage page = webClient.getPage(url.toString());

I keep getting a million errors whenever I setJavascriptEnabled to true, but if I turn it false. It doesn't error out, however I still get the 7 threads with jsoup.

WARNING: Script is not JavaScript (type: 'application/json', language: ''). Skipping execution.
Feb 09, 2020 4:54:36 PM com.gargoylesoftware.htmlunit.javascript.DefaultJavaScriptErrorListener scriptException
SEVERE: Error during JavaScript execution
======= EXCEPTION START ========
Exception class=[net.sourceforge.htmlunit.corejs.javascript.EvaluatorException]
com.gargoylesoftware.htmlunit.ScriptException: syntax error (https://www.redditstatic.com/desktop2x/vendors~Governance~Reddit.791bf381e13bfdc452ab.js#1)
    at com.gargoylesoftware.htmlunit.javascript.JavaScriptEngine$HtmlUnitContextAction.run(JavaScriptEngine.java:882)
    at net.sourceforge.htmlunit.corejs.javascript.Context.call(Context.java:624)
    at net.sourceforge.htmlunit.corejs.javascript.ContextFactory.call(ContextFactory.java:537)
    at com.gargoylesoftware.htmlunit.javascript.HtmlUnitContextFactory.callSecured(HtmlUnitContextFactory.java:354)
    at com.gargoylesoftware.htmlunit.javascript.JavaScriptEngine.compile(JavaScriptEngine.java:713)
    at com.gargoylesoftware.htmlunit.javascript.JavaScriptEngine.compile(JavaScriptEngine.java:679)
    at com.gargoylesoftware.htmlunit.javascript.JavaScriptEngine.compile(JavaScriptEngine.java:103)
    at com.gargoylesoftware.htmlunit.html.HtmlPage.loadJavaScriptFromUrl(HtmlPage.java:1104)
    at com.gargoylesoftware.htmlunit.html.HtmlPage.loadExternalJavaScriptFile(HtmlPage.java:984)
    at com.gargoylesoftware.htmlunit.html.HtmlScript.executeScriptIfNeeded(HtmlScript.java:361)
    at com.gargoylesoftware.htmlunit.html.HtmlScript$2.execute(HtmlScript.java:234)
    at com.gargoylesoftware.htmlunit.html.HtmlPage.initialize(HtmlPage.java:301)
    at com.gargoylesoftware.htmlunit.WebClient.loadWebResponseInto(WebClient.java:560)
    at com.gargoylesoftware.htmlunit.WebClient.getPage(WebClient.java:419)
    at com.gargoylesoftware.htmlunit.WebClient.getPage(WebClient.java:336)
    at com.gargoylesoftware.htmlunit.WebClient.getPage(WebClient.java:488)
    at com.gargoylesoftware.htmlunit.WebClient.getPage(WebClient.java:469)
    at RedditScraper.main(RedditScraper.java:40)

These are some of the first few errors


问:
Multi Query for inserting then deleting data
I am struggling to understand how multi queries work.

I want to insert data from one table into another, then delete the data from the original table. How can I do this? Is the method below viable?

<?php

$con =  mysqli_connect('localhost:3308','root','');

if(!$con)
{
    echo 'Not Connected To Server';
}

if(!mysqli_select_db($con, 'Database'))
{
    echo 'Database Not Selected';
}

$jobNumber = $_POST['jobNumberInsert'];
$siteName = $_POST['siteNameInsert'];
$phoneNumber = $_POST['phoneNoInsert'];
$firstName = $_POST['firstNameInsert'];
$lastName = $_POST['lastNameInsert'];
$streetAddress = $_POST['streetAddressInsert'];
$linetwoAddress = $_POST['linetwoAddressInsert'];
$city = $_POST['cityInsert'];
$county = $_POST['countyInsert'];
$postcode = $_POST['postcodeInsert'];
$serviceInfo = $_POST['serviceInfoInsert'];
$jobDate = $_POST['jobDateInsert'];
$priority_value = $_POST['priorityInsert'];

$sql = "INSERT INTO table2(jobNumber,siteName,phoneNumber,firstName,lastName,streetAddress,linetwoAddress,city,county,postcode,serviceInfo,jobDate,priority)
        VALUES ('$jobNumber','$siteName','$phoneNumber','$firstName','$lastName','$streetAddress','$linetwoAddress','$city','$county','$postcode','$serviceInfo','$jobDate','$priority_value')";

$sql .= "DELETE FROM table1 WHERE jobNumber= $jobNumber";

if(!mysqli_multi_query($con,$sql))
{
    echo 'Not Inserted or Deleted';
}
else
{
    echo 'Inserted and Deleted';
}

header("refresh:2 url=index.php");
?>
```

Currently upon executing the code nothing happens. When the statements are executed individually, then they work.

答:
Warning: You are wide open to SQL Injections and should use parameterized prepared statements instead of manually building your queries. They are provided by PDO or by MySQLi. Never trust any kind of input! Even when your queries are executed only by trusted users, you are still in risk of corrupting your data. Escaping is not enough!

Do not use mysqli_multi_query()!

You only have 2 queries, which are separate anyway. There's no need to send them together to MySQL.

```<code><?php
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$con = new mysqli('localhost:3308','root','', 'Database');
$con->set_charset('utf8mb4');

$stmt = $con->prepare('INSERT INTO table2(jobNumber,siteName,phoneNumber,firstName,lastName,streetAddress,linetwoAddress,city,county,postcode,serviceInfo,jobDate,priority)
VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?)');
$stmt->bind_param('sssssssssssss', $_POST['jobNumberInsert'],
    $_POST['siteNameInsert'],
    $_POST['phoneNoInsert'],
    $_POST['firstNameInsert']
    ...
);
$stmt->execute();

$stmtDel = $con->prepare('DELETE FROM table1 WHERE jobNumber=?');
$stmt->bind_param('s', $_POST['jobNumberInsert']);
$stmt->execute();

    header("refresh:2 url=index.php");
?>
</code>```

I also feel like you should wrap this in a transaction. If the delete fails, then it's likely you would like the insert to be rolled back too.

Body:
I am struggling to understand how multi queries work.

I want to insert data from one table into another, then delete the data from the original table. How can I do this? Is the method below viable?

<?php

$con =  mysqli_connect('localhost:3308','root','');

if(!$con)
{
    echo 'Not Connected To Server';
}

if(!mysqli_select_db($con, 'Database'))
{
    echo 'Database Not Selected';
}

$jobNumber = $_POST['jobNumberInsert'];
$siteName = $_POST['siteNameInsert'];
$phoneNumber = $_POST['phoneNoInsert'];
$firstName = $_POST['firstNameInsert'];
$lastName = $_POST['lastNameInsert'];
$streetAddress = $_POST['streetAddressInsert'];
$linetwoAddress = $_POST['linetwoAddressInsert'];
$city = $_POST['cityInsert'];
$county = $_POST['countyInsert'];
$postcode = $_POST['postcodeInsert'];
$serviceInfo = $_POST['serviceInfoInsert'];
$jobDate = $_POST['jobDateInsert'];
$priority_value = $_POST['priorityInsert'];

$sql = "INSERT INTO table2(jobNumber,siteName,phoneNumber,firstName,lastName,streetAddress,linetwoAddress,city,county,postcode,serviceInfo,jobDate,priority)
        VALUES ('$jobNumber','$siteName','$phoneNumber','$firstName','$lastName','$streetAddress','$linetwoAddress','$city','$county','$postcode','$serviceInfo','$jobDate','$priority_value')";

$sql .= "DELETE FROM table1 WHERE jobNumber= $jobNumber";

if(!mysqli_multi_query($con,$sql))
{
    echo 'Not Inserted or Deleted';
}
else
{
    echo 'Inserted and Deleted';
}

header("refresh:2 url=index.php");
?>

Currently upon executing the code nothing happens. When the statements are executed individually, then they work.

Body:
Warning: You are wide open to SQL Injections and should use parameterized prepared statements instead of manually building your queries. They are provided by PDO or by MySQLi. Never trust any kind of input! Even when your queries are executed only by trusted users, you are still in risk of corrupting your data. Escaping is not enough!

Do not use mysqli_multi_query()!

You only have 2 queries, which are separate anyway. There's no need to send them together to MySQL.

<?php
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$con = new mysqli('localhost:3308','root','', 'Database');
$con->set_charset('utf8mb4');

$stmt = $con->prepare('INSERT INTO table2(jobNumber,siteName,phoneNumber,firstName,lastName,streetAddress,linetwoAddress,city,county,postcode,serviceInfo,jobDate,priority)
VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?)');
$stmt->bind_param('sssssssssssss', $_POST['jobNumberInsert'],
    $_POST['siteNameInsert'],
    $_POST['phoneNoInsert'],
    $_POST['firstNameInsert']
    ...
);
$stmt->execute();

$stmtDel = $con->prepare('DELETE FROM table1 WHERE jobNumber=?');
$stmt->bind_param('s', $_POST['jobNumberInsert']);
$stmt->execute();

    header("refresh:2 url=index.php");
?>

I also feel like you should wrap this in a transaction. If the delete fails, then it's likely you would like the insert to be rolled back too.


问:
How to get Expo static deep link for development?
I need an Expo static deep link for development to use for Oauth redirect with a 3rd party ( Cognito )

I have used Linking.makeUrl() but this returns a deep link with a dynamic local ipaddress
exp://10.0.0.107:19000 that will not be consistent for other developers on the team.

The documentation at:
https://docs.expo.io/versions/latest/workflow/linking/#linking-module

Says the various environment links look like

Published app in Expo client :  exp://exp.host/@community/with-webbrowser-redirect

Published app in standalone :  myapp://

Development :  exp://wg-qka.community.app.exp.direct:80

I have tried that Development link but it fails to open.

答:
I have the similar issue too, here is my solution
Also post in https://github.com/aws-amplify/amplify-js/issues/4244#issuecomment-586845322

In case anyone still needs help for expo+amplify+social logins

app.json

{
  "expo": {
    "scheme": "exposchemeappname://"  // use any name you like, just make it unique
  }
}
```

App.js

<pre class="lang-js prettyprint-override"><code>import { Linking } from 'expo';
import * as WebBrowser from 'expo-web-browser';

import awsconfig from './aws-exports';

const amplifyConfig = {
  ...awsconfig,
  oauth: {
    ...awsconfig.oauth,
    urlOpener: async (url, redirectUrl) => {
      // On Expo, use WebBrowser.openAuthSessionAsync to open the Hosted UI pages.
      const { type, url: newUrl } = await WebBrowser.openAuthSessionAsync(url, redirectUrl);

      if (type === 'success') {
        await WebBrowser.dismissBrowser();

        if (Platform.OS === 'ios') {
          return Linking.openURL(newUrl);
        }
      }
    },
    options: {
      // Indicates if the data collection is enabled to support Cognito advanced security features. By default, this flag is set to true.
      AdvancedSecurityDataCollectionFlag: true
    },
  }
};

const expoScheme = "exposchemeappname://"
// Technically you need to pass the correct redirectUrl to the web browser.
let redirectUrl = Linking.makeUrl();
if (redirectUrl.startsWith('exp://1')) {
  // handle simulator(localhost) and device(Lan)
  redirectUrl = redirectUrl + '/--/';
} else
if (redirectUrl === expoScheme) {
  // dont do anything
} else {
  // handle the expo client
  redirectUrl = redirectUrl + '/'
}
amplifyConfig.oauth.redirectSignIn = redirectUrl;
amplifyConfig.oauth.redirectSignOut = redirectUrl;

Amplify.configure(amplifyConfig);
</code>```

Make sure you add the following redirect urls to amplify amplify auth update

# development
exp://127.0.0.1:19000/--/
exp://192.168.1.101:19000/ # depends on your lan ip

# expo client
exp://exp.host/@[EXPO_ACCOUNT]/[EXPO_APPNAME]/

# expo scheme for standalone
exposchemeappname://
```

Body:
I have the similar issue too, here is my solution
Also post in https://github.com/aws-amplify/amplify-js/issues/4244#issuecomment-586845322

In case anyone still needs help for expo+amplify+social logins

app.json

{
  "expo": {
    "scheme": "exposchemeappname://"  // use any name you like, just make it unique
  }
}

App.js

import { Linking } from 'expo';
import * as WebBrowser from 'expo-web-browser';

import awsconfig from './aws-exports';

const amplifyConfig = {
  ...awsconfig,
  oauth: {
    ...awsconfig.oauth,
    urlOpener: async (url, redirectUrl) => {
      // On Expo, use WebBrowser.openAuthSessionAsync to open the Hosted UI pages.
      const { type, url: newUrl } = await WebBrowser.openAuthSessionAsync(url, redirectUrl);

      if (type === 'success') {
        await WebBrowser.dismissBrowser();

        if (Platform.OS === 'ios') {
          return Linking.openURL(newUrl);
        }
      }
    },
    options: {
      // Indicates if the data collection is enabled to support Cognito advanced security features. By default, this flag is set to true.
      AdvancedSecurityDataCollectionFlag: true
    },
  }
};

const expoScheme = "exposchemeappname://"
// Technically you need to pass the correct redirectUrl to the web browser.
let redirectUrl = Linking.makeUrl();
if (redirectUrl.startsWith('exp://1')) {
  // handle simulator(localhost) and device(Lan)
  redirectUrl = redirectUrl + '/--/';
} else
if (redirectUrl === expoScheme) {
  // dont do anything
} else {
  // handle the expo client
  redirectUrl = redirectUrl + '/'
}
amplifyConfig.oauth.redirectSignIn = redirectUrl;
amplifyConfig.oauth.redirectSignOut = redirectUrl;

Amplify.configure(amplifyConfig);

Make sure you add the following redirect urls to amplify amplify auth update

# development
exp://127.0.0.1:19000/--/
exp://192.168.1.101:19000/ # depends on your lan ip

# expo client
exp://exp.host/@[EXPO_ACCOUNT]/[EXPO_APPNAME]/

# expo scheme for standalone
exposchemeappname://


问:
WooCommerce: CSS - Target specific product categories
I have added dropshaddow to product images in catalouge-pages. But i want to leave the products of the category "utility" out, so the pictures in this category do not have drop shaddow. (EDIT: so they don't have dropshaddow even if they are shown in another category where they also belong)
This is what I have to add to all products:

```<code>.woocommerce ul.products li.product a img {
    box-shadow: 0 0 14px #aaa !important;
}
</code>```

I'm trying to target the specific category:

```<code>.product-cat-utility ul.products li.product a img {
    box-shadow: 0 0 0 #aaa !important;
}
</code>```

It does not work, and I am hoping for a more elegant solution.
Thanks.

答:
The  on each category page contain unique classes, both the term id and term name

Try something like this

.woocommerce ul.products li.product a img {
    box-shadow: 0 0 14px #aaa !important;
}

.term-utility ul.products li.product a img, .myclass-utility ul.products li.product a img {
    box-shadow: 0 0 0 #aaa !important;
}
```

<p>add a custom body class for term (parent) utility and the childs</p>

<pre class="lang-php prettyprint-override"><code>function my_body_classes( $classes ) {
    global $post;

    if ( is_product_category() ) {
        $term_slug = 'utility';
        $taxonomy  = 'product_cat';
        $term_id   = get_term_by( 'slug', $term_slug, $taxonomy )->term_id; // Get the term ID
        $child_ids = get_term_children( $term_id, $taxonomy ); // Get the children terms IDs
        $terms_ids = array_merge( $child_ids, [$term_id] ); // an array of all term IDs (main term Id and it's children)

        if ( has_term( $terms_ids, $taxonomy, $post->ID ) ) {
            $classes[] = 'myclass-utility';
        }
    }

    return $classes;
}
add_filter( 'body_class','my_body_classes' );
</code>```

Body:
I have added dropshaddow to product images in catalouge-pages. But i want to leave the products of the category "utility" out, so the pictures in this category do not have drop shaddow. (EDIT: so they don't have dropshaddow even if they are shown in another category where they also belong)
This is what I have to add to all products:

.woocommerce ul.products li.product a img {
    box-shadow: 0 0 14px #aaa !important;
}

I'm trying to target the specific category:

.product-cat-utility ul.products li.product a img {
    box-shadow: 0 0 0 #aaa !important;
}

It does not work, and I am hoping for a more elegant solution.
Thanks.

Body:
The <body class="..."> on each category page contain unique classes, both the term id and term name

Try something like this

.woocommerce ul.products li.product a img {
    box-shadow: 0 0 14px #aaa !important;
}

.term-utility ul.products li.product a img, .myclass-utility ul.products li.product a img {
    box-shadow: 0 0 0 #aaa !important;
}

add a custom body class for term (parent) utility and the childs

function my_body_classes( $classes ) {
    global $post;

    if ( is_product_category() ) {
        $term_slug = 'utility';
        $taxonomy  = 'product_cat';
        $term_id   = get_term_by( 'slug', $term_slug, $taxonomy )->term_id; // Get the term ID
        $child_ids = get_term_children( $term_id, $taxonomy ); // Get the children terms IDs
        $terms_ids = array_merge( $child_ids, [$term_id] ); // an array of all term IDs (main term Id and it's children)

        if ( has_term( $terms_ids, $taxonomy, $post->ID ) ) {
            $classes[] = 'myclass-utility';
        }
    }

    return $classes;
}
add_filter( 'body_class','my_body_classes' );


答:
to see, what is the output:

(function() {
    var element,
        index,
        length,
        content = document.getElementById("content"),
        html = "",
        data = [{
            id: 1,
            name: "John",
            color: "green"
        }, {
            id: 2,
            name: "Sally",
            color: "pink"
        }, {
            id: 3,
            name: "Andrew",
            color: "blue"
        }, {
            id: 4,
            name: "Katie",
            color: "purple"
        }];

    for (index = 0; index < data.length; index++) {
        html +=
            '
' +
                '' + data[index].name + '' +
            '
';
    }

    content.innerHTML = html;
 })();```
<pre class="snippet-code-html lang-html prettyprint-override"><code><ul id="content">

</ul></code>```

Title: What this function on redraws and reflows is doing?

Body:
to see, what is the output:

(function() {
    var element,
        index,
        length,
        content = document.getElementById("content"),
        html = "",
        data = [{
            id: 1,
            name: "John",
            color: "green"
        }, {
            id: 2,
            name: "Sally",
            color: "pink"
        }, {
            id: 3,
            name: "Andrew",
            color: "blue"
        }, {
            id: 4,
            name: "Katie",
            color: "purple"
        }];

    for (index = 0; index < data.length; index++) {
        html +=
            '<li id="' + data[index].id + '" style="color: ' + data[index].color + '">' +
                '<strong>' + data[index].name + '</strong>' +
            '</li>';
    }

    content.innerHTML = html;
 })();

<ul id="content">

</ul>


问:
Check if props contain string or SVG
I pass props to a component that can be either string or an SVG. I want to render it conditionally based on the type.

This is what I tried:

const ProjectIcon = ({icon}) => { // icon can be an SVG or just a string string
  console.log("string: "+icon);
  console.log(typeof icon === "string"); // true for both string AND SVG
  console.log(typeof icon !== "string"); // false for both string AND SVG
  return (...) // return based on the type of props
}
```

<p>I import an SVG file or set a string variable in a distant parent component:</p>

<p><code>Parent.jsx</code></p>

```import svg from "./icon.svg";
import Parent from "./Parent.jsx";

const Parent = () => {
  return (
    <ProjectIcon icon={svg}>
  )
}
```

<p>I import this <code>icon.svg</code></p>

```<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" width="100%">
  <circle cx="50" cy="50" r="50"/>
</svg>
```

It seems like both types are interptreted like a string. How can I tell the difference in JavaScript / React?

答:
If your imported svg comes as a string you could parse it back into an object and check the type.

```<code>const icon1 = <svg...>...</svg>
const icon2 = 'some string'
JSON.parse(JSON.stringify(icon1)).type==='svg'// is true
JSON.parse(JSON.stringify(icon2)).type==='svg'// is false
</code>```

Otherwise an svg is just an object and typeof icon should give object or string accordingly. One could also check for the length which should be undefined for a svg. Check out the snippet below. The circle background color is blue for string and red for svg's.

function Tile(){
  const SVG = <svg viewBox="0 0 100 100" fill="grey">
  <circle cx="50" cy="50" r="30" /></svg>
  return

<Circle icon={SVG}/>

<Circle icon='test'/>

}
function Circle({icon}){
  return
{icon}

}
ReactDOM.render(<Tile/>, document.getElementById('root'))```
<pre class="snippet-code-css lang-css prettyprint-override"><code>.tile{ position: relative; display: inline-block; margin-left: 10px; width: 100px; height: 100px; background: orange; }
.circle{ position: absolute; top: 25px; left: 25px; width: 50px; height: 50px; border-radius: 50%; line-height: 50px; text-align: center; color: white; font-weight: bold; font-size: 20px; }</code>```

```

Title: Check if props contain string or SVG

Body:
I pass props to a component that can be either string or an SVG. I want to render it conditionally based on the type.

This is what I tried:

const ProjectIcon = ({icon}) => { // icon can be an SVG or just a string string
  console.log("string: "+icon);
  console.log(typeof icon === "string"); // true for both string AND SVG
  console.log(typeof icon !== "string"); // false for both string AND SVG
  return (...) // return based on the type of props
}

I import an SVG file or set a string variable in a distant parent component:

Parent.jsx

import svg from "./icon.svg";
import Parent from "./Parent.jsx";

const Parent = () => {
  return (
    <ProjectIcon icon={svg}>
  )
}

I import this icon.svg

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" width="100%">
  <circle cx="50" cy="50" r="50"/>
</svg>

It seems like both types are interptreted like a string. How can I tell the difference in JavaScript / React?

Body:
If your imported svg comes as a string you could parse it back into an object and check the type.

const icon1 = <svg...>...</svg>
const icon2 = 'some string'
JSON.parse(JSON.stringify(icon1)).type==='svg'// is true
JSON.parse(JSON.stringify(icon2)).type==='svg'// is false

Otherwise an svg is just an object and typeof icon should give object or string accordingly. One could also check for the length which should be undefined for a svg. Check out the snippet below. The circle background color is blue for string and red for svg's.

function Tile(){
  const SVG = <svg viewBox="0 0 100 100" fill="grey">
  <circle cx="50" cy="50" r="30" /></svg>
  return <div>
  <div className='tile'><Circle icon={SVG}/></div>
  <div className='tile'><Circle icon='test'/></div>
  </div>
}
function Circle({icon}){
  return <div style={{background: icon.length?'blue':'red'}} className='circle'>{icon}</div>
}
ReactDOM.render(<Tile/>, document.getElementById('root'))

.tile{ position: relative; display: inline-block; margin-left: 10px; width: 100px; height: 100px; background: orange; }
.circle{ position: absolute; top: 25px; left: 25px; width: 50px; height: 50px; border-radius: 50%; line-height: 50px; text-align: center; color: white; font-weight: bold; font-size: 20px; }

<div id='root'></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.6/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.6/umd/react-dom.production.min.js"></script>