[PHP] Url Query extract

Pagina: 1
Acties:

Acties:
  • 0 Henk 'm!

  • DannyBevers
  • Registratie: November 2009
  • Laatst online: 23:53
Hallo Devs!

Ben al een tijdje aan het puzzelen met een query voor mijn API. Deze wil ik op basis van de Facebook Graph API gaan doen aangezien ik zelf ook een Graph database heb is het voor mij tevens handig is om specifieke data terug te krijgen.

Waar ik nu echter op vast loop ondanks vele pogingen is het goed uit elkaar splitten van de url query die ik mee stuurt als data.

Dit is de data als volgt mee stuur.

code:
1
/me?fields=id,name,photos.limit(100){height,from}


Ik wil het op de volgende manier hebben namelijk. Alleen kreeg ik het ondanks vele pogingen met splitten van de data het niet voor elkaar.

code:
1
2
3
4
5
6
7
['me' => 
   ['fields' => 
      ['id', 'name', 'photos' => [
         'limit' => '100', ['height', 'from']
      ]
   ]
]


Ik heb zelf al de volgende pogingen gedaan om dit zo efficiënt te maken maar echt gelukt tot deze diepte is het niet gelukt.

Weet iemand hier raad mee om het alsnog voor elkaar te krijgen. Facebook heeft zijn eigen explorer waarbij je de query kan maken. In principe is mijn doel om eigenlijk alle lagen die hun kunnen dat ik die ook bij mijn eigen applicatie aan kan.

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
        function parseQuery()
    {
        $newoutput = [];
        $buffer = '';
        $depth = 0;
        $parent = '';
        $subParent = '';

        for( $i = 0; $i < strlen( $this->_input ); $i++ )
        {
            if( $this->_input[$i] == ',' )
            {
                if( strlen( $buffer ) )
                {
                    if( $depth == 0 )
                    {
                        $filters = explode( ".", $buffer );

                        $newoutput[$filters[0]] = [];

                        if( count( $filters ) > 1 )
                        {
                            $key = $filters[0];
                            array_shift( $filters );

                            foreach( $filters AS $filter )
                            {
                                $newoutput[$key][] = $filter;
                            }
                        }

                        $parent = $buffer;
                    }
                    else
                    {
                        $filters = explode( ".", $buffer );

                        $newoutput[$parent][] = $filters[0];

                        if( count( $filters ) > 1 )
                        {
                            $key = $filters[0];
                            array_shift( $filters );

                            foreach( $filters AS $filter )
                            {
                                $newoutput[$parent][$key][] = $filter;
                            }
                        }
                    }
                }

                $buffer = "";
            }
            elseif( $this->_input[$i] == '{' )
            {
                $filters = explode( ".", $buffer );

                $parent = $filters[0];

                $newoutput[$filters[0]] = [];

                if( count( $filters ) > 1 )
                {
                    $key = $filters[0];
                    array_shift( $filters );

                    foreach( $filters AS $filter )
                    {
                        $newoutput[$key][] = $filter;
                    }
                }

                $buffer = "";
                $depth++;
            }
            elseif( $this->_input[$i] == '}' )
            {
                $filters = explode( ".", $buffer );

                $newoutput[$parent][] = $filters[0];

                if( count( $filters ) > 1 )
                {
                    $key = $filters[0];

                    array_shift( $filters );

                    foreach( $filters AS $filter )
                    {
                        $newoutput[$parent][$key][] = $filter;
                    }
                }

                $buffer = "";
                $depth--;
            }
            else
            {
                $buffer .= $this->_input[$i];

                if( $i == strlen( $this->_input )-1 )
                {
                    if( strlen( $buffer ) )
                    {
                        if( $depth == 0 )
                        {
                            $filters = explode( ".", $buffer );

                            $newoutput[$filters[0]] = [];

                            if( count( $filters ) > 1 )
                            {
                                $key = $filters[0];
                                array_shift( $filters );

                                foreach( $filters AS $filter )
                                {
                                    $newoutput[$key][] = $filter;
                                }
                            }

                            $parent = $buffer;
                        }
                        else
                        {
                            $filters = explode( ".", $buffer );

                            $newoutput[$parent][] = $filters[0];

                            if( count( $filters ) > 1 )
                            {
                                $key = $filters[0];
                                array_shift( $filters );

                                foreach( $filters AS $filter )
                                {
                                    $newoutput[$parent][$key][] = $filter;
                                }
                            }
                        }
                    }
                }
            }
        }

        $this->_fields = array_keys( $newoutput );

        $this->_parssed = $newoutput;
    }

Acties:
  • 0 Henk 'm!

  • Ventieldopje
  • Registratie: December 2005
  • Laatst online: 19:53

Ventieldopje

I'm not your pal, mate!

Oei oei, kijk eens naar de functies explode en preg_match. Lijkt mij een veel betere en robuustere methode dan wat je nu probeert te doen. Voor hulp met regex kun je bijv regexr.com gebruiken.

Kijk ook nog eens naar je voorbeeld array, daar mix je een associative met index based elementen, lijkt me niet de bedoeling ;)

