[Laravel] Onverwacht reultaat van sortBy()

Pagina: 1
Acties:

Vraag


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Als oefening voor mezelf probeer ik een adres boek te maken met Laravel. Als ik mijn adres lijst wil sorteren krijg ik niet het resultaat dat ik verwacht. ik heb de volgende code in mijn controller:
PHP:
1
2
3
4
5
public function test(){
        $adres = Adres::all()->sortBy( 'surname' );
        return View::make('adres.test')
                    ->with('adres', $adres);
    }

en in mijn view dit:
PHP:
1
2
3
4
5
6
7
@section('content')
 <div class="col-md-10 table-responsive">   
    @foreach ($adres as $test)
        {{ $test->surname }}<br>
    @endforeach
 </div> 
@stop

Als resultaat krijg ik een achternamen lijst met eerst alle namen met 1 woord, dan alle namen met 2 woorden, daarna alle namen met 3 woorden. dus zoiets als:
  • Akkermans
  • ...
  • Wagenaar
  • de Bekker
  • ...
  • van Zeeland
  • van den Heuvel
  • ...
  • van der Zee
Mijn verwachting is dat een spatie tussen de letters niet uit maakt voor de manier van sorteren. Als ik met phpMyadmin naar de dataset kijk en sorteer dan krijg ik wel de achternamen gesorteerd zoals ik zou verwachten. Ik heb geprobeerd dit te googelen maar vind niks. (Kan er ook aan liggen dat ik geen goede steek woorden kan verzinnen)
Waarom wordt er op deze manier gesorteerd en voor kom ik het?

Beste antwoord (via Verwijderd op 21-01-2016 19:31)


  • Barryvdh
  • Registratie: Juni 2003
  • Nu online
Je kan ook een flag meegeven om case insensitive te sorteren:

PHP:
1
Adres::all()->sortBy('surname', SORT_STRING | SORT_FLAG_CASE)


Zie http://php.net/manual/en/function.sort.php

Maar in dit geval kan je ook via MySQL sorteren, dat is waarschijnlijk efficienter ook.

[ Voor 46% gewijzigd door Barryvdh op 21-01-2016 11:14 ]

Alle reacties


Acties:
  • 0 Henk 'm!

  • naam
  • Registratie: Oktober 2007
  • Laatst online: 13:07
De spatie maakt inderdaad niet uit, de hoofdletters (A, B, C.., W) tov de kleine letters (d, v) wel. Dit komt omdat het sorteren op volgorde van de ASCII waarde van een letter gebeurt, waarin hoofdletters een lagere waarde hebben dan kleine letters (A-Z: 65 t/m 90, a-z: 97 t/m 122).

zie: http://www.asciitable.com/index/asciifull.gif

Laravel doet na het aanmaken van de collectie (Adres::all()) zijn eigen sorteermethode uitvoeren over deze collectie, dus niet tegen de database aan. PMA doet wel de sortering in de query. MySQL kijkt vervolgens niet naar hoofdletters (vermoedelijk bouwt die een index op met alleen kleine, of alleen hoofdletters).

Voor laravel zou je het volgende kunnen gebruiken: (niet getest, maar zou moeten werken)
PHP:
1
2
3
4
5
public function test() {
  $adres = Adres::sortBy('surname')->get();
  return View::make('adres.test')
                   ->with('adres', $adres);
}

[ Voor 46% gewijzigd door naam op 21-01-2016 09:10 ]


Acties:
  • Beste antwoord
  • 0 Henk 'm!

  • Barryvdh
  • Registratie: Juni 2003
  • Nu online
Je kan ook een flag meegeven om case insensitive te sorteren:

PHP:
1
Adres::all()->sortBy('surname', SORT_STRING | SORT_FLAG_CASE)


Zie http://php.net/manual/en/function.sort.php

Maar in dit geval kan je ook via MySQL sorteren, dat is waarschijnlijk efficienter ook.

[ Voor 46% gewijzigd door Barryvdh op 21-01-2016 11:14 ]


Acties:
  • 0 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
naam schreef op donderdag 21 januari 2016 @ 09:07:
De spatie maakt inderdaad niet uit, de hoofdletters (A, B, C.., W) tov de kleine letters (d, v) wel. Dit komt omdat het sorteren op volgorde van de ASCII waarde van een letter gebeurt, waarin hoofdletters een lagere waarde hebben dan kleine letters (A-Z: 65 t/m 90, a-z: 97 t/m 122).
Nou ben ik niet bekend met Laravel, maar als de "ordering" gedaan wordt door de DB (MySQL in dit geval) is bovenstaande alleen van toepassing als je een "CS collation" (ofwel: case-sensitive collation (bijv. utf8_general_cs)) gebruikt voor je DB (of specifieke tabel daarvan).
naam schreef op donderdag 21 januari 2016 @ 09:07:
MySQL kijkt vervolgens niet naar hoofdletters (vermoedelijk bouwt die een index op met alleen kleine, of alleen hoofdletters).
Again: dat is dus afhankelijk van je collation; "normaal" (of "by default") is dat een CI (case-INsensitive) collation (bijv. utf8_general_ci).

