Using Blade directives outside of templates - laravel

Laravel 5.1: I defined a few custom directives inside a BladeServiceProvider (example below). Now I would like to use them outside of a view template to format strings (I am writing an EXCEL file with PHPExcel in a custom ExportService class). Is it possible to reuse my directives?
Blade::directive('appFormatDate', function($expression) {
return "<?php
if (!is_null($expression)) {
echo date(\Config::get('custom.dateformat'), strtotime($expression));
}
else {
echo '-';
}
?>";
});

The BladeCompiler has a compileString method, which allows you to use the Blade directives outside the views. :)
So, you can do things like this:
$timestamp = '2015-11-10 17:41:53';
$result = Blade::compileString('#appFormatDate($timestamp)');

You can use this:
use Illuminate\Support\Facades\Blade;
$timestamp = '2023-01-28 12:41:53';
Blade::render("#appFormatDate({$timestamp})");

Related

How to get translate message in controller Laravel?

I have file excel.php by the path /resources/lang/en/excel.php
Then in controller I tried to fetch word by key:
use Lang;
echo Lang::get('excel.idEvent');
Also I tried:
dd(echo __('excel.idEvent'));
Whats is right way to do that?
First, your excel.php file must be in the right format:
<?php
return [
'welcome' => 'Welcome to our application'
];
The right way to get it on your blade template in fact it is:
echo __('excel.welcome');
or
echo __('Welcome to our application');
The way to do it on your controller is:
use Lang;
Lang::get('excel.welcome');
If you are not using Facades: use \Illuminate\Support\Facades\Lang;
You can also use the trans() function, ex:
Route::get('/', function () {
echo trans('messages.welcome');
});
If you use JSON translation files, you might have to use __().
Here are all the ways to use:
#lang('...') // only in blade files
__('...')
Lang::get('...')
trans('...')
app('translator')->get('...')
Lang::trans('...')
They all defer to \Illuminate\Translation\Translator::get() eventually.

laravel blade include files with relative path

In laravel blade system when we want to include a partial blade file we have to write the full path every time for each file. and when we rename a folder then we will have to check every #include of files inside it. sometimes it would be really easy to include with relative paths. is there any way to do that?
for example we have a blade file in this path :
resources/views/desktop/modules/home/home.blade.php
and I need to include a blade file that is near that file :
#include('desktop.modules.home.slide')
with relative path it would be something like this :
#include('.slide')
is there any way to do this?
if someone still interest with relative path to current view file, put this code in the boot method of AppServiceProvider.php or any provider you wish
Blade::directive('relativeInclude', function ($args) {
$args = Blade::stripParentheses($args);
$viewBasePath = Blade::getPath();
foreach ($this->app['config']['view.paths'] as $path) {
if (substr($viewBasePath,0,strlen($path)) === $path) {
$viewBasePath = substr($viewBasePath,strlen($path));
break;
}
}
$viewBasePath = dirname(trim($viewBasePath,'\/'));
$args = substr_replace($args, $viewBasePath.'.', 1, 0);
return "<?php echo \$__env->make({$args}, \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))->render(); ?>";
});
and then use
#relativeInclude('partials.content', $data)
to include the content.blade.php from the sibling directory called partials
good luck for everyone
you need to create custom blade directive for that, the native include directive doesn't work like that.
read this page to learn how to create custom blade directive :
https://scotch.io/tutorials/all-about-writing-custom-blade-directives
\Blade::directive('include2', function ($path_relative) {
$view_file_root = ''; // you need to find this path with help of php functions, try some of them.
$full_path = $view_file_root . path_relative;
return view::make($full_path)->render();
});
then in blade file you can use relative path to include view files :
#include2('.slide')
I tried to tell you the idea. try and test yourself.
There’s now a package doing both relative and absolute includes (lfukumori/laravel-blade-include-relative) working with #include, #includeIf, #includeWhen, #each and #includeFirst directives. I just pulled it in a project, it works well.
A sleek option, in case you want to organise view files in sub-folders:
public function ...(Request $request) {
$blade_path = "folder.subfolder.subsubfolder.";
$data = (object)array(
".." => "..",
".." => $..,
"blade_path" => $blade_path,
);
return view($data->blade_path . 'view_file_name', compact('data'));
}
Then in the view blade (or wherever else you want to include):
#include($blade_path . 'another_view_file_name')