www.maartendeboer.net
1D X | 5Ds | Zeiss Milvus 25, 50, 85 f/1.4 | Zeiss Otus 55 f/1.4 | Canon 200 f/1.8 | Canon 200 f/2 | Canon 300 f/2.8


Acties:
  • 0 Henk 'm!

  • DannyBevers
  • Registratie: November 2009
  • Laatst online: 23:53
Zoiets had ik al verwacht, het bleef ook maar fout gaan met wat ik probeerde. Echter hoe zou de explode dan kunnen aangezien je bijvoorbeeld als je op een komma explode krijg je allerlei dingen die lagen dieper zitten.

Dat is namelijk niet zo handig, echter is mijn regex nog niet optimaal genoeg waardoor ik daar niet uit kwam. Echter zal ik er vanavond nog maar eens wat uren aan besteden aan regex om het te proberen.

Echter wat zou jou keuze zijn in de opbouw van de array, ik snap inderdaad dat index en associative elementen niet verstandig is om te combineren echter was ik daarin iets te huiverig.

Acties:
  • 0 Henk 'm!

  • DominicVonk
  • Registratie: Juni 2016
  • Laatst online: 07-11-2020
Hey, Dit is een opzet dat je dit resultaat kan behalen.

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
function parseURL($url) {
    $parsed = array();
    preg_match('/\/(.*?)\?(.*)/', $url, $match);
    $page = $match[1];
    $query = $match[2];
    $parsed[$page] = array();
    $query = explode('&', $query);
    $history = array();
    foreach($query as $q) {
        $q = preg_replace_callback('/{(.*?)}/', function($matches) use (&$history) {
            
            $name = ':' . sha1($matches[1]) . '';
            $history[$name] = explode(',', $matches[1]);
            return ($name);
        }, $q);
        $q = explode('=', $q);
        $field = $q[0];
        $value = $q[1];
        $parsed[$page][$field] = array();
        $values = explode(',', $value);
        foreach($values as $value) {
            if (strpos($value, '.') === false) {
                array_push($parsed[$page][$field], $value);
            } else {
                $values = explode('.', $value);
                $values = preg_replace_callback('/(.*?)\((.*?)\):(.{40})/', function($matches) use (&$history, &$parsed, $page, $field, $values) {
                    $parsed[$page][$field][$values[0]][$matches[1]] = $matches[2];
                    array_push($parsed[$page][$field][$values[0]], $history[':'. $matches[3]]);
                }, $values);
                
            }
        }
    }
    return $parsed; 
}


en met jouw url krijg je nu:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 {
    "me": {
        "fields": {
            "0": "id",
            "1": "name",
            "photos": {
                "limit": "100",
                "0": [
                    "height",
                    "from"
                ]
            }
        }
    }
}


Wat je kunt doen om de "," explode te fixen is hem er bijvoorbeeld eerder uithalen en later terugzetten.

[ Voor 11% gewijzigd door DominicVonk op 13-06-2016 15:55 ]


Acties:
  • 0 Henk 'm!

  • Hydra
  • Registratie: September 2000
  • Laatst online: 06-10 13:59
Normaliter POST je zulke search queries i.p.v. dit via een GET te doen. Dan kun je vanuit je client gewoon een JSON object samenstellen en die simpelweg aan je back-end kant weer deserializen.

Die baggercode hierboven is dan volledig overbodig (ervanuitgaande dat je in PHP fatsoenlijke JSON databind libraries hebt).

Mocht jet het perse via GET moeten doen dan kun je hetzelfde bereiken door de JSON data als base64-encoded string mee te sturen en die aan de achterkant eerst te decoden.

[ Voor 46% gewijzigd door Hydra op 13-06-2016 16:15 ]

https://niels.nu


Acties:
  • 0 Henk 'm!

  • DominicVonk
  • Registratie: Juni 2016
  • Laatst online: 07-11-2020
Hydra schreef op maandag 13 juni 2016 @ 16:13:
Normaliter POST je zulke search queries i.p.v. dit via een GET te doen. Dan kun je vanuit je client gewoon een JSON object samenstellen en die simpelweg aan je back-end kant weer deserializen.

Die baggercode hierboven is dan volledig overbodig (ervanuitgaande dat je in PHP fatsoenlijke JSON databind libraries hebt).

Mocht jet het perse via GET moeten doen dan kun je hetzelfde bereiken door de JSON data als base64-encoded string mee te sturen en die aan de achterkant eerst te decoden.
En je niet afhankelijk ben van 1 programmeertaal, dan zou je je back-end ook kunnen omschrijven zonder dat je een andere parser moet schrijven.

Acties:
  • 0 Henk 'm!

  • Ventieldopje
  • Registratie: December 2005
  • Laatst online: 19:53