Waarom laravel dan vervolgens daar leuk nog eens z'n eigen ordering overheen gooit is me een raadsel, maar ik ben dus niet bekend met laravel en misschien is 't daar wel heel gewoon. Raar vind ik 't wel; als ik (bij wijze van) 10K records selecteer gaat eerst m'n DB al 't sorteerwerk doen en vervolgens gaat Laravel nog eens datzelfde werk verrichten (en erger: ongedaan maken)? Okee...

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Acties:
  • 0 Henk 'm!

  • naam
  • Registratie: Oktober 2007
  • Laatst online: 13:07
RobIII schreef op donderdag 21 januari 2016 @ 11:21:
[...]

Nou ben ik niet bekend met Laravel, maar als de "ordering" gedaan wordt door de DB (MySQL in dit geval) is bovenstaande alleen van toepassing als je een "CS collation" (ofwel: case-sensitive collation (bijv. utf8_general_cs)) gebruikt voor je DB (of specifieke tabel daarvan).


[...]

Again: dat is dus afhankelijk van je collation; "normaal" (of "by default") is dat een CI (case-INsensitive) collation (bijv. utf8_general_ci).

Waarom laravel dan vervolgens daar leuk nog eens z'n eigen ordering overheen gooit is me een raadsel, maar ik ben dus niet bekend met laravel en misschien is 't daar wel heel gewoon. Raar vind ik 't wel; als ik (bij wijze van) 10K records selecteer gaat eerst m'n DB al 't sorteerwerk doen en vervolgens gaat Laravel nog eens datzelfde werk verrichten (en erger: ongedaan maken)? Okee...
Collations ben ik niet heel bekend mee. Maar wat hier eigenlijk tegen Laravel gezegd word is het volgende:
1) Haal alle records op uit de 'adressen' tabel
2) sorteer deze

Hierdoor gaat Laravel dus zijn eigen collection sorteren, op zn eigen manier. Ik ben het eens dat het veel efficienter is om dit door de database te laten doen. Maar dat is niet wat er hier gebeurt.

Hierbij word er dus niet eerst een order by gedaan tegen de database. De enige sortering is die van Laravel

[ Voor 3% gewijzigd door naam op 21-01-2016 11:36 ]


Acties:
  • 0 Henk 'm!

  • Barryvdh
  • Registratie: Juni 2003
  • Nu online
RobIII schreef op donderdag 21 januari 2016 @ 11:21:
[...]

Waarom laravel dan vervolgens daar leuk nog eens z'n eigen ordering overheen gooit is me een raadsel, maar ik ben dus niet bekend met laravel en misschien is 't daar wel heel gewoon. Raar vind ik 't wel; als ik (bij wijze van) 10K records selecteer gaat eerst m'n DB al 't sorteerwerk doen en vervolgens gaat Laravel nog eens datzelfde werk verrichten (en erger: ongedaan maken)? Okee...
Zoals naam al zegt, zodra je de query uitvoert (met all() of get() bijv.), krijg je een Collection terug, met een aantal methodes: https://laravel.com/docs/5.2/collections#available-methods

Via MySQL sorteren doe je dus op de QueryBuilder, niet op de Collection achteraf, zie https://laravel.com/docs/...grouping-limit-and-offset

Het is daar dus orderBy() in plaats van sortBy().
PHP:
1
Adres::orderBy('surname')->get();

Acties:
  • 0 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Barryvdh schreef op donderdag 21 januari 2016 @ 11:37:
Zoals naam al zegt, zodra je de query uitvoert (met all() of get() bijv.), krijg je een Collection terug, met een aantal methodes: https://laravel.com/docs/5.2/collections#available-methods

Via MySQL sorteren doe je dus op de QueryBuilder, niet op de Collection achteraf, zie https://laravel.com/docs/...grouping-limit-and-offset

Het is daar dus orderBy() in plaats van sortBy().
PHP:
1
Adres::orderBy('surname')->get();
Ah; that 'splains it :P
(Ik vrees dat ik verwend ben met IQueryables en deferred execution :X De ::All() voert de query natuurlijk al uit)

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Bedankt voor de reacties. Ik had over het hoofd gezien dat de tussenvoegsels met kleine letters geschreven zijn geschreven en de naam met een hoofdletter. (dat was erg consequent gedaan) Daarom kwamen ze dus onder aan de lijst. voor mij is het dan ook voldoende om niet hoofdletter gevoelig te sorteren. dat ging het makkelijkst op de manier die Barryvdh voorstelt.

PHP:
1
Adres::all()->sortBy('surname', SORT_STRING | SORT_FLAG_CASE)
Pagina: 1