argumenten in construct

Overzicht Reageren

Sponsored by: Vacatures door Monsterboard

Ozzie PHP

Ozzie PHP

11/03/2013 02:57:41
Quote Anchor link
Ola allemaal,

Ik ben aan het knutselen aan m'n service container en nu loop ik tegen het volgende aan:

Stel ik heb een config bestand met daarin de service 'foo_bar':

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
arguments:
    bar: abc
    foo: xyz

services:
    foo_bar:
        class    : FooBar
        arguments: [bar, foo]

De class foo verwacht zoals je kunt zien 2 argumenten, namelijk 'bar' en 'foo'.

Normaal gesproken als ik nu een object zou aanmaken, dan doe ik dat zo:
$foo_bar = new FooBar($bar, $foo);

Maar ik loop nu tegen het volgende aan:
Als ik de service foo_bar vanuit het configuratiebestand inlees, dan staan de 2 argumenten 'bar' en 'foo' in een array. Hoe moet ik die 2 argumenten vanuit de array nu meegeven aan de class FooBar?

Als ik dit doe $this->container->get('foo_bar'); dan zou er dus zoiets moeten gebeuren:

return new FooBar($arguments[0], $arguments[1]);

Maar nu is mijn vraag hoe ik die 2 argumenten tussen de 2 haakjes krijg. Nu zijn het 2 argumenten, maar het kunnen er natuurlijk ook meer of minder zijn. Iemand een idee?
 
PHP hulp

PHP hulp

28/11/2024 06:49:24
 
Erwin H

Erwin H

11/03/2013 11:39:33
 
Ozzie PHP

Ozzie PHP

11/03/2013 11:47:38
Quote Anchor link
Dankjewel voor de link Erwin! Ziet er wel best ingewikkeld uit.

Maar begrijp ik nu goed dat je dan voor het aanmaken van een object altijd die Reflection class gebruikt door middel van $reflecton->newInstance of $reflection->newInstanceArgs($arguments)? En heeft dat dan hetzelfde effect als wanneer ik $object = new Object(arguments) zou doen?
 
Erwin H

Erwin H

11/03/2013 12:00:19
Quote Anchor link
Uiteindelijk valt het wel mee met de complexiteit. Dit is hoe ik het volledig heb verpakt in mijn Instantiator_Class:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
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
<?php
  public function instantiate( $classname, array $arguments = array(), $error = '' ){    
    try{
      $reflection = new ReflectionClass( $classname );
      $constructor = $reflection->getConstructor();

      if ( $constructor === null ){
        //no constructor, instantiate
        $obj = $reflection->newInstance();
      }
else {
        //there is a constructor, how the object is instantiated depends on the
        //number of parameters and number of required parameters.

        if ( $constructor->getNumberOfParameters() == 0 ){
          $obj = $reflection->newInstance();
        }
elseif( $constructor->getNumberOfRequiredParameters() <= count( $arguments ) ){
          $obj = $reflection->newInstanceArgs( $arguments );
        }
else {
          //the number of given parameters doesn't match the number of needed
          //parameters, throw an exception because in this case no instance can
          //be created.

          throw new Exception();
        }
      }

      
      //return the object
      return $obj;
    }
catch( Exception $e ){
      throw new $this->exceptionClass( $error );
    }
  }

?>

Zoals je ziet maak ik het object nu aan via die reflection class die via newInstance (of newInstanceArgs) een object teruggeeft van het type dat ik heb aangevraagd. Dat obj wordt weer geretourneerd uit mijn Instantiator_Class en uiteindelijk heb ik in mijn applicatie dus het object dat ik nodig heb.
 
Ozzie PHP

Ozzie PHP

11/03/2013 12:07:38
Quote Anchor link
Ah oke, thanks :-)
Daar kan ik wel mee uit de voeten!

Ik denk dat ik zelf iets minder controles ga inbouwen... ik ben zelf de enige die het framework gebruikt. Als ik een verkeerd aantal argumenten opgeef dan zie ik het direct omdat er een PHP foutmelding zal volgen. Ik denk dat ik het zo doe: als er argumenten aanwezig zijn dan gebruik ik deze $reflection->newInstanceArgs( $arguments ) en als er geen argumenten zijn, dan deze $reflection->newInstance().
 
Erwin H

Erwin H

