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

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().

Related

Error Class "App\Exports\SOAReportExport" not found in laravel 8.x

I am using Laravel 8.x, livewire and etc. also laravel-excel package for exporting data.
I want to export data from a generated report and there is no model for it.
I am not sure that is it possible that can I export without model or not.
however, the problem is that laravel doesn't know my export class.
I have import this class at the top:
use Livewire\Component;
use App\Exports\SOAReportExport;
use Maatwebsite\Excel\Facades\Excel;
...
public function exportSOA()
{
$results = $this->results;
return Excel::download(new SOAReportExport($results), 'SOAReport.csv');
}
when I hover over it it shows:
Undefined type 'App\Exports\SOAReportExport'
Glad you found the solution, it's been 7 months but i want to let the answer to anyone is dealing this easy problem.
You mistyped the class name in 'App\Exports\SOAReportExport' export file.
Cheers.

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?

How can I render a twig template in a custom controller in Silex?

I'm playing with Silex microframework to build a very simple app.
The Silex documentation briefly illustrates how to keep your code organised using controller as class and I've also found this useful article talking about the same practice:
https://igor.io/2012/11/09/scaling-silex.html
but still can't solve my problem
The issue:
in my app.php I'm using
$app->get('/{artist}', 'MyNamespace\\MyController::getAlbum');
This is working. MyController is a class correctly loaded through composer using psr-4.
At the moment the return method of getAlbum($artist) is return $player;
What I'd like to do instead, is returning a twig view from getAlbum, something like:
return $app['twig']->render('player.twig', $player);
To do so, what I've tried to do in my custom class/controller is:
use Silex\Application;
use Symfony\Component\HttpFoundation\Request;
[...]
public function getAlbum(Request $request, Application $app, $artist)
but this is generating the following error when I try to access the routed pages:
ReflectionException in ControllerResolver.php line 43:
Class MyNamespace\Request does not exist
Whic made me think that there's a namespace conflict between myNamespace and the Silex namespaces?!
What am I doing wrong?
Is this the right way to make $app visible in my custom controller in order to use return $app['twig']... ?
Thank you in advance!
EDIT
After several other tries still didn't get to the point (replies still welcome!) but I've found a workaround solution that could be useful to anyone will incur in a similar issue. Directly in my app.php I added this
$app->get('/{artist}', function (Silex\Application $app, $artist) use ($app)
{
$object = new MyNamespace\MyController();
$player = $object->getAlbum($artist);
return $app['twig']->render('player.twig',
array(
//passing my custom method return to twig
'player' => $player,));
});
then in my player.twig I added:
{{player | raw}}
And this basically means that I still need an anonymous function to get use of my custom method which is a working solution I'm not really happy with because:
I'm using 2 functions for 1 purpose.
The return value of getAlbum is dependent from the use of "raw" in twig.
SOLVED
The workflow described works fine. It was a distraction error: I've placed the namespace of my custom class after use Symfony\Component\HttpFoundation\Request;
namespace declaration in PHP needs always to be at the top of the file, Silex wasn't able to injects $app and $request for this reason.

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.

Resolve view helper location from within the controller or form

I have a few view helpers that add JavaScript files when they're needed (for instance, so that only forms use CKEditor and such). My directory structure (simplified to include only the relevant files) is this:
application
--forms
--Project
AddIssue.php
--modules
--default
--views
--helpers
JQueryUI.php
Wysiwyg.php
--project
--controllers
ProjectController.php
--views
--scripts
--project
version.phtml
issueadd.phtml
What I want to do:
include CKEditor in the view project/project/issueadd
include jQuery UI in project/project/version
When I'm inside the view script, calling <?php $this->jQueryUI(); ?> works like a charm, even though the helper is in the default module's helpers directory. However, the same is not true for the controller and the form.
In the controller ProjectController.php, versionAction(), I tried to call:
$this->view->jQueryUI();
and the effect was an exception:
Message: Plugin by name 'JQueryUI' was not found in the registry; used paths: Project_View_Helper_: C:/xampp/htdocs/bugraid/application/modules/project/views\helpers/ Zend_View_Helper_: Zend/View/Helper/
Similarly, in the AddIssue.php form, I tried this:
$this->getView()->wysiwyg();
and there was an exception again:
Message: Plugin by name 'Wysiwyg' was not found in the registry; used paths: Project_View_Helper_: C:/xampp/htdocs/bugraid/application/modules/project/views\helpers/ Zend_View_Helper_: Zend/View/Helper/
Obviously, both would work if my view helpers were in the helper directories of the modules/controllers they're being called from, but since they're used across many modules, I'd like to have them in the default module's view helpers directory.
So, my questions are:
How do I access those view helpers from within the controller and the form?
Is there a simpler way to get around this (apart from simply including all javascript files in the layout)? Like creating a plugin or an action helper? (I haven't done these things before, so I really don't know, I'm only starting my adventure with ZF).
Regarding Q1 (based on the comments). You should be able to access the helpers in a usual way. However since it does not work, I think there is a problem with the way you bootstrap your view resource and/or the way how you perform concrete registration of the helpers or how you add helper path to it. I paste an example of adding helper path in Bootsrap.php:
<?php
#file: APPLICATION_PATH/Bootstrapt.php
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap {
public function _initViewHelperPath() {
$this->bootstrap('view');
$view = $this->getResource('view');
$view->addHelperPath(
APPLICATION_PATH . '/modules/default/views/helpers',
'My_View_Helper' // <- this should be your helper class prefix.
);
}
}
?>
This off course should normally work for modular setup of ZF.
Regarding Q2:
You can use headScript view helper to manage what scripts do you load in the head tag of your layout. Using this helper you can do it from your actions.
For example. If in a layout.php you have:
<head>
<?php echo $this->headScript(); ?>
</head>
then in, e.g. indexAction you can append some JS file as follows:
$this->view->headScript()->appendFile($this->view->baseUrl('/js/someJS.js'));
As much as I hate answering my own questions, there's one more solution I came up with, based on what Marcin has suggested in his answer. It can also be done in application.ini:
resources.view[] =
resources.view.helperPath.My_View_Helper = APPLICATION_PATH "/modules/default/views/helpers"
The caveat is that the lines need to appear in this order. Should it be reversed, anything before resources.view[] = will be ignored.
I'd rather get rid of your JQueryUI.php and would use ZendX. Something like that:
In controller:
ZendX_JQuery::enableView ($this->view);
$this->view->jQuery ()->enable ()->setRenderMode (ZendX_JQuery::RENDER_ALL);
In layout:
<?php echo $this->jQuery () ?>

Resources