Laravel package facade - php

I have create facade for my package by following the tutorial (https://github.com/orangehill/Laravel-Workbench-Walkthrough#package-facade-generation).
Now I have the facade working with all the function store on package main class.
E.g:
<?php namespace Orangehill\Walkthrough;
class Walkthrough {
public static function hello(){
return "What's up Zagreb!";
}
.....
}
I am able call to the function in the main class file with something like this:
Walkthrough::hello();
Walkthrough::hello2();
Walkthrough::hello3();
....
The problem is now my main class file has grown huge with lots of functions in it. How can I separate it into multiple class files? After separating, how can I have the facade able to link to it under the same facade name?
Thank you.

Related

PHP Laravel 5.2 - Call function in another file [duplicate]

I have two controller file homecontroller and backendcontroller. What is the best way to create global function and access it from both files?
I found here Arian Acosta's answer helpful but I wonder if there is an easiest way. I would appreciate any suggestions.
Solution
One way to do this is to create a class and use its instance, this way you can not only access the object of the class within a controller, blade, or any other class as well.
AppHelper file
In you app folder create a folder named Helpers and within it create a file name AppHelper or any of your choice
<?php
namespace App\Helpers;
class AppHelper
{
public function bladeHelper($someValue)
{
return "increment $someValue";
}
public function startQueryLog()
{
\DB::enableQueryLog();
}
public function showQueries()
{
dd(\DB::getQueryLog());
}
public static function instance()
{
return new AppHelper();
}
}
Usage
In a controller
When in a controller you can call the various functions
public function index()
{
//some code
//need to debug query
\App\Helpers\AppHelper::instance()->startQueryLog();
//some code that executes queries
\App\Helpers\AppHelper::instance()->showQueries();
}
In a blade file
Say you were in a blade file, here is how you can call the app blade helper function
some html code
{{ \App\Helpers\AppHelper::instance()->bladeHelper($value) }}
and then some html code
Reduce the overhead of namespace (Optional)
You can also reduce the overhead of call the complete function namespace \App\Helpers by creating alias for the AppHelper class in config\app.php
'aliases' => [
....
'AppHelper' => App\Helpers\AppHelper::class
]
and in your controller or your blade file, you can directly call
\AppHelper::instance()->functioName();
Easy Solution:
Create a new Helpers folder in your app directory.
Create a php file named your_helper_function.php in that Helpers directory.
Add your function(s) inside your_helper_function.php
function your_function($parameters){
//function logic
}
function your_another_function($parameters){
//function logic
}
Add this file to the Files key of your composer.json like
"autoload": {
...
"files": [
"app/Helpers/your_helper_function.php"
]
...
}
Finally, regenerate composer autoload files. (Run this in your project directory)
composer dump-autoload
That's it! and now you can access your_function() or your_another_function() in any part of your Laravel project.
If you still have any confusion, check my blog post on how to do this:
How to Add a Global Function in Laravel Using Composer?
Updated:
Step 1
Add folder inside app folder
app->Helper
Step 2
add php Class inside Helper folder
Eg. Helper.php
Add namespace and class to the Helper.php
namespace App\Helper;
class Helper
{
}
Register this Helper.php into config/app.php file
'aliases' => [
....
'Helper' => App\Helper\Helper::class
]
Now, write all the functions inside Helper.php and it will be accessible everywhere.
How to access from Controller?
Step 1 - Add a namespace at top of the controller.
use App\Helper\Helper;
Step 2 - Call function - Assume there a getInformation() inside the Helper Class.
$information = Helper::getInformation()
In your Controller.php which extends BaseController, you can create a function like;
public function data($arr = false)
{
$data['foo'] = 'bar';
return array_merge($data,$arr);
}
And from any controller when you send a data to a view;
public function example()
{
$data['smthg'] = 'smthgelse';
return view('myView',$this->data($data));
}
The data in the the main controller can be accessed from all controllers and blades.
The Laravel Service Provider way
I've been using global function within Laravel for a while and I want to share how I do it. It's kind of a mix between 2 answers in this post : https://stackoverflow.com/a/44021966/5543999 and https://stackoverflow.com/a/44024328/5543999
This way will load a file within a ServiceProvider and register it within your Laravel app.
Where is the difference, the scope, it's always about the scope.
Composer //Autload whitin composer.json method
|
|--->Laravel App //My method
|
|--->Controller //Trait method
|--->Blade //Trait method
|--->Listener //Trait method
|--->...
This is a really simplist way to explain my point, all three methods will achieve the purpose of the "Global function". The Traits method will need you to declare use App\Helpers\Trait; or App\Helpers\Trait::function().
The composer and service provider are almost about the same. For me, they answer better to the question of what is a global function, because they don't require to declare them on each place you want to use them. You just use them function(). The main difference is how you prefer things.
How to
Create the functions file : App\Functions\GlobalFunctions.php
//App\Functions\GlobalFunctions.php
<?php
function first_function()
{
//function logic
}
function second_function()
{
//function logic
}
Create a ServiceProvider:
//Into the console
php artisan make:provider GlobalFunctionsServiceProvider
Open the new file App\Providers\GlobalFunctionsServiceProvider.php and edit the register method
//App\Providers\GlobalFunctionsServiceProvider.php
public function register()
{
require_once base_path().'/app/Functions/GlobalFunctions.php';
}
Register your provider into App\Config\App.php wihtin the providers
//App\Config\App.php
'providers' => [
/*
* Laravel Framework Service Providers...
*/
Illuminate\Auth\AuthServiceProvider::class,
...
Illuminate\Validation\ValidationServiceProvider::class,
Illuminate\View\ViewServiceProvider::class,
App\Providers\GlobalFunctionsServiceProvider::class, //Add your service provider
Run some artisan's commands
//Into the console
php artisan clear-compiled
php artisan config:cache
Use your new global functions
//Use your function anywhere within your Laravel app
first_function();
second_function();
Laravel uses namespaces by default. So you need to follow the method described in that answer to setup a helper file.
Though in your case you want to access a method in different controllers. For this there's a simpler way. Add a method to you base controller app/Http/Controllers/Controller.php and you can access them in every other controller since they extend it.
// in app/Http/Controllers/Controller.php
protected function dummy()
{
return 'dummy';
}
// in homecontroller
$this->dummy();
There are a few ways, depending on the exact functionality you're trying to add.
1) Create a function inside Controller.php, and make all other controller extend that controller. You could somewhat compair this to the master.blade.php
2) Create a trait, a trait can do a lot for you, and keeping ur controllers clean. I personally love to use traits as it will look clean, keep my Controller.php from being a mess with tons of different lines of code.
Creating a global function
create a Helpers.php file under a folder, let's name it 'core'.
core
|
-- Helpers.php
namespace Helpers; // define Helper scope
if(!function_exists('html')) {
function html($string) {
// run some code
return $str;
}
}
In your composer.json
"autoload": {
"psr-4": {
},
"files": [
"core/Helpers.php"
]
}
in the file that you want to use it
// the " use " statement is not needed, core/Helpers is loaded on every page
if(condition_is_true) {
echo Helpers\html($string);die();
}
Remove the namespace in Helpers.php if you want to call your function without the need to prefix namespace. However I advise to leave it there.
Credit: https://dev.to/kingsconsult/how-to-create-laravel-8-helpers-function-global-function-d8n
By using composer.json and put the function containing file(globalhelper.php) to the autoload > files section, then run
composer dump-autoload
You can access the function inside the file(globalhelper.php) without having to calling the class name, just like using default php function.

