Best way to override single method in Illuminate\Foundation\Application through service provider - laravel

I just made changes to the application structure for my Laravel application. It works well when runnning tests (for the Http controllers). The problem is when i try to run artisan commands (that literally need to access "getNamespace()" method), it wont resolve the namespaces.
Here are the composer.json:
"autoload": {
"psr-4": {
"App\\": "app/",
"Database\\Factories\\": "database/factories/",
"Database\\Seeders\\": "database/seeders/",
"Modules\\": "modules/"
},
"files": [
"app/Helpers/app.php",
"app/Helpers/form.php",
"app/Helpers/view.php"
]
},
"autoload-dev": {
"psr-4": {
"Tests\\": "tests/"
}
},
I do aware that i can add Modules\ModuleA, Modules\ModuleB to the composer json, but that put alot of work. So i decided to override the getNamespace() method instead, but what is the best way to override single method illuminate/foundation/xxx classes through service provider?
Folder tree:
laravel-project/
├── app/
│ ├── Exception
│ ├── Providers
│ └── ...
├── modules/
│ ├── ModuleA/
│ │ ├── Services
│ │ ├── Http/
│ │ │ ├── Controllers
│ │ │ └── Requests
│ │ └── Models
│ └── ModuleB/
│ └── ...
├── tests
└── ...

If you want to override a single method in Illuminate\Foundation\Application through a service provider in Laravel, you can use the following steps:
Create a new service provider by running the command php artisan make:provider YourServiceProvider in your terminal.
In your YourServiceProvider class, extend the Illuminate\Support\ServiceProvider class.
Override the register() method in your YourServiceProvider class. In this method, you can bind your custom implementation of the method you want to override to the container. For example, if you want to override the loadEnvironmentFrom() method, you can do so as follows:
use Illuminate\Foundation\Application;
class YourServiceProvider extends ServiceProvider
{
public function register(){
$this->app->bind(Application::class, function ($app) {
return new class($app) extends Application {
public function loadEnvironmentFrom($file)
{
// Your custom implementation here
}
};
});
}
}
Then in your config.app file, add the service provider to the list of providers:
'providers' => [
// Other service providers
App\Providers\YourServiceProvider::class,
],
This way, the method you've overridden will use your custom implementation instead of the default implementation in Illuminate\Foundation\Application.
Hope this helps

Related

Package: the importance of naming files when using initialization

I wrote a structure like display in the tree below.
.
├── README.md
├── db
│ └── db.go
├── go.mod
├── go.sum
├── handler
│ ├── category.go
│ ├── handler.go
│ └── users.go
├── main.go
├── model
│ ├── category.go
│ ├── model.go
│ └── users.go
└── route
├── category.go // init() ❌ error to using package vars
├── route.go // init() writing package vars
└── users.go // init() ✅ no error to using package vars
All the files in the packages except the one with the same name (route/route.go, handler/handler.go,...) are generated automatically. For these files to extend the package variables, I use golang's func init(){} ex:
route/route.go
package route
import (
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware"
)
var (
// public routes
e *echo.Echo = echo.New()
// restricted routes
r *echo.Group = e.Group("/restricted")
)
func init() {
e.Use(middleware.CORSWithConfig(middleware.CORSConfig{
AllowOrigins: []string{"http://localhost:3000"},
AllowMethods: []string{echo.GET, echo.PUT, echo.POST, echo.DELETE, echo.OPTIONS},
AllowHeaders: []string{echo.HeaderAuthorization, echo.HeaderContentType},
}))
e.Use(middleware.Recover())
r.Use(middleware.JWT([]byte("secret")))
}
route/category.go
package route
import (
"github.com/username/project/handler"
)
func init() {
r.GET("/category", handler.ListCategory)
r.POST("/category/add", handler.CreateCategory)
r.GET("/category/:id", handler.ReadCategory)
r.PUT("/category/edit/:id", handler.UpdateCategory)
r.DELETE("/category/:id", handler.DeleteCategory)
}
route/user.go
package route
import (
"github.com/username/project/handler"
)
func init() {
r.GET("/users", handler.ListUsers)
r.POST("/users/add", handler.CreateUser)
r.PUT("/users/edit/:id", handler.UpdateUser)
r.DELETE("/users/:id", handler.DeleteUser)
e.POST("/auth", handler.Login)
e.POST("/lost", handler.Lost)
e.POST("/password", handler.Password)
}
As you already understood, the category.go init() starts before the router.go init(), which is described here: Go Package initialization.
After coding a pretty program that auto writes routes like route/category.go. I realize that to solve this problem, I will have to rename router/router.go to router/0router.go (it works) so that it is still at the top of the pillar, but it's not a good approach.
Have any suggestions for this tree and the use of golang ini() ?
Thank you
Use variable declaration expressions to avoid file name dependencies. The assignments execute before the init() functions that reference the variables.
var (
// public routes
e *echo.Echo = newPublic()
// restricted routes
r *echo.Group = newRestricted()
)
func newPublic() *echo.Echo {
e := echo.New()
e.Use(middleware.CORSWithConfig(middleware.CORSConfig{
AllowOrigins: []string{"http://localhost:3000"},
AllowMethods: []string{echo.GET, echo.PUT, echo.POST, echo.DELETE, echo.OPTIONS},
AllowHeaders: []string{echo.HeaderAuthorization, echo.HeaderContentType},
}))
e.Use(middleware.Recover())
}
func newRestricted() *echo.Group {
r := e.Group("/restricted")
r.Use(middleware.JWT([]byte("secret")))
return r
}

