Laravel - Artisan gives wrong base url - php

My app/config/app.php has
'url' => 'http://dev.domain.com/something/somethingElse'
Then I have a function that can be called from the application and also from an artisan command. But URL::route('myRoute') returns different results. When called from the application it returns http://dev.domain.com/something/somethingElse/myRoute, but in the artisan command http://dev.domain.com/myRoute.
URL::to has same behaviour.
Note: I do not have any other app.php file defined for other environments that could overwrite the global one.
Any ideas why this happens ?
Thanks!

A Laravel-generated URL consists of a number of parts:
Scheme: http://, https://, etc.
Host: dev.domain.com, localhost, etc.
Base: something/somethingElse (the subdirectory on the web server)
Tail: myRoute, (the Laravel route parameters)
These parts are then concatenated to form the URL.
Ultimately, Laravel generates the URL using the $_SERVER request variables. The function prepareBaseUrl() in Symfony\Component\HttpFoundation\Request is what is ultimately used to determine the base part of the URL.
When you make a request through your web browser, the request goes to ~/public/index.php and the necessary $_SERVER variables are populated with the correct information for Laravel to populate the base part of the URL.
However, when you make the request using Artisan on the command line, the request goes to the ~/artisan script. This means that the $_SERVER variables are not populated in the same way and Laravel is not able to determine the base part of the URL; instead, it returns an empty string ''.
From what I can find, it doesn't look like there is any appetite from the Laravel team to enable the application to function out-of-the-box in a subdirectory, e.g. Bugfix: domain routing for subfolder.
I ended up working around it in the way described by #medowlock for my scripts that would be called from the command line, e.g.:
Config::get('app.url') . URL::route('route.name', ['parameter'=>'value'], false)
This concatenates the application URL set in the app/config/app.php and the relative URL route.

If you use Laravel 4.2, you can call the URL::forceRootUrl function to explicitly define what the root url of your laravel application is.
URL::forceRootUrl( Config::get('app.url') );
Calls to URL::to will use the URL define in your app config file after forcing the Root URL.
Unfortunately, this isn't available in Laravel 4.1 or Laravel 4.0

Related

Absolute URL in template returns localhost in email templates

I'm using absolute_url function defined here in my twig email template that is triggered via symfony command but the path only returns localhost/route instead of the complete URL http://abc.local/route.
download
What am I missing here ?
Solution with Symfony-5.4
Generating URLs in commands works the same as generating URLs in services. The only difference is that commands are not executed in the HTTP context. Therefore, if you generate absolute URLs, you'll get http://localhost/ as the host name instead of your real host name.
The solution is to configure the default_uri option to define the "request context" used by commands when they generate URLs:
On config/packages/routing.yaml add the URL of the real host.
# config/packages/routing.yaml
framework:
router:
# ...
default_uri: 'https://example.org/my/path/'
The default_uri option was introduced in Symfony 5.1.
For reference please see the official documentation.
https://symfony.com/doc/5.4/routing.html#generating-urls-in-commands

Angular 2 + angular-cli + Laravel 5.3

Using latest angular-cli, I created new project and everything works fine. Next, I tried to integrate it in Laravel 5.3. I have this project working with systemjs, but I want to switch to webpack and to take advantage of angular-cli.
Problem is that in angular-cli.json I can't specify that index is index.php, it only accepts HTML.
Basically, I can't start the Angular application at all with this setup.
How can I overcome this?
In the end I separated Laravel and Angular 2, as Cristian Sepulveda wrote in the comment. This is the recommended approach anyway.
I make API with Laravel and use it with Angular 2.
In my case I serve the angular app from laravel. I still use webpack to build my assets but have a gulp task which copies the angular index.html to be index.blade.php of which the laravel app serves.
I also use gulp to copy the built files from /dist to /public
I had the same problem and what I found is this related issue in their GitHub issues:
The output folder will always be entirely replaced. You can use the public/ folder to have your index.php which will be copied to your output folder, or output the app to a separate folder and copy the files yourself.
This is by design and will not change. This is a build output folder, not a deploy folder. You should separate those two steps.
So, you can't really achieve what you exactly want, but this is the only workaround I found.
I found only one solution for me.
create build for client side code by ng build --prod
Using gulp copy generated files into Laravel public dir gulp copy (here you can check if old build files exists remove them)
Using gulp-ingect plugin inject copied files into layout gulp inject
-- This can be used in CI and done with automation tools. In result we have inline.js and three *.**.bundle.js files injected. In same main layout i have statically add <base href="/example"> (you can use any defined in Laravel routes root path here) and inside template file which loaded from this path (in my case 'example.blade.php') add angular 2 root element <st-example>Loading...</st-example>
-- By this set up you have root Laravel layout which have inside required by angular 2 root url href and injected scripts files from build. And your template file for current route have root element inside (it included to main layout by simple blade yeild('content')).
P.S. also you must notice that if you are using some http requests in angular 2, after you integrate it into Laravel project this will add csrf protection middleware to each request... And if you have some new errors in requests which work previously just check headers.
Since angular-cli doesn’t allow you to specify index.php, let it be, simply specify index.html then there…
And add an appropriate route into Laravel routing. Like this one, for instance:
Route::any('{path?}', function () {
return File::get(public_path() . '/index.html');
})->where("path", ".+");
Btw, it’s simply a trap for any unknown routes… But I think you get an idea.

