I've created a very basic app in Laravel 4, it's something I'll be reusing a lot in various projects so it made sense to convert it to a package before i got too far, but I'm struggling to make the changes to get it working, which I think is largely due to figuring out how to access the various objects that are normally available in an app, eg View::make
I had the following code working in an app:
class PageController extends BaseController {
public function showPage($id)
{
//do stuff
return View::make('page/showPage')
->with('id', $id)
->with('page', $page);
}
for the package I have the following:
use Illuminate\Routing\Controllers\Controller;
use Illuminate\Support\Facades\View;
class PageController extends Controller {
public function showPage($id)
{
//do stuff
return View::make('page/showPage')
->with('id', $id)
->with('page', $page);
}
However this does not load the blade template which is located at:
workbench/packagenamespace/package/src/views/page/showPage.blade.php
nor does this work:
return View::make('packagenamespace/package/src/page/showPage')
Also, I am wondering if what i have done with the use statements where I use the facade object correct, to me it seems like there should be a neater way to access things like the View object?
You should read the docs: http://four.laravel.com/docs/packages
Specifically the part explaining loading views from packages ;)
return View::make('package::view.name');
If you don' want to use:
use Illuminate\Support\Facades\View;
Just do:
use View;
Or even without the use statement:
\View::make('package::view.name');
// Serviceprovider.php
$this->loadViewsFrom(__DIR__.'/resources/views', 'laratour');
// Controller
<?php
namespace Mprince\Laratour\Controllers;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
class LaratourController extends Controller
{
public function index()
{
return view('laratour::index');
// return view('packageName::bladeFile');
}
//END
}
Related
I've code in my controller which returns some $data, and I want to refer that in all my blades, I can make routes for each page, but I don't like this way. I thought should be better if I refer this $data on layout.blade which include navbar, and etc..., but is it a possible to make route without url? cause I don't want to appear my layout.blade, So my question is, what is a best way to get $data on each blade?
You may perhaps want a view composer. A view composer is an extension of a blade via php that runs before the blade.
In app service provider you set the view you want to view composer class.
use Illuminate\Support\Facades\View;
use App\Http\ViewComposers\LayoutComposer;
class AppServiceProvider extends ServiceProvider
{
public function boot()
{
View::composer('layout', LayoutComposer::class);
}
}
Then write your logic in the class.
use Illuminate\View\View;
class LayoutComposer
{
public function compose(View $view)
{
$data = Model::where('id',###)->first();
return $view->with(['data' => $data]);
}
}
https://laravel.com/docs/7.x/views#view-composers
I'm using Laravel 5.5 and trying to get used to code by psr-2 standard (just started learning). I analyze all my code with Quafoo QA and go step by step fixing the errors and record them.
By using facades i get this error "Avoid using static access to class". Because of it i'm trying to avoid using them.
On my controller i have this code:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Events\FileLoaded;
use Illuminate\Support\Facades\Input;
use Illuminate\Auth\Middleware\Authenticate;
use PhpOffice\PhpSpreadsheet\Shared\StringHelper;
use \Illuminate\Contracts\View\Factory as ViewFactory;
class LoadDataController extends Controller
{
public function index()
{
$viewfactory = app(ViewFactory::class);
return $viewfactory->make('LoadData/index');
}
//more code
}
Besides the View Facade i also use DB, Input, Validator and Storage
Is this the correct way, are there others?
You don't need to avoid Facades - they are a key part of the framework. But if you want to, you can use dependency injection to include the classes you need as arguments in the controller methods:
class LoadDataController extends Controller
{
public function index(ViewFactory $viewFactory)
{
return $viewfactory->make('LoadData/index');
}
//more code
}
Or if you need that in all the controller methods:
class LoadDataController extends Controller
{
private $viewFactory;
public function __construct(ViewFactory $viewFactory)
{
$this->viewFactory = $viewFactory;
}
public function index()
{
return $this->viewFactory->make('LoadData/index');
}
//more code
}
Of course, this doesn't actually change the functionality of the code you've written, it just rearranges it. I wouldn't take the word of the code analyzer you mentioned as something you are doing wrong. These are standard patterns to use in Laravel.
In several controllers i have to use the same method to show results as table with column sorting functionality:
public function showSearchResults(Request $req){
$query=Service::where('title', $req->search);
// Columns sorting
if ($req->has('order')){
$order= $req->order=='asc' ? 'asc' : 'desc';
$order_inverse=$req->order=='asc' ? 'desc' : 'asc';
} else {
$order='desc';
$order_inverse='asc';
}
...
$url=$req->url().'?'.http_build_query($req->except('sortby','order','page'));
$results=$query->with('type')->paginate(15)->appends($req->all());
return View::make('services.search_results')
->with('results', $results)
->with('url',$url)
->with('sortby', $sortby)
->with('order', $order)
->with('order_inverse', $order_inverse);
}
What is the best approach to avoid DRY in such case?
Sharing methods among Controllers with Traits
Step 1: Create a Trait
<?php // Code in app/Traits/MyTrait.php
namespace App\Traits;
trait MyTrait
{
protected function showSearchResults(Request $request)
{
// Stuff
}
}
Step 2: use the Trait in your Controller:
<?php // Code in app/Http/Controllers/MyController.php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Traits\MyTrait; // <-- you'll need this line...
class MyController extends Controller
{
use MyTrait; // <-- ...and also this line.
public function getIndex(Request $request)
{
// Now you can call your function with $this context
$this->showSearchResults($request);
}
}
Now you can use your Trait in any other controller in the same manner.
It is important to note that you don't need to include or require your Trait file anywhere, PSR-4 Autoloading takes care of file inclusion.
You can also use Custom Helper classes as others have mentioned but I would recommend against it if you only intend to share code among controllers. You can see how to create custom helper classes here.
You can use traits (as ventaquil suggested) or you can create custom helpers file and add helpers there.
After that, you'll be able to use this helper from any class (controllers, models, custom classes, commands etc) like any other Laravel helper.
Use traits? More available here: http://php.net/manual/en/language.oop5.traits.php
You can create a helper file in your app directory. for eg. MethodHelper.php
In this file you can mention the method that you require using anywhere.
For instance,
<?php namespace App;
class MethodHelper
{
public static function reusableMethod()
{
//logic
}
}
You can use this method anywhere, by using the namespace and calling the method.
In the above eg.
The namespace would be:
The method call function would look like:
MethodHelper::reusableMethod();
You can send parameters too based on your functional requirements.
In your eg. you could have
public function showSearchResults(Request $req){
//
}
instead of reusableMethod().
Your call would be:
MethodHelper::showSearchResults($req);
I wanna ask about design pattern.
Why should I use dependency injection in constructor, not import it ('use statement')?
For example:
in my controller:
class AuthController extends Controller {
public function __construct(UserGateway $userGateway)
{
$this->userGateway = $userGateway;
}
public function doSomething()
{
$this->userGateway->foo();
}
}
Why don't use just like this instead?
use Acme\UserGateway;
class AuthController extends Controller {
public function doSomething()
{
UserGateway::foo();
}
}
Many thanks.
Assuming UserGateway is not laravel facade: here's the biggest advantage of injecting stuff this way: in the future, you might redefine what UserGateway actually is, and supply some other class (most often, it's subclass) instead of it like this:
$this->app->bind(UserGateway::class, function ($app) {
return new NewUserGateway();
});
This is extremely useful for overriding some parts of your code, especially if you're using same packages across multiple projects. And it does not require you to change the AuthController's code.
If UserGateway is a Facade, the only benefit you'll get is a better code navigation with you IDE, since it will know what class exactly are you referencing (assuming that you didn't re-bound it).
Can you help me with this? I am currently studying Laravel on my own and I followed the tutorials in the Laracasts and it is awesome. Before Laravel I am using CodeIgniter and Opencart in my projects and I started to study Laravel because I want to learn a new framework.
In CI and Opencart all your database queries are in the model. But in Laravel you can perform and queries in Controller?. Is it a proper way to the queries in Laravel?
I have this kind of code in the Controller:
<?php namespace App\Http\Controllers;
use App\Http\Requests;
use App\Http\Controllers\Controller;
use App\Article;
use Illuminate\Http\Request;
class ArticlesController extends Controller {
public function index() {
$articles = Article::all();
return view('articles.index')->with('articles', $articles);
}
}
Yes, this is perfectly fine for small applications.
For large-scale apps however, i'd recommend using repositories as they decouple your models from the controller - which makes them more readable and testable.
Your ArticlesController would translate to something like this:
<?php namespace App\Http\Controllers;
use App\Repositories\Articles\ArticleRepositoryInterface;
class ArticlesController extends Controller {
private $articles;
public function __construct(ArticleRepositoryInterface $articles)
{
$this->articles = $articles;
}
public function index()
{
return view('articles.index')
->with('articles', $this->articles->all());
}
}
Have a look at Laravels Service Container to understand the automatic resolution of the ArticleRepositoryInterface. Laracasts has some good videos on repositories.
Repositories is a smart decision to you. But why?
Basically, repositories is a 'gateway' between your application and your storage.
With repositories, you'll find your 'database queries' in a single place.
Let's think about the model Articles.
Instead of use a static instance of Articles all the times that you need to use it (Articles::find(), Articles::all(), etc), just create a repository of Articles.
Inject this repo in your controller (e.g.), and use 'features' storaged in your ArticleRepository.
What do you mean?
Let's consider a repository of Articles. What I'll use many times in my app of Articles model? I need select all, select by id, insert, update, delete. Basically these 'stuffs'. So, if I have all this stuffs in a place?
class ArticleRepository {
public function all(){}
public function getById($id){}
public function insert($data){}
public function update($data){}
public function delete($id){}
}
Inject this ArticleRepository in your controller. To do this, read a about IoC Container here: http://laravel.com/docs/5.0/container
The construct in your controller will be like this:
public function __construct(ArticleRepository $articles)
{
$this->articles = $articles;
}
Once all, when you need get all Articles in your controller, just do:
public function index()
{
$articles = $this->articles->all();
return View::make('articles.index')->with(['articles' => $articles]);
}
With this practice, you have a clean application with testables controllers and a beautiful organization and design. ;)
Look, I tried to be as didactic as possible to you understand the concept. The use of repositories is not only a way to do. So I let the links in the comments. And let other references here as well.
I'm sure you will understand quickly.
Success in learning! :)
https://laracasts.com/search?q=repositories&q-where=lessons
http://ryantablada.com/post/the-repository-pattern-in-action
http://culttt.com/2014/03/17/eloquent-tricks-better-repositories/
http://culttt.com/2013/07/15/how-to-structure-testable-controllers-in-laravel-4/