How to store JSP views in classpath instead of webapp?

I want to store JSP files in src/main/resources/templates
but after setup i get not found error. It seems that spring.mvc.view.prefix only supports path for folder in wepabb folder.
Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.
There was an unexpected error (type=Not Found, status=404).
application.properties
spring.mvc.view.prefix = classpath*:/templates/
spring.mvc.view.suffix = .jsp
Controller
#Controller
public class DemoController {
#RequestMapping("/")
public String index() {
return "test";
}
}
And this is the src file structure:
├───main
│ ├───java
│ │ └───com
│ │ └───example
│ │ └───demo
│ │ DemoApplication.java
│ │ DemoController.java
│ ├───resources
│ │ └───templates
│ │ test.jsp
│ └───webapp
The solution (from Dave Newton) is to put jsp file in folder
src/main/resources/META-INF/resources/WEB-INF/templates/
and set
spring.mvc.view.prefix = /WEB-INF/templates/
spring.mvc.view.suffix = .jsp
Folder src/main/resources/META-INF/resources works like src/main/webapp

Combining GraphQL queries

I am building my first GraphQL based project so forgive me if this is a newbie question. I have arranged my queries and mutations in the following fashion:
├── graphql
│   ├── lessons
│   │   ├── logic.js
│   │   ├── query.js
│   │   ├── schema.js
│   │   └── types.js
│   ├── schema.js
│   └── users
│   ├── logic.js
│   ├── mutation.js
│   ├── query.js
│   ├── schema.js
│   └── types.js
This is my users/query.js file:
const graphql = require('graphql')
const types = require('./types.js')
const logic = require('./logic.js')
module.exports = new graphql.GraphQLObjectType({
name: 'UserQuery',
fields: {
user: {
type: types.userType,
args: {
email: { type: new graphql.GraphQLNonNull(graphql.GraphQLString) }
},
resolve: (root, { email }, context) => logic.getUser(email, context)
}
}
})
In my schema.js, I have combined the queries of users and lessons as per the following code:
module.exports = new graphql.GraphQLSchema({
query: new graphql.GraphQLObjectType({
name: 'RootQuery',
fields: {
lessons: { type: require('./lessons/query.js') },
users: { type: require('./users/query.js') }
}
})
})
Now the problem is, the following query:
{
users {
user(email: "a#.a") {
name,
purchases
}
}
}
is producing the following output:
{
"data": {
"users": null
}
}
I am getting a null in place of a user record. What am I doing wrong here?

Getting the puppet module pcfens/filebeat to work

I'm new to this site and puppet. I'm trying so setup a puppet module for filebeat. I want Linux nodes to send logs to logstash using this module
I want a configuration that looks something like this:
class { 'filebeat':
outputs => {
'logstash' => {
'hosts' => [
'<FQDN>:5044',
],
'enabled' => true,
},
},
}
filebeat::prospector { 'syslogs':
paths => [
'/var/log/*.log',
'/var/log/messages',
],
doc_type => 'syslog-beat',
}
Does anyone have any experience with this module or with Puppet in general and can tell me how to configure this module with the configuration above. I feel clueless right now and I can't seem to find a lot of documentation about this module. I would really appreciate a push into the right direction on how to setup this module.
You probably want to ask about how to start your Control Repo. But before you do that, make sure you read up on the Roles and Profiles design pattern.
To get you started, you will have start something like this:
$ tree
.
└── modules
├── profile
│   └── manifests
│   ├── base
│   │   └── filebeat.pp
│   └── base.pp
└── role
└── manifests
├── base
└── myrole.pp
7 directories, 3 files
(Obviously, as you can see from the example I linked above, it is going to have a lot more in it eventually.)
Then your base class:
$ cat modules/profile/manifests/base.pp
class profile::base {
include profile::base::filebeat
}
Which includes (the code you wrote above):
$ cat modules/profile/manifests/base/filebeat.pp
class profile::base::filebeat {
class { 'filebeat':
outputs => {
'logstash' => {
'hosts' => [
'<FQDN>:5044',
],
'enabled' => true,
},
},
}
filebeat::prospector { 'syslogs':
paths => [
'/var/log/*.log',
'/var/log/messages',
],
doc_type => 'syslog-beat',
}
}
Your role:
$ cat modules/role/manifests/myrole.pp
class role::myrole {
include profile::base
}
Now, you can test the code on the local host just by ensuring that your modules directory gets copied one way or another into Puppet's modulepath.
If so, try:
# puppet module install pcfens/filebeat
# puppet apply -e 'include role::myrole'
Providing you installed Puppet correctly, and your code above is correct, that would get you started.