new laravel package not recognized

I was writing my first laravel package, so I could use it and understand how packages work and learn how to write packages and etc.
But my project didn't recognize the package that I wrote.
Here is my package Github link: https://github.com/IIIphr/Shamsi_Calendar
And this is my main project: https://github.com/IIIphr/aimeos_shamsi
I use this command to add my package to the app: composer require iiiphr/shamsi_calendar
And it'll be added successfully (at least I guess). Then in the temp Controller, I wrote this:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use iiiphr\shamsi_calendar;
class temp extends Controller
{
public function index(){
return shamsi_calendar::get_date();
}
}
And a route:
Route::get('/date','temp#index');
But in the http://localhost:8000/date, I will face this error:
Before, I have tried other ways and the result was anything but success.
Another thing, I have this error in visual studio code in the temp controller:
Undefined type 'iiiphr\shamsi_calendar'.intelephense(1009)
I will appreciate any kind of help :)
You import the library perfectly but you don't use the Calendar Controller that the package gives you. The package haves a controller called CalendarController, you have two ways, extends from this controller or create an instance of this controller, if you extend the controller from this:
<?php
namespace App\Http\Controllers;
use iiiphr\shamsi_calendar\CalendarController;
class temp extends CalendarController
{
public function index(){
return $this->get_date();
}
}
What do you think about it?

