Code Monkey home page Code Monkey logo

laroute's Introduction

Laroute

Laravel has some pretty sweet helper functions for generating urls/links and its auto-json-magic makes it building APIs super easy. It's my go-to choice for building single-page js apps, but routing can quickly become a bit of a pain.

Wouldn't it be amazing if we could access our Laravel routes from JavaScript?

This package allows us to port our routes over to JavaScript, and gives us a bunch of very familiar helper functions to use.

Laroute in action

Installation

Install the usual composer way.

composer.json
{
	"require" : {
		"lord/laroute" : "2.*"
	}
}

n.b Laravel 4.x users, check out version 1.3.2

app/config/app.php
	...
	
	'providers' => array(
		...
		Lord\Laroute\LarouteServiceProvider::class,
	],
	
	...

Configure (optional)

Copy the packages config files.

php artisan vendor:publish --provider='Lord\Laroute\LarouteServiceProvider'
app/config/packages/lord/laroute/config.php
return [

    /*
     * The destination path for the javascript file.
     */
    'path' => 'public/js',

    /*
     * The destination filename for the javascript file.
     */
    'filename' => 'laroute',

    /*
     * The namespace for the helper functions. By default this will bind them to
     * `window.laroute`.
     */
    'namespace' => 'laroute',

    /*
     * Generate absolute URLs
     *
     * Set the Application URL in config/app.php
     */
    'absolute' => false,

    /*
     * The Filter Methode
     *
     * 'all' => All routes except "'laroute' => false"
     * 'only' => Only "'laroute' => true" routes
     * 'force' => All routes, ignored "laroute" route parameter
     */
    'filter' => 'all',

    /*
     * Action Namespace
     *
     * Set here your controller namespace (see RouteServiceProvider -> $namespace) for cleaner action calls
     * e.g. 'App\Http\Controllers'
     */
    'action_namespace' => '',

    /*
     * The path to the template `laroute.js` file. This is the file that contains
     * the ported helper Laravel url/route functions and the route data to go
     * with them.
     */
    'template' => 'vendor/lord/laroute/src/templates/laroute.js',
    
    /*
     * Appends a prefix to URLs. By default the prefix is an empty string.
    *
    */
    'prefix' => '',

];

    

Generate the laroute.js

To access the routes, we need to "port" them over to a JavaScript file:

php artisan laroute:generate

With the default configuration, this will create a public/js/laroute.js file to include in your page, or build.

<script src="/js/laroute.js"></script>

Note: You'll have to laroute:generate if you change your routes.

JavaScript Documentation

By default, all of the functions are under the laroute namespace. This documentation will stick with this convention.

action

Generate a URL for a given controller action.

/** 
 * laroute.action(action, [parameters = {}])
 *
 * action     : The action to route to.
 * parameters : Optional. key:value object literal of route parameters.
 */

laroute.action('HomeController@getIndex');

route

Generate a URL for a given named route.

/**
 * laroute.route(name, [parameters = {}])
 *
 * name       : The name of the route to route to.
 * parameters : Optional. key:value object literal of route parameters.
 */
 
 laroute.route('Hello.{planet}', { planet : 'world' });

url

Generate a fully qualified URL to the given path.

/**
 * laroute.url(name, [parameters = []])
 *
 * name       : The name of the route to route to.
 * parameters : Optional. value array of route parameters.
 */
 
 laroute.url('foo/bar', ['aaa', 'bbb']); // -> /foo/bar/aaa/bbb

link_to

Generate a html link to the given url.

/**
 * laroute.link_to(url, [title = url, attributes = {}]])
 *
 * url        : A relative url.
 * title      : Optional. The anchor text to display
 * attributes : Optional. key:value object literal of additional html attributes.
 */
 
 laroute.link_to('foo/bar', 'Foo Bar', { style : "color:#bada55;" });

link_to_route

Generate a html link to the given route.