Static files not working in Django development

I'm trying to follow the section in the Django docs called Managing static files. I am interested in finding out:
What I am doing wrong.
Or, what is wrong with the Django docs.
1) Make sure that django.contrib.staticfiles is included in your INSTALLED_APPS.
In the default settings.py file:
INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles', #<****HERE*****
)
2) In your settings file, define STATIC_URL, for example: STATIC_URL = '/static/'
In the default settings.py:
STATIC_URL = '/static/'
3) In your templates, either hardcode the url like /static/my_app/myexample.jpg
In mysite2/mysite2/views.py:
from django.http import HttpResponse
def index(request):
return HttpResponse('''
<h2>Hello</h2>
<img src="/static/mysite2/Aerial03.jpg">
''')
4) Store your static files in a folder called static in your app. For example: my_app/static/my_app/myimage.jpg.
Here is my directory structure:
(django186p34)~/django_projects$ tree mysite2
mysite2
├── db.sqlite3
├── manage.py
└── mysite2
├── __init__.py
├── settings.py
├── static #<****HERE*****
│   └── mysite2
│   └── Aerial03.jpg
├── urls.py
├── views.py
└── wsgi.py
4 directories, 13 files
But after starting the server:
(django186p34)~/django_projects/mysite2$ python manage.py runserver
Performing system checks...
System check identified no issues (0 silenced).
November 26, 2015 - 02:44:57
Django version 1.8.6, using settings 'mysite2.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
And then navigating in my browser to:
http://localhost:8000/
I see the text:
Hello
but the image is not found:
[Error] Failed to load resource: the server responded with a status of 404 http://localhost:8000/static/mysite2/Aerial03.jpg
I've tried many combinations of urls in my html and nothing works.
Here is settings.py in its entirety(I made no changes):
"""
Django settings for mysite2 project.
Generated by 'django-admin startproject' using Django 1.8.6.
For more information on this file, see
https://docs.djangoproject.com/en/1.8/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/1.8/ref/settings/
"""
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
import os
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.8/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'pmaup3%)m09cs2goldduw2iogso%(#8cz0s-zmr%*e'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = []
# Application definition
INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
)
MIDDLEWARE_CLASSES = (
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'django.middleware.security.SecurityMiddleware',
)
ROOT_URLCONF = 'mysite2.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
WSGI_APPLICATION = 'mysite2.wsgi.application'
# Database
# https://docs.djangoproject.com/en/1.8/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
# Internationalization
# https://docs.djangoproject.com/en/1.8/topics/i18n/
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_L10N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.8/howto/static-files/
STATIC_URL = '/static/'
This fixed things:
INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'mysite2', #<*****HERE*****
)
And if you organize things so that you have apps inside your project, e.g.:
(django186p34)~/django_projects$ tree mysite3
mysite3
├── db.sqlite3
├── manage.py
├── myapp
│   ├── __init__.py
│   ├── admin.py
│   ├── migrations
│   │  
│   │  
│   ├── models.py
│   ├── static
│   │   └── myapp
│   │   └── Aerial03.jpg
│   ├── tests.py
│   ├── urls.py
│   └── views.py
└── mysite3
├── __init__.py
├── settings.py
├── urls.py
└── wsgi.py
8 directories, 24 files
Then in settings.py add your app name to INSTALLED_APPS:
INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'myapp', #<*****HERE*****
)
Everything else in the default settings.py stays the same. However, the urls are different:
mysite3/mysite3/urls.py:
from django.conf.urls import include, url
from django.contrib import admin
urlpatterns = [
url(r'^admin/', include(admin.site.urls)),
url(r'^myapp/', include('myapp.urls')),
]
mysite3/myapp/urls.py:
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^$', views.index, name='index'),
]
And in your browser, the url becomes:
http://localhost:8000/myapp/
myapp/views.py:
from django.shortcuts import render
# Create your views here.
from django.http import HttpResponse
def index(request):
return HttpResponse('''
<h2>Hello</h2>
<img src="/static/myapp/Aerial03.jpg">
''')

Resources