composer autoload files and variables - composer-php

I'm creating a class that gets a random string from an array. The data will not change enough to make using a database worth it, but there are a few hundred entries so I don't really want to put the entire thing, into the class I'm creating.
Is there a way I can use composers autoload files to create a new php file, dump the array in and use it where ever I like? I've read up and to do that you apparently need to use the globals keyword which I'd rather not do.
Am I thinking too much about this? Would you just add the array to the class, or do a require etc, the functionality of the class itself is tiny.
Thanks.

Lets say you have these strings as text file. If its composer package, you can use composer scripts and generate php file from this text file during installation.
Then you can have one class with your functionality and second class containing array of items only.
Items class generation can look like (not tested):
<?php
...
$items = file_get_contents('items.txt');
$fileContent = '<?php
namespace Your\Namspace;
class Items {
public function getItems() {
return [
\'' . implode("',\n\t\t\t'", array_filter(explode("\n", $items))) . '\'
];
}
}';
file_put_contents('Items.php', $fileContent);

Related

Two models, two fields, return preferred if present

Been struggling with how to do this the most optimized way possible...
I have two models: Catalog and Application.
Catalog has a field called name.
Application has a field called name.
Both have a relationship with each other.
I am struggling to find a way to create a function i could use across my Laravel application which i would pass application.id to it and it would return a $app->name value based on the following logic:
if $application->name exists, use this value as the $app->name for the $application object
otherwise, get the $catalog->name value and use it as the $app->name
Note that I would like to create a component #application() where i can simply pass the $application->id and build the display logic (theming/styling) into it.
Since i display this $app->name in many places, i would like to make it as lightweight as possible to avoid unnecessary queries.
I hope this makes sense! There are probably so many ways to go with it, i am lost at figuring out the way way to do this :(
I'm not completely sure to understand your model/DB design, but you could use a custom Helper to use that function through the whole app.
For that, you can create a simple PHP class Helper.php file in app/Http/Helpers folder or whatever location you want. Something like:
<?php
use App\Catalog;
use App\Application;
if (! function_exists('getAppName')) {
function getAppName($id){
// Do your logic here to return the name
$catalog = Catalog::find($id);
return $catalog->name;
}
}
?>
Then in any controller or view, you just do
getAppName($application->id)
Do no forget to add your helpers file to the composer autoload. So in composer.json in Laravel's root folder, add the helper path to the autoload array:
"files": [
"app/Http/Helpers/helpers.php"
],
Last but not least, run the following command:
composer dump-autoload
Please note that function logic is just for sample purposes since I don't know your model structure.
In my opinion, I care about the database cost.
Use ternary expression will be elegant. But it took two times IO costs from database if application name is empty.
$app_name = Application::find($id)->name;
$app_name = empty($app_name) ? Catalog::where('application_id', $id)->first()->name;
And this will more complicated, but the catalog_query only execute when application.name is empty, it execute in database and the result is taken out only once;
And Database will only find the name from one table or two table.
Something like this:
$catalog_query = Catalog::where('catalogs.application_id', $id)->select('catalogs.name')->groupBy('catalogs.name');
// if catalogs and applications relationship is 1:1, use ->limit(1) or remove groupBy('name') is better.
Application::where("applications.id", $id)
->selectRaw("IF(application.name IS NULL OR application.name = '', (" . $catalog_query->toSql() ."), applications.name ) AS app_name")
->mergeBindings($catalog_query->getQuery())
->first()
->app_name;
Hope this will help you.

Isolate external php code in Laravel

I need to integrate Slider Revolution editor into my Laravel (5.5) app.
I've put the editor in public/revslider/ folder to be able to use the visual editor. I also created a helper class to "communicate" with it and be able to use it inside my Blade views:
namespace App\Helpers;
include( public_path('revslider/embed.php') );
class Slider{
/**
* This function is called where you want to put your slider
*/
public static function make($slider){
return \RevSliderEmbedder::putRevSlider( $slider );
}
/**
* This function is called inside <HEAD> tag to include all
* SR assets (js/css/font files)
*/
public static function head(){
return \RevSliderEmbedder::headIncludes(false);
}
}
The SR's PHP code does not use namespaces. In fact it is a strange mix of Code Igniter, Wordpress and vanilla php.
The problem is it is trying to declare a translation function __(...):
if( ! function_exists('__'))
{
function __($string = '')
{
....
}
}
and since there is already such Laravel's helper function, it does not redeclare it and tries to use Laravel's __() function. And that obviously causes errors.
I temporarily managed to fix this problem by changing the name of SR's __() function (and all references to it). But of course it is not a best way to solve this problem, since I will be unable to use SR's automatic updates or will be forced to do these changes after every update.
So my questions are:
Is there any good way of integrating such "bad" code into your project, invoking it safely without conflicts? Is there any way of isolating such code and avoid clashes? By "bad code" I mean code that does not follow strict OOP/PSR rules present in projects like Laravel.
What is the best way to include "external" PHP code? I've just used plain include() inside of my helper class' file, but is there a better/cleaner way? Like, I don't know, loading it through composer?

what does it mean in blade #extends('some::thing')

Today I have installed jeroennoten/laravel-adminlte and after following all the installation command I created a view and just wrote the line
#extends('adminlte::page')
and it works fine but I do not understand how it works? specially this :: symbol? I checked the laravel documentation but could not find anything.
Please help me by explaining it or give some article/tutorial link from where I can learn more.
adminlte is the name of the package, which is used for views and configs in Laravel as a namespace in order to avoid conflicts with other other packages.
It is defined in the ServiceProvider class on line 51.
By calling this in your blade files:
#extends('adminlte::page')
you are telling to Laravel, that you want to extend the page.blade.php file.
If you call #extends('page'), without adminlte::, it will look for the page.blade.php in your resources/views directory.
You won't see information in Laravel's Blade documentation section about this, because it's specific for Laravel Packages. And you can learn more from here.
::
symbol is a call of static function or static property in a class, for example if you define a class like this:
class Foo{
public static $a = 1;
public static function test(){};
}
you can use Foo::$a to get the value of $a, and use Foo::test() to call the function test().

CodeIgniter pagintation - appending the page number to "page" string

What I am trying to achieve is urls outputting via pagination like this:
http://www.mysite.com/users/page5
or
http://www.mysite.com/users/page-5
At present, it will be using the URI segments like this:
http://www.mysite.com/users/page/5
I can modify the routes.php config file to route the path if the first two URLs are used. So, that's not the issue.
What I am having trouble with is, how do I initialize the settings for the pagination, so that the $this->pagination->create_links() will create a pagination with items having links like in the first or the second format?
Let me know if you need more explanation or examples regarding this. I'm not much good in explaining things. :)
Thank you
This functionality already exists in the in-development version of CodeIgniter 3.0. You can view the Pagination class as it sits here.
To use this library, you can either A) use all of CI 3.0 (it's pretty stable), or B) extend (or, more realistically, replace) the Pagination library by creating application/libraries/MY_Pagination.php and filling it with the contents of the link above. (Full disclosure: it's been a while since I tinkered with CI, so I don't know if anything has changed since that may result in errors with any of this answer.)
To use the feature you want, specify your base URL minus the page-X segment, set that you want to use page numbers instead of offset in your URI segment, and then specify a prefix.
$config['base_url'] = site_url('users');
$config['use_page_numbers'] = true;
$config['prefix'] = 'page-';
Make sure to include your other obvious items as well, such as per_page, etc.
To change the functionality of the Pagination library, you can extend the library and override the create_links() function.
Create a file named MY_Pagination.php in application/libraries/
The file should have the following structure, so you can change or add additional functionality to CI's native Pagination library. (It is bad practice to directly change the Pagination library in the system directory.
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class MY_Pagination extends CI_Pagination {
public function __construct()
{
parent::__construct();
}
}
You'll then need to add the create_links() function to your MY_Pagination class, allowing you to override its default functionality. Below is an explanation of what you could change to achieve your desired output (you may want to add flexibility, by adding a parameter to the function, but this is the simplest change that I could think of.)
function create_links()
{
// You can copy the exact functionality of this function from:
// system/libraries/Pagination.php
// The line you want to change is:
// $this->base_url = rtrim($this->base_url, '/') .'/';
// Changing to this: $this->base_url = rtrim($this->base_url, '/') .'';
// Will create links in this format: ../page5
// Or changing to this: $this->base_url = rtrim($this->base_url, '/') .'-';
// Will create links in this format: ../page-5
}

Best Practices for Laravel 4 Helpers and Basic Functions?

I'm trying to understand the best place to put a global function in Laravel 4. For example, date formatting. I don't think making a facade is worth it as facades are too modular. I've read articles about creating a library folder and storing classes there but that also seems like a lot for a simple function. Shouldn't a 'tool' like this be available in Blade templates?
What are the best practices for something like this and how do I make it available to Blade templates?
The ugly, lazy and awful way: At the end of bootstrap/start.php , add an include('tools.php') and place your function in that new file.
The clean way: Create a library. That way it'll be autoloaded ONLY when you actually use it.
Create a libraries folder inside your app folder
Create your library file, create a class in it, and add static functions to it
Option 1: Edit start/global.php to add app_path().'/libraries' to the ClassLoader::addDirectories( array.
Option 2: Edit composer.json to add "app/libraries" to the autoload array. Run composer dump-autoload
Call your class and static functions from your views.
About your options, quoted from the global.php file
In addition to using Composer, you may use the Laravel class loader to
load your controllers and models. This is useful for keeping all of
your classes in the "global" namespace without Composer updating.
You can combine both options, where the Laravel class loader will automatically search for classes in the registered directories (Option 1, easier) and Composer will keep record of all the classes but only after you update it (Option 2, might improve performance).
My way of doing this is to create a new folder in the /app directory in the root of your Laravel 4 project. Then add this folder to the first array of the /app/start/global.php file like so:
<?php
ClassLoader::addDirectories(array(
app_path().'/commands',
app_path().'/controllers',
app_path().'/models',
app_path().'/database/seeds',
app_path().'/classes', // This line is the one I've added.
));
As long as the folder structure within the new /app/classes folder follows your namespacing convention. Laravel 4 will autoload all the classes/files within this folder. This way there's no need to dig into any composer files or run composer command.
Not sure if this is best practice but it certainly works.
If you created a simple file called /app/classes/Helpers/Helper.php such as this:
<?php namespace Helpers;
class Helper {
public static function helloWorld()
{
return 'Hello World';
}
}
All you would need to do is call Helpers\Helper::helloWorld();
You could also alias this helper class in your /app/config/app.php file. Just add something like this to the end of the aliases array:
'Helper' => 'Helpers\Helper'
Laravel's helpers.php method is to add it to your "files" in composer.json (https://github.com/laravel/framework/blob/master/composer.json):
"autoload": {
"classmap": [
...
],
"files": [
"app/libraries/helpers.php"
],
},
What I do is to create small classes (a few methods per class, one line per method, everything extended from something and DRY, that's my goal),
class ExtendedCarbon extends Carbon\Carbon {
public function formatDDMMAAAA($date)
{
/// format and return
}
}
save them to them in app/libraries and add to composer.json:
"autoload": {
"classmap": [
...
"app/libraries",
...
],
},
Execute
composer dump
And then just use them wherever you need
$formatted = (new ExtendedCarbon)->formatDDMMAAAA($date);
Watch this video about refactoring: http://www.youtube.com/watch?v=DC-pQPq0acs
By the way, I'm kind of sure it was just an example, but you might not need a helper to format dates, since all dates in Laravel are instances of Carbon (https://github.com/briannesbitt/Carbon) and it has loads of methods to format date and time.
You can also use View::share() together with closures to achieve this - I just posted about this: http://www.develophp.org/2014/07/laravel-4-blade-helper-functions/
Added benefit: You don't need to create an extra class and also keep the global namespace clean.

Resources