5

I wish i knew how to search for this question / phrase it more appropriately. This hampered my search for prior questions; bear with me if this is a duplicate.

See the update / edits at the bottom of this post

Background / what i'm trying to do:

I have a URL that looks a lot like this:

http://myapp.com/calculate/$fileID/$calculateID

$fileID and $calculateID are keys that I use to keep track of a data set and something I call a 'calculation'. Essentially, that URL says perform $calculateID on the data in $fileID.

I go to my database (mongo) and ask for a php class name or sring or file path or what have you that matches $calculateID. For example's sake let's say the table looks like this:

 +-----+-------------------+
 | _id |     phpFile       |
 +-----+-------------------+
 |   1 | basicCalcs.php    |
 |   2 | advancedCalcs.php |
 |   3 | summaryCalcs.php  |
 +-----+-------------------+

Note: is is safe to assume that each file in the phpFile column has a common interface / set of public methods.

Example:

http://myapp.com/calculate/23/2

would go to the database, get the data from set 23 and then load up the functions in advancedCalcs.php. Once advancedCalcs.php has been loaded, a function within will receive the data. From there, a set of calculations and transformations are performed on the data.

My question

My question is what is a 'laravel 4 friendly' way to dynamically load up advancedCalcs.php and feed the data into a set of methods? Is there a way to lazy load this type of thing. Currently, i am only aware of the very unsophisticated require_once() method. I would really like to avoid this as i am convinced that laravel 4 has functionality to dynamically load an underlying class and hook it up to a common interface.

EDIT 1

Thanks to Antonio Carlos Ribeiro, i was able to make some progress.

After running dump-autoload command, my vendor/composer/autoload_classmap.php file has a few new entries that look like this:

'AnalyzeController' => $baseDir . '/app/controllers/AnalyzeController.php',
'AppName\\Calc\\CalcInterface' => $baseDir . '/app/calculators/CalcInterface.php',
'AppName\\Calc\\basicCalcs' => $baseDir . '/app/calculators/basicCalcs.php',

With code like the sample below, i can create an instance of the basicCalcs class:

$className = "AppName\\Calc\\basicCalcs";

$instance = new $className; 

var_dump($instance);

Where the basicCalcs.php file looks like this:

//PATH: /app/calculators/basicCalcs.php
<?php namespace Reporter\Calc;


class basicCalcs {


    public function sayHi(){
        echo("hello world! i am basicCalcs");
    }

};

?>

Updated question: How can i create an alias similar to the AnalyzeController entry in autoload_classmap.php rather than having to refer to basicCalcs.php with a full namespace?

2 Answers 2

6

Add your library folder to your composer.json autoload:

"autoload": {
    "classmap": [
        "app/commands",
        "app/controllers",
        "app/models",
        "app/extended",
        "app/calculators",  <------- This is where you put all your calculators
        "app/database/migrations",
        "app/database/seeds",
        "app/tests/TestCase.php"
    ]
},

Update your autoloaded classes:

composer dump-autoload

If you want to be sure it did worked, check if your classes are autoloaded opening the file

vendor/composer/autoload_classmap.php

To instantiate them dinamically you better have this as a table class names:

+-----+-------------------+-------------------+
| _id |     phpFile       |  namespace        |
+-----+-------------------+-------------------+
|   1 | basicCalcs        | Reporter\Calc\    |
|   2 | advancedCalcs     | Reporter\Calc\    |
|   3 | summaryCalcs      | Reporter\Calc\    |
+-----+-------------------+-------------------+

Then you just have to use it

class CalculateController extends Controller {

    public function calculate($fileID, $calculateID)
    {
        $file = phpFile::find($fileID);

        $className = $file->namespace . $file->phpFile;

        $calculator = new $className; //// <--- this thing will be autoloaded

        return $calculator->calculate( $calculateID );
    }

}

I'm assuming your calculators are all:

class basicCalcs {

    public function calculate($calculateID)
    {
        return performCalculation( $calculateID ); /// something like this
    }

}

And your router is somethink like

Route::get('/calculate/{fileID}/{calculateID}', array('as'=>'calculate', 'uses'=>'CalculateController@calculate'));
Sign up to request clarification or add additional context in comments.

8 Comments

Thanks. I see waht you're trying to do, but the find() method does not exist in laravel 4's Filesystem class. I can't seem to find much mention of it on php.net, either. I was able to get what i needed by doing this $className = "The\\Namespace\\path\\Inautoload_classmap.php"; $instance = new $className; This works but is there any way i set up aliases for the namespace?
Sorry about that File::, I changed it to phpFile to be clearer, because it should be your phpFile model, where you store your filenames. As long as your classes are appearing in the autoload_classmap.php file, you don't need the namespaces, unless you need them to organize your code, of course.
namespace is required if you want to use psr0.
Ah, Antonio, i understand now. My classes are appearing in the autoload file, but only by namespace. I have updated my original post to reflect this. I can load up the class by referring to it with it's full namespace, so i might end up just storing that in the database
I think you have two options: add the namespace '<?php namespace Reporter\Calc;' to your controller and then refer to it also in your routes or $class = 'Reporter\Calc\' . $file->phpFile;. Just edited to support your namespaces.
|
1

In Laravel4 the file composer.json is responsible for this, following is an example

{
    "require": {
        "laravel/framework": "4.0.*"
    },
    "autoload": {
        "classmap": [
            "app/commands",
            "app/controllers",
            "app/models",
            "app/database/migrations",
            "app/database/seeds",
            "app/tests/TestCase.php"
        ]
    },
    "scripts": {
        "post-update-cmd": "php artisan optimize"
    },
    "config": {
        "preferred-install": "dist"
    },
    "minimum-stability": "dev"
}

Notice the autoload section where classmap is used to to tell laravel4 from which folders it should load classes and also which file should it load. For example, "app/controllers", will be used to load all classes from the app/controllers folder and "app/tests/TestCase.php" will make Laravel4 to autoload the class TestCase.php from app/tests/ folder. So, add your library folder in to the classmap section. Once you have added your folder path in autoload -> classmap section then you have to run

composer dumpautoload // or
composer dump-autoload

from the command line.

1 Comment

Thanks; this got me going in the right direction. my original question has been updated to reflect where i am now getting stuck.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.