/**
 * laroute.link_to_route(name, [title = url, parameters = {}], attributes = {}]]])
 *
 * name       : The name of the route to route to.
 * title      : Optional. The anchor text to display
 * parameters : Optional. key:value object literal of route parameters.
 * attributes : Optional. key:value object literal of additional html attributes.
 */
 
 laroute.link_to_route('home', 'Home');

link_to_action

Generate a html link to the given action.

/**
 * laroute.link_to_action(action, [title = url, parameters = {}], attributes = {}]]])
 *
 * action     : The action to route to.
 * title      : Optional. The anchor text to display
 * parameters : Optional. key:value object literal of route parameters.
 * attributes : Optional. key:value object literal of additional html attributes.
 */
 
 laroute.link_to_action('HelloController@planet', undefined, { planet : 'world' });

PHP Documentation

Ignore/Filter Routes

By default, all routes are available to laroute after a php artisan laroute:generate. However, it is sometimes desirable to have laroute ignore certain routes. You can do this by passing a laroute route option.

Route::get('/ignore-me', [
    'laroute' => false,
    'as'      => 'ignoreme',
    'uses'    => 'IgnoreController@me'
]);

Route::group(['laroute' => false], function () {
    Route::get('/groups-are-super-useful', 'GroupsController@index');
});

Licence

View the licence in this repo.

laroute's People

Contributors

aaronlord avatar anahkiasen avatar crinsane avatar dallincoons avatar danny-dtcmedia avatar dbpolito avatar jipe47 avatar jscarmona avatar killtw avatar laravel-shift avatar lukepolo avatar martdegraaf avatar mputkowski avatar omranic avatar reecss avatar rtheunissen avatar schnoop avatar sschlein avatar tvbeek avatar xeno010 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

laroute's Issues

Setup Travis CI

There are tests but they aren't run on every build, this would prevent syntax error bugs and stuff.

https url issue

i want to get https URL when i call route method. but it always return http one.. i tried both absolute true and false. but didn't work.. my rootUrl is also have https...