How to include a function file in symfony2 in controller

Hi I have a file called payment.php it contains some functions related to payments and some multiple classess. So I want to include that file in my symfony2 Controller to access its all methods and classless. I am trying it as follows:
//File location is in src/AppBundle/Controller/payment.php
namespace AppBundle\Controller;
require_once __DIR__.'/./payment.php';
//My controller
class ApiServicesController extends Controller
{
$this->payment(array('txnId'=>1112548));
}
But I am not able to access the file and its methods.
I am using this approach because keeping it in /vendor directory it also not able to access because this file contains multiple classless in same files.
Please advice me how can I access this file in my controller.
thanks in advance
If paymant.php have classes you need to make instance of that class to call method from it, that's like basic OOP stuff.
class ApiServicesController extends Controller
{
$this->payment(array('txnId'=>1112548));
}
First of all, where is the method in this controller where you want to call your method? Then, why you are calling payment on $this if it comes from diffrent class. It should be something like this
class ApiServicesController extends Controller
{
public function indexAction()
{
$somePaymentClass = new SomePaymantClass(); //whatever class you want from payment.php
$somePaymentClass->payment(array('txnId'=>1112548));
}
}
But iI strongly recommend to use it as a service and put it in some autoloader namespace.
You have to make a Payment class as a service and then you can use all functions of Payment class in controller. Please refer this document.
http://symfony.com/doc/current/service_container.html

Laravel error interface class does not exist