How to call helper function in laravel 5.5

I am using laravel 5.5. I have created a helper.php in app\Http. I am calling this helper in my blade file by using
{!! Helper::functionName() !!}
this is working fine. but i want to hold this helper result in a variable like
{!! $Result=Helper::functionName() !!}
But currently this is printing this result. How to solve this. please help.
So that i can make any if condition on this $Result.
In my helpers.php
namespace App\Http\Helpers;
class Helper
{
public static function functionName()
{
return "mydata";
}
}
There is no point to use helper like this. You should run the helper in controller and pass calculated data into view. In most cases you shouldn't set any variables in views or make any calculations - those should be passed from controller to view and view should only use them.
In this case, you can use "<?php ?>".
So result:
<?php $Result=Helper::functionName(); ?>
may be this is not possible because in laravel "{{}}" this means echo "" so by default it will print the value. return the value from helper function and use in your blade

Laravel 5.2 : Extending Blade by passing an object instead of a string

I want to add some blade directives.
I have in my service provider
Blade::directive('image', function ($media) {
return "<?php echo {$media->getImageUrl()}; ?>";
});
The blade file contain
#image($media)
the $media variable is an object which use the Media model and which contains a public function getImageUrl()which return a string with the url of the image.
When I execute this code, I have this error message
Fatal error: Call to a member function getImageUrl() on string
The object passed in the Blade directive is considered as a string instead of Media object
Is there any way to use $media as an Mediaobject instead of a string ?
The curly braces should be around $media:
Blade::directive('image', function ($media) {
return "<?php echo {$media}->getImageUrl(); ?>";
});
This compiles to:
<?php echo ($media)->getImageUrl(); ?>
As far as I know Blade directives only accept one expression as a string, including the function call braces. So the expression received by the directive is:
"($media)"
After changing directives you should clear the compiled views because Blade is caching the directives, so you would not see your changes taking affect.

Get Laravel 5 controller name in view

Our old website CSS was set up so that the body tag had an id of the controller name and a class of the action name, using Zend Framework 1. Now we're switching to Laravel 5. I found a way to get the action name through the Route class, but can't find a method for the controller name. I don't see anything in the Laravel docs like this. Any ideas?
This is how you do with action. You inject the Route class, and then call:
$route->getActionName().
I'm looking for something similar for controllers. I've checked the entire route class and found nothing.
If your layout is a Blade template, you could create a view composer that injects those variables into your layout. In app/Providers/AppServiceProvider.php add something like this:
public function boot()
{
app('view')->composer('layouts.master', function ($view) {
$action = app('request')->route()->getAction();
$controller = class_basename($action['controller']);
list($controller, $action) = explode('#', $controller);
$view->with(compact('controller', 'action'));
});
}
You will then have two variables available in your layout template: $controller and $action.
I use a simple solution. You can test and use it in everywhere, also in your views:
{{ dd(request()->route()->getAction()) }}
I will simply use as bellow
$request->route()->getActionMethod()
To get something like PostController try following ...
preg_match('/([a-z]*)#/i', $request->route()->getActionName(), $matches);
$controllerName = $matches[1];
$matches[1] includes the first group while $matches[0] includes everything matched. So also the # which isn't desired.
use this
strtok(substr(strrchr($request->route()->getActionName(), '\\'), 1), '#')
To add to Martin Bean answer, using Route::view in your routes will cause the list function to throw an Undefined offset error when this code runs;
list($controller, $action) = explode('#', $controller);
Instead use this, which assigns null to $action if not present
list($controller, $action) = array_pad(explode('#', $controller), 2, null);
You can use this to just simply display in the title like "Customer - My Site" (laravel 9)
{{ str_replace('Controller', '', strtok(substr(strrchr(request()->route()->getActionName(), '\\'), 1), '#'))}} - {{ config('app.name') }}
You can add this (tested with Laravel v7+)
<?php
use Illuminate\Support\Facades\Route;
echo Route::getCurrentRoute()->getActionMethod();
?>
or
You can use helper function
<?php echo request()->route()->getActionMethod(); ?>
for example :-
Route::get('test', [\App\Http\Controllers\ExampleController::class, 'exampleTest'])->name('testExample');
Now If I request {app_url}/test then it will return exampleTest

Resources