Testing multi-tenancy Laravel applications using Behat / Mink and Behat Laravel Extension

I am building a multi-tenant SaaS application which I am trying to write tests for with Behat, using Mink and the Behat Laravel Extension
When you register for an account, you get your own subdomain on the site {account}.tenancy.dev
my behat.yml file looks like so:
default:
extensions:
Laracasts\Behat:
# env_path: .env.behat
Behat\MinkExtension:
default_session: laravel
base_url: http://tenancy.dev
laravel: ~
I am having problems straight off the bat as when I try to test my registration flow, I am getting a 404 error testing that the new subdomain is accessible, all of the data has been saved correctly, manually testing the process works and the subdomain routing works.
I was wondering if there was any way to do this using Behat and how I would go about setting Behat / Mink to use wildcard subdomains to test SaaS applications?
I am running the test inside the Homestead VM.
The base_url: http://tenancy.dev configuration is used to generate a fully qualified domain URL when you utilize relative path URL's in your mink steps (IE "/home").
When you want to hit a domain different from the domain specified in base_url, all you have to do is use the fully qualified domain URL in your step like "http://test.tenancy.dev/fully/qualified".
So use the base_url configuration to set what you will be using for the majority of your steps as relative url's and then explicitly specify the full domain for the exceptions.
When I create an account named foo
And GET "http://foo.tenancy.dev/ping"
Then I get a 200 response code
When I GET "/home"
Then the response contains "Sign Up"
If the majority of your testing will be against the sub domain, set that as your base_url and explicitly specify your top level domain when necessary.
You may resolve subdomains using xip.io, which is especially useful if you cannot access the /etc/hosts file on a CI server, for example.
To route {account}.tenancy.dev to your local webserver, you can use account.tenancy.dev.127.0.0.1.xip.io which resolves to 127.0.0.1.
After a short while I revisited this problem and found a rather simple solution to be used in my FeatureContext.php:
$this->setMinkParameter('base_url', $url);
This changes the base url for any scenario it is used in:
/**
* #Given I visit the url :url
*/
public function visitDomain($url)
{
$this->setMinkParameter('base_url', $url);
$this->visit('/');
}
Which is used in the following way:
Scenario: Test Multi Tenancy
Given I have a business "mttest"
When I visit the url "http://mttest.example.com"
Then I should see "mttest"
Obviously this is slightly contrived but does show that what I was intending to do is possible.

Laravel: URL::to('/') port number for localhost not included in db seed files

I am running a local server on port 4567. I am trying to make it so that when my database seeds I save a reference to the home page on my site in my db. However I noticed when I run URL::to('/') in my seeds it only includes "localhost" without the port, but if I include it in my view code it comes out as "localhost:4567". Why is this? How can I fix it, if possibly, without writing if statement conditionals about what production environment I am in? Thank you.
Seed File result of URL::to('/')
http://localhost
View File result of URL::to('/')
http://localhost:4567
Either set APP_URL in env file
APP_URL=http://localhost:4567
Or set url in config/app.php
'url' => env('APP_URL', 'http://localhost:4567'),
Many internal functions and third-party libraries use the APP_URL .env var directly or via config('app.url'). The better way is to use the URL generator classes that Laravel provides, eg. the Url facade.
Even so, you'll see different results in Views versus in the CLI, or in Jobs (eg. links in emails). In the web context most of Laravel's URL generation is based on the server/request URL. For example, the url() helper calls methods in Illuminate\Routing\UrlGenerator that ultimately use Illuminate\Http\Request's URL methods.
The CLI and Queued Jobs don't have the Request object, so they have to fall back to something else. That's right, configuration.
So, even though links, redirects, and other generated URL's will function perfectly in the web, these can be "broken" (misconfigured ;) outside the HTTP request lifecycle if APP_URL isn't set in your .env, or directly in the app config as #Sachin Kumar points out.

Where is the Front Controller using server:run in Symfony 2

Using plain old apache server, you make your request to Symfony using localhost:80/acme/app.php/routes
So app.php or app_dev.php is you Front Controller. Knowing this, you can forget almost it. But when you use the PHP built in server, you can access directly to localhost:8000/routes.
I have looked inside the console script file, and it looks like app.php but we call it only once, at the start of the server. Where is the glue stuff ?
The console file is the front-controller for the CLI environment of your Symfony application. The server:run is part of this environment and can be found in the FrameworkBundle: ServerRunCommand (EDIT: as of Symfony 3.3, the command can be found in the WebServerBundle)
It starts the built-in webserver of PHP: php -S localhost:8000 and it routes all incomming requests to a so-called routing script. In case of the dev environment, the router_dev.php router inside the FrameworkBundle.
This router file has this line:
$_SERVER['SCRIPT_FILENAME'] = $_SERVER['DOCUMENT_ROOT'].DIRECTORY_SEPARATOR.'app_dev.php';
Which pretends that the incomming request was made to the app_dev.php file. (So localhost:8000/something becomes localhost:8000/app_dev.php/something after this router script). It then includes the app_dev.php file to handle the rendering of the site.

Categories