I am very new to "Advanced Laravel" so to speak, however I do know most of the basics and I am trying to understand what namespacing, interfaces and repositories is all about, since I came across it not so long ago.
However, I am getting the following error, and I have no idea what I am doing wrong:
Class app\models\Interfaces\CategoriesInterface does not exist
Below is my code:
Routes.php
App::bind('App\Models\Interfaces\BaseInterface', 'App\Models\Repositories\BaseRepository');
CategoriesController.php
<?php
use app\models\Interfaces\CategoriesInterface;
class CategoriesController extends BaseController
{
protected $categories;
public function __construct(CategoriesInterface $categories)
{
$this->categories = $categories;
}
BaseInterface.php
<?php
interface BaseInterface
{
public function all();
}
CategoriesInterface.php
<?php namespace App\Models\Interfaces;
interface CategoriesInterface extends BaseInterface { }
CategoriesRepository.php
<?php namespace app\models\Repositories;
use App\Models\Interfaces\CategoriesInterface;
use Categories;
class CategoriesRepository implements CategoriesInterface
{
public function all()
{
$categories = $this->categories->all();
return $categories;
}
}
EloquentCategoriesRepository.php
<?php namespace app\models\Repositories;
use App\Models\Interfaces\CategoriesInterface;
class EloquentCategoriesRepository implements CategoriesInterface {
public function all()
{
return Categories::all();
}
Try name spacing the classes/interfaces properly. EloquentCategoriesRepository.php and CategoriesRepository are having app instead of App in the namespace. And CategoriesController too needs to use App\.. not app\...
I see you are trying to implement the repository pattern, which at first it might seem a bit 'advanced' but it's actually pretty simple.
So the basic idea is to abstract the data layer of your application with the database to make your transitions from one DBS to another(ex. Mysql to Mongo).
In other words your are trying to make the business logic of your application independent to the data layer (Where you query your collections/instances), so when you reach a point that you might want to change your database you can just implement another repository. The Interfaces are there to provide a contract between your application and the data layer.
Laravel implementation of the repository pattern it's pretty straight forward.
Create your interface
Create your interface's repository (actual implementation)
Bind the repository using a service provider class (Or in your case App::bind)
Instantiate the dependency in to your controller using the repository
Don't forget to auto load your namespaces using psr-04.
In your case I think the problem is you are not autoloading the namespace.
Also CategoriesRepository.php & EloquentCategoriesRepository.php are both Eloquent repositories and will return Eloquent collections. To return an array of stdClass (standar PDO) you will have to use the \DB facade.
If my answer does not cover you please take a look here

How do I extend the code igniter controller class?

In my CI system\libraries directory I have a new class named DD_Controller.php. This file looks like this:
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class DD_Controller extends Controller
{
protected $ddauthentication;
function __construct()
{
parent::Controller();
$this->ddauthentication = "Authenticated";
}
}
?>
My application controller is defined like this:
class Inquiry extends DD_Controller
{...}
The Inquiry class works fine when I extend Controller, but I get a
Fatal error: Class 'DD_Controller' not
found in
C:\development\localhost\applications\inquiry\controllers\inquiry.php
on line 4
When I extend DD_Controller. In the config file I have the prefix defined as such:
$config['subclass_prefix'] = 'DD_';
Any idea of what I'm missing?
TIA
This is a better approach. Do the following:
Go to the following directory: your_ci_app/application/core/ and create a php file called MY_Controller.php (this file will be where your top parent classes will reside)
Open this the file you just created and add your multiple classes, like so:
class Admin_Parent extends CI_Controller {
public function __construct() {
parent::__construct();
}
public function test() {
var_dump("from Admin_Parent");
}
}
class User_Parent extends CI_Controller {
public function __construct() {
parent::__construct();
}
public function test(){
var_dump("from User_Parent");
}
}
Create your children controllers under this directory your_ci_app/application/controllers/ . I will call it adminchild.php
Open adminchild.php and create your controller code, make sure to extend the name of the parent class, like so:
class Adminchild extends Admin_Parent {
function __construct() {
parent::__construct();
}
function test() {
parent::test();
}
}
DD_Controller.php should be in /system/application/libraries/
If you're using the same CI for multiple apps, and you want them all to be able to extends their controllers to your custom one then you can extend the base Controller class in the same file.
In system/libraries/Controller.php below the Controller class:
class Mega_Controller extends Controller {
function Mega_Controller()
{
parent::Controller();
// anything you want to do in every controller, ye shall perform here.
}
}
Then you'll be able to do this in your app controllers:
class Home extends Mega_Controller {
....
Since the extended controller class you created will be available. I think this is better then overwriting the base controller, but that would work as well.
I recommend to avoid "cracking" CodeIgniter core files.
Better use its native extending possibilities and try to fit into them.
The same rule I would recommend for any PHP library / CMS.
This rule has few reasons:
- ability to quiclky upgrade without takint into account thousands of notes where and how was cracked in core files;
- portability;
- possibility to share your code - eg, this will be usable by both you and your friends in case of need, and it will help them to keep their library up to date, the same as you.
In other words, this is much more professional and it pays to you in the future by usability, portability and by update application possibility.
Regarding your personal question...
As for me, there is nothing bad to create your own library with everything you need to extend native CodeIgniter Controller, then load this library in Controller's constructor and you are done. The only thing to make better usability is to give short name to your library.
This way you can even divide what you need in different pieces and put into separate libraries:
WebFeatures
AdminFeatures
etc.
Then you just load needed libraries in your controller's constructor and you are done.
P.S. I know that proposed way does not fit into "right" OOP concept, but in the same time you must never forget about the integrity of the libraries used.
Everything above is just one more view of mine 7-years experience in professional web development, so I hope it will be helpful if not to follow, then at least to take into account.
Regards,
Anton

Categories