Laravel 4 Aliases in custom classes - laravel

i want to use the alias classes on laravel 4 "facades" like App::method , Config::method.
Well the thing is that i create a custom class and i have to import the namespaces like
<?php
namespace Face\SocialHandlers;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Config;
class FacebookHandler implements SocialHandlerInterface {
public function registrar($perfil) {
Config::get('facebook');
}
}
is there any way to use those classes like in controllers or routes files of the framework ?
like
<?php
namespace Face\SocialHandlers;
//use Illuminate\Support\Facades\App;
//use Illuminate\Support\Facades\Config;
class FacebookHandler implements SocialHandlerInterface {
public function registrar($perfil) {
Config::get('facebook');
}
}
Cya
ps: sry for my english

You can use use Config; instead of the more verbose use Illuminate\Support\Facades\Config; and the autoloader should handle it correctly.

Just as a tip, you shouldn't hardcode dependencies in your code. Instead of using the facades, you could create an "ConfigInterface" to get the common dependencies you need. Then create a "LaravelConfig class" (Or Laravel4Config.php) and implement those methods.
For a Quick Fix Answer, "catch the underliying facade instance":
namespace Face\SocialHandlers;
//use Illuminate\Support\Facades\App;
//use Illuminate\Support\Facades\Config;
class FacebookHandler implements SocialHandlerInterface {
protected $config;
protected $app;
public function __construct()
{
$this->config = \Illuminate\Support\Facades\Config::getFacadeRoot();
$this->app = \Illuminate\Support\Facades\App::getFacadeRoot();
}
public function registrar($perfil) {
$this->config->get('facebook');
}
}
For a Real Answer, maybe tedious, but good in the long run, instead of using the facades use an interface.
interface SocialConfigInterface
{
public function getConfigurationByKey($key)
}
Then
class Laravel4Config implements SocialConfigInterface
{
protected $config;
public function __construct()
{
$this->config = \Illuminate\Support\Facades\Config::getFacadeRoot(); //<-- hard coded, but as expected since it's a class to be used with Laravel 4
}
public function getConfigurationByKey($key)
{
return $this->config->get($key);
}
}
And Your Code
namespace Face\SocialHandlers;
//use Illuminate\Support\Facades\App;
//use Illuminate\Support\Facades\Config;
class FacebookHandler implements SocialHandlerInterface {
protected $config;
public function __construct(SocialConfigInterface $config)
{
$this->config = $config;
}
public function registrar($perfil) {
$this->config->get('facebook');
}
}
This way, if you want to change between frameworks you just need to create a SocialConfigInterface Implementation, or imagine the scenario where Laravel 5 wont use Facades, you want your code to be independent of "outsider changes" this is inversion of control IoC

First run,
php artisan dump-autoload
This will add your class namespace to vendor/composer/autoload_classmap.php. Now locate the entry for your class in this classmap array and get the proper namespace from there.
For example, you will get something like,
'Illuminate\\Support\\Facades\\App' => $vendorDir . '/laravel/framework/src/Illuminate/Support/Facades/App.php',
For this particular entry you have an alias in app/config/app.php
'App' => 'Illuminate\Support\Facades\App',
At the same way, locate your entry and use an alias in app/config/app.php.

