Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

laravel 5.1 - Dynamically create Class object based on string

i want to create object of class base on string which come from URL parameter.

for example :

 http://localhost/CSWeb/api/search/Slideshare

in above URL Slideshare is parameter which get in apiController->indexAction.

slideshare.php class

<?php

namespace App\Http\API;

class slideshare 
{

    public function index()
    {
         return 'any data'; 

    }

}

apiController.php

namespace App\Http\Controllers\API;

use Illuminate\Http\Request;
use App\Http\Requests;
use App\Http\Controllers\Controller;
use Auth;
use App\Http\API\Slideshare;

class apiController extends Controller
{

    public function index($source)
    {
        $controller=  new $source;
        return $controller->index();
        // if i change code to  $controller=  new Slideshare; it works fine
    }

}

laravel error when i use parameter string to create class object

FatalErrorException in apiController.php line 17: Class 'Slideshare' not found

if i change code to

$controller=  new Slideshare; it works fine

Thank you in advance

like image 700
Nishit Maheta Avatar asked Oct 29 '15 19:10

Nishit Maheta


1 Answers

When creating PHP objects with strings, you must provide the full qualified name of the class (a.k.a include the namespace). So, you should have something like this:

$className = 'App\\Http\\API\\' . $source;

$controller =  new $className;

return $controller->index();

Another way to do it, if you are sure that the class you want to instantiate lives in the same namespace as your code, you can use:

$className = __NAMESPACE__ . '\\' . $source;

$controller =  new $className;

return $controller->index();

A more elaborated way of achieving the same results is through the Factory Design Pattern. Basically you create a class that is responsible for instantiating elements, and you delegate the task of actually creating those objects to that class. Something along those lines:

class Factory {
  function __construct ( $namespace = '' ) {
     $this->namespace = $namespace;
  }

  public function make ( $source ) {
    $name = $this->namespace . '\\' . $source;

    if ( class_exists( $name ) ) {
      return new $name();
    }
  }
}


$factory = new Factory( __NAMESPACE__ );

$controller = $factory->make( $source );

The advantage of this approach is that the responsability of creating the objects now lies in the Factory, and if you ever need to change it, maybe allow for aliases, add some additional security measures, or any other thing, you just need to change that code in one place, but as long as the class signature remains, your code keeps working.

An interesting tutorial on factories: http://culttt.com/2014/03/19/factory-method-design-pattern/

Source: http://nl3.php.net/manual/en/language.oop5.basic.php#language.oop5.basic.new http://php.net/manual/en/language.namespaces.nsconstants.php

like image 70
Pedro M. Silva Avatar answered Nov 18 '22 00:11

Pedro M. Silva