Ventieldopje

I'm not your pal, mate!

Hydra schreef op maandag 13 juni 2016 @ 16:13:
Normaliter POST je zulke search queries i.p.v. dit via een GET te doen. Dan kun je vanuit je client gewoon een JSON object samenstellen en die simpelweg aan je back-end kant weer deserializen.

Die baggercode hierboven is dan volledig overbodig (ervanuitgaande dat je in PHP fatsoenlijke JSON databind libraries hebt).

Mocht jet het perse via GET moeten doen dan kun je hetzelfde bereiken door de JSON data als base64-encoded string mee te sturen en die aan de achterkant eerst te decoden.
En wat als je de zelfde zoek query wil herhalen (met de zelfde settings), dan is GET helemaal niet gek. Zie bijv. de zoekfunctie hier op GoT met url's als: http://gathering.tweakers...DDQUSrJL8hMDqksAPKjDWJrAQ.

JSON is inderdaad een betere oplossing, scheelt je een hoop werk vermoed ik zo. Maar goed, ik weet niet hoe de rest van je applicatie er uit ziet ;)

offtopic:
Baggercode, serieus.. gaan we zo doen? 8)7

www.maartendeboer.net
1D X | 5Ds | Zeiss Milvus 25, 50, 85 f/1.4 | Zeiss Otus 55 f/1.4 | Canon 200 f/1.8 | Canon 200 f/2 | Canon 300 f/2.8


Acties:
  • 0 Henk 'm!

  • Hydra
  • Registratie: September 2000
  • Laatst online: 06-10 13:59
Ventieldopje schreef op maandag 13 juni 2016 @ 23:52:
En wat als je de zelfde zoek query wil herhalen (met de zelfde settings), dan is GET helemaal niet gek. Zie bijv. de zoekfunctie hier op GoT met url's als: http://gathering.tweakers...DDQUSrJL8hMDqksAPKjDWJrAQ.
Ik zeg letterlijk dat base64 encoden van dat zoekobject en meesturen als GET query param ook een optie is! Daarnaast was ik er volgens mij vrij expliciet over dat het me ging om het zelf met de hand parsen van JSON. En ja dat is baggercode: het is onnodig, complex en de kans dat je fouten maakt is gewoon groot. Dat is een wiel dat je niet opnieuw uit wil vinden.

https://niels.nu


Acties:
  • 0 Henk 'm!

  • DannyBevers
  • Registratie: November 2009
  • Laatst online: 23:53
Dit is waardevolle informatie. In principe wil ik mijn applicatie over mijn eigen API laten lopen maar later ook koppelingen kunnen maken vanuit andere platformen. In principe wilde ik het dan zo makkelijk mogelijk maken doormiddel van precies aan te geven welke data je waarvan wilt en hoeveel je wilt.

Het is inderdaad wel wat complex als iemand ermee zal werken maar die keuze wil ik zelf het liefst wel zo hebben omdat ik denk dat hier voordelen uit te behalen zijn.

De applicatie bestaat uit een graph database waar alles netjes in uitgesplitst staat en dus ook met alle gemak de data uit kan halen op elke manier die ik zelf wil.

Zelf vond ik namelijk de Facebook methode aardig efficiënt werken, dit vooral omdat die ook gebruik maken van de graph methode in database vorm.

De structuur in base64 laten doorkomen ben ik opzicht wel mee eens dat het makkelijk zou zijn echter zien je dan niet meer wat je erheen stuurt waardoor je de controle voor een deel kwijt raakt. Echter hoeft dat niet perse als degene het zelf omzet naar base64 natuurlijk.

Heb inmiddels al structuur opgezet met de code van DominicVonk; dit om te kijken of het echt bruikbaar zal zijn om goed mee te kunnen werken. Aangezien deze niet oneindig in diepte kan op dit moment.

In ieder geval zeker heel erg bedankt, vooral de discussie die er voor een deel is ontstaan geeft wel waarde aan mijn manier hoe ik het beter of misschien anders kan doen.

Acties:
  • 0 Henk 'm!

  • kutagh
  • Registratie: Augustus 2009
  • Laatst online: 21:16
Is er eigenlijk een reden waarom je niet gebruik maakt van http://graphql.org/ ? Die is dan niet precies hetzelfde als de Facebook API, maar als ik dit zo lees heb je dat ook niet nodig? Voor graphql zijn er namelijk al PHP libraries beschikbaar zoals https://github.com/webonyx/graphql-php

Acties:
  • 0 Henk 'm!

  • Firefly III
  • Registratie: Oktober 2001
  • Niet online

Firefly III

Bedrijfsaccount Firefly III
-

[ Voor 113% gewijzigd door Firefly III op 21-10-2019 09:22 . Reden: Leeg ivm privacy ]

Hulp nodig met Firefly III? ➡️ Gitter ➡️ GitHub ➡️ Mastodon

Pagina: 1