You just have to create a folder, or place a class wherever already is listed for autoload. Me, for exemple, have this class PDFMaker, that uses a DomPDF Laravel implementation. I created a folder named libraries and put the path to it (under the app folder) in the autoload:classmap key on composer.json
"autoload": {
"classmap": [
"app/commands",
"app/controllers",
"app/libraries",
"app/models",
"app/helpers",
"app/database/migrations"
]
I did the same with commands for artisan commands! When you do that, you only have to declare a new object for any class under that folder, or call it in a static way, if the class has defined static methods. Something like Class::method.
Hope it helps you, have a nice day! :D
EDIT: After that, don't forget the dump-autoload for placing the new class in autoload scope.
EDIT 2: Remember that once you've put the class on autoload, it will be in same scope the others, so you won't have to import it to other, neither others to it!

You can also prefix the class names with a backslash, to use the global namespace: \Config::get('facebook') and \App::someMethod() will work without the need to add a use statement, regardless of the file's namespace.

Related

How to extend a laravel package within laravel 5.8 application?

I am new to Laravel and would appreciate any help on describing how a Laravel package residing in vendor folder can be extended and wont get affected if I update the package.
I'll try to create a brief guide, and we'll expand if need be.
I suggest putting all of your files inside a separate directory / namespace. You'll benefit from this should you decide to create your own composer package afterwards.
As an example I'll extend bumbummen99/shoppingcart package which forks the great gloudemans/shoppingcart, adding support for Laravel 5.8 and some minor functionality. You will of course first need to install that package:
composer require bumbummen99/shoppingcart
Start by making a couple of folders. You can use any name for folders / classes, this is what I used, relative to the project root:
app/Repositories/ExtendedCart
app/Repositories/ExtendedCart/Facades
Create the file
app/Repositories/ExtendedCart/ExtendedCart.php
This class will extend the package's main class:
namespace App\Repositories\ExtendedCart;
use Gloudemans\Shoppingcart\Cart;
class ExtendedCart extends Cart
{
public function myMethod(){
return 'myMethod';
}
}
Then make your Service Provider. Create the file:
app/Repositories/ExtendedCart/ExtendedCartServiceProvider.php
(I'm not using artisan as generating / moving the provider will produce wrong namespace)
This is your Service Provider content, here you reference the class that extends the package's class. Note you overwrite the binding from the original package.
namespace App\Repositories\ExtendedCart;
use Gloudemans\Shoppingcart\ShoppingcartServiceProvider;
class ExtendedCartServiceProvider extends ShoppingcartServiceProvider
{
public function register()
{
$this->app->bind('cart', 'App\Repositories\ExtendedCart\ExtendedCart');
}
}
Then register your service provider in config/app.php
'providers' => [
...
//Add this line to the end of providers array
App\Repositories\ExtendedCart\ExtendedCartServiceProvider::class,
]
Lastly create a Facade, which will instantiate the class (otherwise you will get non-static method exceptions). Create this file:
app/Repositories/ExtendedCart/Facades/ExtendedCart.php
This is the contents of the file:
namespace App\Repositories\ExtendedCart\Facades;
use Illuminate\Support\Facades\Facade;
class ExtendedCart extends Facade {
protected static function getFacadeAccessor() { return 'cart'; }
}
You're all set to use your extended methods. You can safely upgrade the original package, and you can even use the default facade:
namespace App\Http\Controllers;
use Cart;
class SomeController extends Controller{
public function someFunction(){
Cart::instance('default')->myMethod();
//This should return 'myMethod'
}
}
I hope this helps, good luck!

Creating a helper system in laravel is correct or not?

My helper root
app\http\myHelpers\customClass.php
customClass.php
<?php
namespace App\Http\myHelper;
class CustomClass {
public static function customFunction(){
return 'Custom class working......';
}
}
Controller function
public function test(){
CustomClass::customFunction();
}
routes
Route::get('/test', 'HomeController#test');
There is no need composer command. It is work properly but I am not sure to is it correct system or wrong system. Please help me.
How you organize your code is honestly a personal choice. So there is nothing wrong with your code. You don’t need any composer command because in Laravel everything in the app folder is auto loaded by composer: The App Directory
This is perfectly fine, what you can do additionally is to organize function inside traits and place them e.g. in the /app folder.
<?php
namespace App;
trait HasRoles
{
public function hasPermission(Permission $permission)
{
return $this->hasRole($permission->roles);
}
}
and use this trait inside your controller like
use Authenticatable, Authorizable, CanResetPassword, HasRoles;
just another way of bundling helper functions!

Laravel 5 preventing 'use'

Is there a way to prevent using 'use' for everything. In Laravel 4 I never used 'use' and everything just worked. I'm now finding out I have to include everything, even 'DB' use DB. This is extremely frustrating and time consuming looking all this up.
My question is, is there an easier way to include everything?
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\Customer;
use DB;
class HomeController extends Controller {
}
?>
Thanks
Not really -- this is the Brave New Namespaced world of PHP 5.3+. Your class file above lives in the App\Http\Controllers namespace, which means when you type something like
$object = new SomeClass;
PHP will assume you mean the class App\Http\Controllers\SomeClass.
You'll either, as you complained about, need to use use, or you'll need to use the full classname (with a leading \ to let PHP know to start from the global namespace) whenever you want to use a class
class HomeController extends Controller {
public function someFunction()
{
$result = \DB::query(...);
$customer = new \App\Models\Customer;
//etc...
}
}
This is question is old but I found you can do this based on information from a tutorial by Tejas Jasani: http://www.theappguruz.com/blog/upgrading-from-laravel-4-2-to-5-in-web
Here are the key steps:
1 - Add the app/Http/Controllers directory to the "autoload" classmap directive of your composer.json file.
"autoload": {
"classmap": [
"database",
"app/Http/Controllers"
],
2 - Remove the namespace from the abstract app/Http/Controllers/Controller.php base class.
3 - In app/Providers/RouteServiceProvider.php file, set the namespace property to null
protected $namespace = null;
4 - Run "composer dump-autoload" from the command line.

Injection in Repository

I found many questions about my problem and tried (I think) all the solutions, but I can not make it work. I'm overlooking something very easy, probably.
I'm using Laravel 5. I try to implement a repository-pattern.
I have an Eloquent model '\Notos\Kind'.
Then I have this interface:
namespace Notos\Contracts;
interface Kind
{
public function findByName($name);
}
My Repository looks like this:
namespace Notos\Repository;
use Illuminate\Database\Eloquent\Model;
use Notos\Contracts\Kind as KindContract;
class Kind implements KindContract
{
protected $kind;
public function __construct(Model $kind)
{
$this->kind = $kind;
}
public function findByName($name)
{
return $this->kind->firstOrCreate(array('name' => $name));
}
}
My ServiceProvider:
namespace Notos\Providers;
use Illuminate\Support\ServiceProvider;
use Notos\Kind;
use Notos\Repository\Kind as KindRepository;
class RepoServiceProvider extends ServiceProvider
{
/**
* Register the service provider.
*
* #return void
*/
public function register()
{
$this->app->bind('Notos\Contracts\Kind', function ($app) {
return new KindRepository(new Kind);
});
}
}
And my controller that uses the repository:
namespace Notos\Http\Controllers;
use Notos\Repository\Kind as KindRepository;
class KindController extends Controller
{
protected $kind;
public function __construct(KindRepository $kind)
{
$this->kind = $kind;
}
public function find($name)
{
return $this->kind->findByName($name);
}
}
This provider is registered in config/app.php
When I try to execute the KindController#find I get this error:
BindingResolutionException in Container.php line 785:
Target [Illuminate\Database\Eloquent\Model] is not instantiable.
I can't find what I'm doing wrong.
It works perfect if I change __construct(Model $kind) to __construct(Kind $kind).
Any ideas?
Thanks
The first thing, I would advice you to add to your class names the function so for example instead of Kind for repository use KindRepository, the same for contract. Otherwise you will have 3 kinds classes (of course in different namespaces) but it will be hard to analyse the code.
The problem here is that in your KindController you try to inject KindRepository directly but in constructor you use Model. It won't work because Model is only abstract class. What you should do to make it work?
In the code:
$this->app->bind('Notos\Contracts\Kind', function ($app) {
return new KindRepository(new Kind);
});
you told Laravel that when you will use Notos\Contracts\Kind it should create KindRepository for you with Kind in constructor - look you told here about Contract, not about repository itself.
So to make it work, you should use in your controller not your repository, but your contract.
Instead of line:
use Notos\Repository\Kind as KindRepository;
you should write:
use Notos\Contracts\Kind as KindRepository;
and it should work now.

How to register a namespace in laravel 4

The problem:
class PostRepostioryInterface not found for line 4 in PostController.php
or in tinkering with the namespace I've even got class
App\Models\Interfaces\PostRepositoryInterface not found
The questions: How to register a namespace in laravel 4? What do I need to do to get L4 to recognise the classes/interfaces at this namespace?
Larave 3 had a $namespaces static object in ClassLoader where you could add namespaces by
Autoloader::namespaces(array(
'App\Models\Interfaces' => path('app').'models/interfaces',
));
I'm not sure if I have that right for laravel 3 but either way, AutoLoader doesn't exist in Laravel 4 and ClassLoader exists but the method namespaces doesn't exist in ClassLoader in Laravel 4.
I've looked at this but it doesn't seem to work without registering the namespace somehow.
Using namespaces in Laravel 4
Example structure:
app/models/interfaces
PostRepostitoryInterface.php
app/models/repositories
EloquentPostRepository.php
namespaces:
App\Models\Repositories;
App\Models\Interfaces;
the files:
PostRepositoryInterface.php
<?php namespace App\Models\Interfaces;
interface PostRepositoryInterface {
public function all();
public function find($id);
public function store($data);
}
EloquentPostRepository.php
<?php namespace App\Models\Repositories;
use App\Models\Interfaces\PostRepositoryInterface;
class EloquentPostRepository implements PostRepositoryInterface {
public function all()
{
return Post::all();
}
public function find($id)
{
return Post::find($id);
}
public function store($data)
{
return Post::save($data);
}
}
PostController.php
<?php
use App\Models\Interfaces\PostRepositoryInterface;
class PostsController extends BaseController {
public function __construct( PostRepositoryInterface $posts )
{
$this->posts = $posts;
}
Thanks
You probably forgot to do composer dump-autoload. This updates the list of classes Laravel autoloads.
You can read more on composer documentation.
On the laravel irc channel I found out the namespaces should work in L4 without a need for registering them anywhere. This is because the composer dump-autoload adds them to the composer/autoload file for me. So that was not an issue.
The issue turned out to be a typo apparently(I can't find it in the code above but after going through every line copy/pasting the class names and namespaces something changed), and also somehow in my real code I left out the 'use' statement for EloquentPostRepository.php
use App\Models\Interfaces\PostRepositoryInterface;
Now I've hit another wall trying to use the namespaced interface with ioc and the controller constructor (target interface App\Models\Interfaces\PostRepositoryInterface is not instantiable) but I guess that should be a different question.

Resources