Note: my site only works in https, http one always redirect to something not related to this project(i have added it, as i want. don't think about that :D )

current config...

var routes = {

            absolute: true,
            rootUrl: 'https://sub.example.com',

....

Filter of hidden routes is not working

The filter method of laroute => false is not working. I triple-checked. I have setted in configs 'filter' => 'all' property, and at route groups / single routes I give an array with "laroute" => false, generate a new javascript, but anyway...it includes even routes with "laroute => false" value...

Check for prefix in getCorrectUrl()

When the Laravel app is hosted at a subdirectory on the webserver and no prefix is set, the returned URL has a / prepended, forcing the URL to become absolute.

Line 85:

            getCorrectUrl: function (uri) {
                    var url = this.prefix + '/' + uri.replace(/^\/?/, '');

I changed to:

            getCorrectUrl: function (uri) {
                if( this.prefix != "")
                    var url = this.prefix + '/' + uri.replace(/^\/?/, '');
                else
                    var url = uri.replace(/^\/?/, '');

I'm certain that can be implemented better but it resolved the problem for me.

Getting generator error in laravel.

Hey,

Just setting up the package on L4 and when I go to do php artisan generate:laroute I get an error. It seems like it is conflicting with Jeffrey Way's Laravel Generators maybe? This is the error:

"[InvalidArgumentException]
Command "generate:laroute" is not defined."

Is this an error at my side?

Invalid release?

I see you have a 5.2 tag that was created by mistake I believe, it's currently making Composer not pick up the latest release (because for him 5.2 is the latest), should that tag be removed maybe?

invalid unicode escape sequence

After generating the file and viewing the page I have spotted an error. An error is to do with an invalid Unicode escape sequence. After searching for the bug in the laroute.js file I spotted that JS was trying to scape "\u" in the action part of the route statement.

Whilst I have hardcoded the fix for myself - it might be of benefit to adjust getRouteInformation() method to handle any backslashes within an action.

    /**
     * Get the route information for a given route.
     *
     * @param $route \Illuminate\Routing\Route
     * @param $filter string
     * @param $namespace string
     *
     * @return array
     */
    protected function getRouteInformation(Route $route, $filter, $namespace)
    {
        $host    = $route->domain();
        $methods = $route->methods();
        $uri     = $route->uri();
        $name    = $route->getName();
        $action  = $route->getActionName();
        $laroute = array_get($route->getAction(), 'laroute', null);

        if(!empty($namespace)) {
            $a = $route->getAction();

            if(isset($a['controller'])) {
                $action = str_replace($namespace.'\\', '', $action);
            }
        }
		
	// escape backslashes
        $action = addslashes($action); 
        
        switch ($filter) {
            case 'all':
                if($laroute === false) return null;
                break;
            case 'only':
                if($laroute !== true) return null;
                break;
        }

        return compact('host', 'methods', 'uri', 'name', 'action');
    }

The use of preg_replace to generate the .js file might leak special characters in Javascript

Let's say we have this route

Route::get('/something', [
    'laroute' => true,
    'as' => 'something',

     // Note the lowercase u from user@..., typically this value 
     // starts with an uppercase letter and the following problem won't apply
    'uses' => 'user@someMethod'
]);

At some point the value of uses from above will end up in an array

array:2 [
    //...
    "action" => "App\Http\Controllers\user@someMethod"
    //...
]

Later on that piece will end up being json_encodeed, which will generate a string containing

... App\\Http\\Controllers\\user@someMethod ...

When converted to json, the backslashes are escaped, as expected.

Ultimately, this json will end up being replaced in the template via preg_replace, However, that double backslash \\ will end up being a single \ backslash afterwards

To use backslash in replacement, it must be doubled ("\\" PHP string). link

Thus, in the file generated from routes.js template, that json will look like

... App\Http\Controllers\user@someMethod ...

In this case, the \u will be interpreted by Javascript as the start of a unicode escape sequence, and since it isn't followed by a hex number, it will trigger an error:

SyntaxError: malformed Unicode character escape sequence

Similar stuff might also happen with \b, \f, \n, \r, \t, \v

If it was up to me I would simply use a str_ireplace instead, in TemplateCompiler, which would preserve the escaped backslashes until the end, but I am not sure if I'm missing some other reason why preg_replace was used.

Don't force user to pass an object

Currently Laroute behaves the same way as the UrlGenerator, but there is one caveat. While in PHP you don't have to specify the name of the arguments, in Laroute you do:

URL::route('users.show', 3); // foo.com/users/3
laroute.route('users.show', {user: 3}); // foo.com/users/3
laroute.route('users.show', 3); // foo.com/users/{users}?3

Could this difference of behavior be fixed?

toJSON should be toJson

There is a typo in the toJson method call in the command.

It should be written "toJson" instead of "toJSON"

[Question] Include a vue plugin?

This is not an issue per se, but since Laravel includes Vue by default, it would be nice to have a laroute Vue plugin available in this package. I have just written one and wanted to ask whether you are interested in including it as an additional template, defaulting to the current laroute.js implementation. You can find the gist right here: https://gist.github.com/Radiergummi/08152f9e6e1f87b57d7acc017a33fdd9

Currently, it does the following things:

  • Add a new $router property to Vue instances that has the methods route() , action(), url(), link_to() , link_to_route(), link_to_action() and match() available
  • Add a new router-link component to Vue that is available globally and works much like the one from vue-router

I'm still working on it for my current project, but if you're interested in adding it to Laroute, I'd be happy to share the source once it's finished and tested.

Method .route mutating params object

const params = { id: 1 }
Laroute.route(route, params)
console.log(params) // > {}

Hi, I've experienced a bug when by using route method and passing object with params to it, I get my object kinda destroyed. This issue is occurs in the replaceNamedParameters() I believe.

@aaronlord

can't install for laravel 6.13.

I am trying to install the package via composer. but received an error

  • don't install illuminate/filesystem v5.7.9|don't install laravel/framework v6.13.1

  • Installation request for laravel/framework (locked at v6.13.1, required as ^6.2) -> satisfiable by laravel/framework[v6.13.1].

Determine Root URL at runtime rather than at time of generation.

Currently, rootUrl is compiled from APP_URL when laroute:generate is executed. As far as I can tell, rootUrl is only ever used when laroute.absolute is false (default). Otherwise, it is not needed.

Using relative path generation assumes URIs are mounted under the domain name, not considering an application that might be hosted in a subdirectory of that domain. Laravel's UrlGenerator doesn't care much about this because it relies on Symfony's Request to generate a correct URI up to the point it takes over. Using absolute URLs when generating is a way around this since JavaScript has no way of telling the difference between what's a subdirectory and what's route.

Here's my specific problem:

  • I do local development on an application and I serve it from http://local.dev.
  • My production environment is hosted from http://example.org/application.
  • I use webpack to handle the bundling of the resultant laroute.js file generated by this package. I do not bundle assets in production; thus, the only .env available at compile-time is my local one.

So, if I pack everything up locally and use absolute URLs, I end up with a production application attempting to query http://local.dev/generated/path when in fact, I want http://example.org/application/generated/path. Previous to discovering this package, I was doing something fairly similar: creating a JavaScript object populated with data from the backend. The difference was that I didn't need to support parameterized routes during prototyping and now I do, so I'm delighted to find this package! 😁

However, I would like to contribute a means of determining root URL at runtime, based on either the .env#APP_URL configuration OR by generating it and disregarding what is in .env#APP_URL.

All this to say, would you be interested in such a contribution and if so, do you have any specific constraints towards development? I've got a local patch that works for me but it requires something like this in my base template (which actually works alright and is reasonable, to me):

<script src="{{ asset("public/js/laroute.js") }}"></script>
<script>
    laroute.config.rootUrl = "{{ env('APP_URL') }}"
</script>

Essentially, exposing configuration to userland to be changed at runtime, while also allowing compile-time generation from your published vendor configuration.

Grouped routes

It would be nice to be to defined route groups, each group would get exported to a different file.

I'd personally find it handy since it wouldn't expose urls i use in the admin to the general users.

Config
Add a groups array, the keys in that array would be the group names, while the value would map to the filename/location

Route definition

Map default group:

'laroute' => true

Map to a defined group:

'laroute' =>'groupName'

Doing it this way would be backwards-compatible.

If you need help implementing this I'm willing to submit a PR

New release with fix for urls

I pulled down the latest version of laroute and got an issue with invalid urls. I see that you have fixed this in your recent commits but have not pushed a new release for this yet. A new release with these fixes would be appreciated 👍

Laravel laroute generate uri in index should be empty

Laroute generate index in laravel route->controller should be empty, but it's returning "/index".

e.g:

$route->controller('admin', 'AdminController', [
    'getIndex' => 'admin.index',
    'getPayment' => 'admin.payment'
]);

The uri in getIndex is returning "admin/index", but the correct should be only "admin" if I don't pass any parameters in controller.

Typo in LayoutServiceProvide::registerCompiler

Hi, in Lord\Laroute\LarouteServiceProvider class line 64 in 'registerCompiler' method it should be 'Lord\Laroute\Compilers\TemplateCompiler' not 'Lord\Laroute\Compilers\Templatecompiler'.
(Note the capital C in TemplateCompiler)

Subdomains - laroute.route('subdomain.route')

I want to link to another route on another subdomain. This is not possible at this time am i correct?

Example routes.php:

Route::group(['domain' =>'sub2.' . Config::get('app.host')], function(){
    Route::get('something/{id}', "OtherSubController@getSomething")->name('subdomain.route');
});

Example usage:

var myNewRoute = laroute.route('subdomain.route', {id: 3});

I would like to see this response:

"https://sub2.example.com/something/3"

How to pass arrays?

Request:
window.axios.post(laroute.route(this.loadRoute, {ids: idsArray}))

Error:
ids must be an array

Request:

array:1 [  "ids" => "46,50,5...3,74"]
// string

Suggestion: Allow inclusion of specific lookup methods

Most developers will probably look up all URLs either by route or by controller action. For that reason, including both lookup methods in the compiled package is a big waste of space and runtime resources. An option for "route names only", "actions only", or both, would be great. Only the appropriate access methods should be included as well.

I would help with this, but... I see issues and pull requests going back years even though the package is also under active development, I would want to make sure there is intent to clear up the PRs and it will actually be considered before I spend time on this.

Parameters not escaped

Is it intentional?

> laroute.route('search', {q: 'this & that'})
"/home/search?q=this & that"

The & that is not part of q anymore because & is query string separator. It should be replaced with its percent encoding.

Routes cache

I recently had a problem generating the js file, I had updated api.php but by running the php artisan laroute:generate command I did not modify js. After a while I thought about clearing the cache of the Laravel routes and then everything worked correctly.

I suggest making the call $this->call('route:cache'); at the beginning of the function handle().

Wrong Urls when in app in subdir

If app sits in subdirectory ie: domain.com/app/api/get-users (where /app/ is the main public dir then routes are generated incorrectly pointing to domain.com/api/get-users. Generator does not look up for routes in subdirectories like usual laravel router.

Option to not expose my PHP classes + methods?

Specifically, I want to disable this feature:

laroute.action('HomeController@getIndex');

I always use named routes. It's not necessary to expose my class structure. If not for security, then simply to reduce the output file size.

Use of undefined constant laroute - assumed 'laroute'

Hey,

One last thing here which is weird. The error above is being called everytime I try and add something like {{ laroute.action('HomeController@getIndex') }} in my template navigation in the header.

Sorry to throw up this :(

Cheers,
Mark

Project abandoned?

@aaronlord

Can you just let us know if you wish to abandon this project so that someone can fork it and continue development? I realize that technically anyone can fork it at any time, but I'd prefer not to do this if you plan on coming back.

Thanks

Template laroute.js not found when executing laroute:generate from outside the base application install folder

I am using deployer to deploy my site to production. One of the tasks I defined was as follows

task('artisan:laroute:generate', function () {
    run('{{bin/php}} {{release_path}}/artisan laroute:generate');
});

However I get the following error when deploying:

Executing task artisan:laroute:generate
[mysite.com] > /usr/local/bin/php ~/releases/12/artisan laroute:generate
[mysite.com] < stdin: is not a tty
[mysite.com] < File does not exist at path vendor/lord/laroute/src/templates/laroute.js

When running the command manually on the server it works.

Any ideas ?

5.1 compatibility

I try install laroute to fresh laravel 5.1.1:

> composer update
Loading composer repositories with package information
Updating dependencies (including require-dev)
Your requirements could not be resolved to an installable set of packages.

  Problem 1
    - Conclusion: remove laravel/framework v5.1.1
    - Installation request for lord/laroute 2.* -> satisfiable by lord/laroute[v2.0.0].
    - Conclusion: don't install laravel/framework v5.1.1
    - Conclusion: don't install laravel/framework v5.1.0
    - lord/laroute v2.0.0 requires illuminate/filesystem 5.0.* -> satisfiable by illuminate/filesystem[5.0.x-dev, v5.0.0, v5.0.22, v5.0.25, v5.0.26, v5.0.28, v5.0.33, v5.0.4].
    - don't install illuminate/filesystem 5.0.x-dev|don't install laravel/framework 5.1.x-dev
    - don't install illuminate/filesystem v5.0.0|don't install laravel/framework 5.1.x-dev
    - don't install illuminate/filesystem v5.0.22|don't install laravel/framework 5.1.x-dev
    - don't install illuminate/filesystem v5.0.25|don't install laravel/framework 5.1.x-dev
    - don't install illuminate/filesystem v5.0.26|don't install laravel/framework 5.1.x-dev
    - don't install illuminate/filesystem v5.0.28|don't install laravel/framework 5.1.x-dev
    - don't install illuminate/filesystem v5.0.33|don't install laravel/framework 5.1.x-dev
    - don't install illuminate/filesystem v5.0.4|don't install laravel/framework 5.1.x-dev
    - Installation request for laravel/framework 5.1.* -> satisfiable by laravel/framework[5.1.x-dev, v5.1.0, v5.1.1].

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.