11/03/2013 12:26:30
Quote Anchor link
Bedenk wel dat als je newInstanceArgs aanroept met parameters, maar de class heeft geen constructor, dan zal je een foutmelding krijgen. Heeft de class wel een constructor (maar zonder parameters) dan lukt het wel gewoon. Vandaar dat ik die check erin heb gebouwd voor de constructor. Op zich werkt het nu namelijk altijd, mits er genoeg parameters zijn meegegeven. Meer dan nodig is nu geen probleem. Uiteraard kan je ervoor kiezen sommige exception gewoon te laten bestaan. mijn idee is echter dat ik dit ook in de toekomst met een gerust hart wil kunnen gebruiken en dan niet nog eens moet gaan bedenken waarom het opeens weer fout gaat. Maar dat is een keuze :-)
 
Ozzie PHP

Ozzie PHP

11/03/2013 12:33:57
Quote Anchor link
Ik snap wat je bedoelt. Maar ik probeer tegenwoordig niet meer zoals vroeger alles dicht te timmeren. Als ik een fout maak, dan loopt de boel de soep in en dan kom ik er vanzelf wel achter dat ik een fout heb gemaakt. Op sommige punten is het goed om iets te controleren, maar ik leg ook graag een stukje verantwoordelijkheid bij mezelf neer. Anders worden er continu allerlei controles uitgevoerd die in feite helemaal niet nodig zijn. Vroeger controleerde ik ook alles... werd er een boolean als argument verwacht, en gaf ik een int? BOEM, foutmelding. Nu denk ik daar anders over. Gewoon goed kijken wellk argument er wordt verwacht, even testen of het werkt zoals verwacht. Ja, dan prima. Nee, dan heb ik een foutje gemaakt: herstellen! Als het eenmaal werkt dan werkt het, en heb ik niet meer al die honderden controles per request nodig. Scheelt toch weer wat in de performance, en het houdt je scherp :)
 
Ozzie PHP

Ozzie PHP

12/03/2013 23:32:14
Quote Anchor link
Toch nog even hier op terugkomend...

Is zo'n reflection class altijd de beste manier om dynamisch een class aan te maken?

Is het beter/handiger dan bijvoorbeeld "call_user_func_array"?

En stel dat er geen argumenten zijn, is het dan ook beter/mooier om de reflection class te gebruiken in plaats van simpelweg zoiets:

$class = 'SomeClass';
$object = new $class();
 
Wouter J

Wouter J

12/03/2013 23:38:39
Quote Anchor link
Dat is alleen mooi wanneer je zeker weet dat je geen argumenten nodig hebt. Wanneer je toch al een Reflection klasse gebruikt kun je die net zo goed ook voor het initializen gebruiken.

En een klasse aanmaken met call_user_func_array, ik denk niet dat dat kan...
 
Ozzie PHP

Ozzie PHP

12/03/2013 23:40:44
Quote Anchor link
Oké... dan zal ik de refelction class gebruiken. Thanks :)

Alleen wat ik me afvraag... stel ik heb geen argumenten, zou het dan zonder reflection class sneller werken?
Gewijzigd op 12/03/2013 23:41:23 door Ozzie PHP
 
Wouter J

Wouter J

12/03/2013 23:45:09
Quote Anchor link
nee, want je hebt al een reflection class. En mocht je anders denken: benchmarken!
 
Ozzie PHP

Ozzie PHP

12/03/2013 23:48:18
Quote Anchor link
Ja, sorry... ik was niet helemaal duidelijk. Ik bedoelde meer...

Stel ik heb geen argumenten, dan doe ik dit:

$class = 'SomeClass';
$object = new $class();

En als ik wel argumenten heb dan gebruik ik de reflection class...
Ik zal eens even benchmarken en zo dadelijk laten weten wat sneller is... momentje...
 
Wouter J

Wouter J

12/03/2013 23:51:57
Quote Anchor link
Maar om te kijken of je wel of geen argumenten hebt gebruik je toch al een reflection?
 
Ozzie PHP

Ozzie PHP

12/03/2013 23:54:59
Quote Anchor link
Wouter J op 12/03/2013 23:51:57:
Maar om te kijken of je wel of geen argumenten hebt gebruik je toch al een reflection?

Nou, dat hoeft niet... stel ik zet bij een service in mijn configuratiebestand geen argumenten, dan hoef ik blijkbaar dus ook geen argumenten mee te geven aan de betreffende class.

Benchmark gedaan:

Conclusie... als je geen argumenten hebt, dan kun je beter NIET de reflection class gebruiken.

Ik heb 1000 loops uitgevoerd.

zonder reflection class: 0,00063
met reflection class: 0,00243

Scheelt toch wel wat...
 



Overzicht Reageren

 
 

Om de gebruiksvriendelijkheid van onze website en diensten te optimaliseren maken wij gebruik van cookies. Deze cookies gebruiken wij voor functionaliteiten, analytische gegevens en marketing doeleinden. U vindt meer informatie in onze privacy statement.