Symfony 3.4.
I have annotations for my controller:
/**
*
* #Route("/{prefix}", requirements={"prefix":"daily_task|event"})
*/
class TaskController extends Controller
and want to access current {prefix} value directly from controller's methods (which aren't routed actions). How to get it's value?
Finally: $this->get('request_stack')->getCurrentRequest()->get('prefix')
Symfony will pass you the variables automatically if you use them as function parameters, like this:
/**
*
* #Route("/{prefix}", requirements={"prefix":"daily_task|event"})
*/
class TaskController extends Controller {
/**
* #Route("/{_locale}/some/path", name="_some_route_name")
*/
public function actualAction($prefix, $_locale) { /* ... */ }
}
Alternatively you can use the whole request like this:
/**
*
* #Route("/{prefix}", requirements={"prefix":"daily_task|event"})
*/
class TaskController extends Controller {
/**
* #Route("/{_locale}/some/path", name="_some_route_name")
*/
public function actualAction(Request $request) {
$prefix = $request->get('prefix');
}
}
Related
I want to reuse a route in symfony as I used in Slim framework.
for example: in Slim I could define groups and then I would put the actions inside the group:
$app->group("example",..{
$app->get("/staff"...);
$app->get("test");
$aap->group("books",..{
$app->get("/"..);
$app->delete("/{id}")
})
});
And to access to the action test the url would be like: "domain/example/test", and to access staff: "domain/example/staff";
and to access book would be like: "domain/example/book/";
can I do this in symfony without having to go to every controller and put it manually.
The symfony documentation provide an example on how defines a prefix for all action routes:
/**
* #Route("/example")
*/
class ExampleController extends Controller
{
/**
* #Route("/staff")
*/
public function staffAction()
{
}
/**
* #Route("/test")
*/
public function testAction()
{
}
}
/**
* #Route("/example/books")
*/
class BookController extends Controller
{
/**
* #Route("/")
*/
public function indexAction()
{
}
/**
* #Route("/{id}")
* #Method({"DELETE"})
*/
public function deleteAction($id)
{
}
}
In my views i am extending a default blade template which acts as my Master Template. I have a ViewComposer setup which serves this template with a number of variables.
I have come to a situation where i need to access one of these variables within my index.blade.php which is the page initiating the #extends function.
Do the variable passed via the ViewComposer reach the scope of the initial view? Or will i need to create another ViewComposer to pass the same variable.
ViewComposer
<?php
namespace App\Http\ViewComposers;
use Illuminate\View\View;
use Illuminate\Http\Request;
use App\Repositories\UserRepository;
use Sentinel;
use App\ProjectUsers;
class MasterComposer
{
/**
* The user repository implementation.
*
* #var UserRepository
*/
protected $users;
private $request;
/**
* Create a new profile composer.
*
* #param UserRepository $users
* #return void
*/
public function __construct(Request $request)
{
$this->request = $request;
// Dependencies automatically resolved by service container...
$uid = Sentinel::getUser()->id;
$this->users = ProjectUsers::where("user_id", '=', $uid)->get();
}
/**
* Bind data to the view.
*
* #param View $view
* #return void
*/
public function compose(View $view)
{
$view->with('projects', $this->users);
$view->with('activeProject', $this->request->session()->get("activeProject"));
}
}
ComposerServiceProvider
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class ComposerServiceProvider extends ServiceProvider {
/**
* Register bindings in the container.
*
* #return void
*/
public function boot() {
// Using class based composers...
view ()->composer ( 'admin/layouts/default', 'App\Http\ViewComposers\MasterComposer' );
}
/**
* Register the service provider.
*
* #return void
*/
public function register() {
//
}
}
index.blade.php
#extends('admin/layouts/default')
{{ $activeProject }}
This ultimately give me an undefined variable error.
Undefined variable: activeProject (View: /home/laravel/public_html/base/resources/views/admin/index.blade.php)
Yes, all variables which are available in the master layout will be passed to any of its children.
Since you're using #extends in your content layout you can use this
#extends('admin/layouts/default', ['activeProject' => $activeProject])
If this doesn't work you might need to pass it through your controller
I am calling the \prelaunchroute in my application and this is how it is defined in my routes.php:
`Route::get('/prelaunch', [ 'uses' => 'SubscriptionController#getReferrer', 'as' => 'subscriber.referral'], function () {
return view('prelaunch');
});`
But unfortunately, I am getting:
Call to undefined method App\Http\Controllers\SubscriptionController::getMiddleware()
This is a draft of my SubscriptionController code:
namespace App\Http\Controllers;
use App\Http\Manager\SubscriptionManager;
use Illuminate\Support\Facades\Request;
/**
* Class SubscriptionController
* #package App\Http\Controllers
*/
class SubscriptionController
{
/**
* #var \SubscriptionManager $subscriptionManager
*/
protected $subscriptionManager;
/**
* SubscriptionController constructor.
*/
//public function __construct(SubscriptionManager $subscriptionManager)
public function __construct(SubscriptionManager $subscriptionManager)
{
$this->subscriptionManager = $subscriptionManager;
}
/**
* #param Request $request
* #return void
*/
public function subscribe(Request $request)
{
$this->subscriptionManager->subscribeToList($request);
}
/**
* #param Request $request
* #return void
*/
public function unsubscribe(Request $request)
{
$this->subscriptionManager->unsubscribeFromList($request);
}
/**
* #return void
*/
public function getReferrer()
{
print_r(Input::all());
die;
$utm_source = \Input::get('utm_source');
return view('prelaunch');
}
}
Any thoughts on this one? Please bare in mind that I am fairly new to Laravel.
You forgot to extend the abstract controller:
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use App\Http\Manager\SubscriptionManager;
use Illuminate\Support\Facades\Request;
/**
* Class SubscriptionController
* #package App\Http\Controllers
*/
class SubscriptionController extends Controller
Try to extends Controller
/**
* Class SubscriptionController
* #package App\Http\Controllers
*/
class SubscriptionController extends Controller
{
I'm building an API and I would ask something about using namespaces on a Symfony2 controller.
Is there a real difference doing :
<?php
namespace My\APIBundle\Controller;
use FOS\RestBundle\Controller\Annotations\View,
FOS\RestBundle\Controller\Annotations\Post,
FOS\RestBundle\Controller\Annotations\Get;
use [...]
class MyRestController extends Controller {
[...]
/**
* #View()
* #Get()
*/
public function getAction(Thing $thing) {
return $thing;
}
/**
* #View()
* #Post()
*/
public function postAction() {
}
or doing
<?php
namespace My\APIBundle\Controller;
use FOS\RestBundle\Controller\Annotations as Rest;
use [...]
class MyRestController extends Controller {
[...]
/**
* #Rest\View()
* #Rest\Get()
*/
public function getAction(Thing $thing) {
return $thing;
}
/**
* #Rest\View()
* #Rest\Post()
*/
public function postAction() {
}
Would the alias load everything in the given namespace, losing perfs ?
Or will it load only annoted classes, unitary ?
My error message:
Illuminate \ Container \ BindingResolutionException
Target [Project\Backend\Service\Validation\ValidableInterface] is not instantiable.
I understand that interfaces and abstract classes are not instantiable so I know that Laravel should not be trying to instantiate my interface. Yet somehow it's trying to and I suspect this may be a binding issue...even though I believe I have bound it correctly and have registered it as a service provider.
I should mention that I have taken this example out of Chris Fidao's "Implementing Laravel" and it's almost identical!
This is the first couple of lines of my form class:
namespace Project\Backend\Service\Form\Job;
use Project\Backend\Service\Validation\ValidableInterface;
use Project\Backend\Repo\Job\JobInterface;
class JobForm {
/**
* Form Data
*
* #var array
*/
protected $data;
/**
* Validator
*
* #var \Project\Backend\Form\Service\ValidableInterface
*/
protected $validator;
/**
* Job repository
*
* #var \Project\Backend\Repo\Job\JobInterface
*/
protected $job;
public function __construct(ValidableInterface $validator, JobInterface $job)
{
$this->validator = $validator;
$this->job = $job;
}
This is the first few lines of my validator class:
namespace Project\Backend\Service\Form\Job;
use Project\Backend\Service\Validation\AbstractLaravelValidator;
class JobFormValidator extends AbstractLaravelValidator {
// Includes some validation rules
This is the abstract validator:
namespace Project\Backend\Service\Validation;
use Illuminate\Validation\Factory;
abstract class AbstractLaravelValidator implements ValidableInterface {
/**
* Validator
*
* #var \Illuminate\Validation\Factory
*/
protected $validator;
/**
* Validation data key => value array
*
* #var Array
*/
protected $data = array();
/**
* Validation errors
*
* #var Array
*/
protected $errors = array();
/**
* Validation rules
*
* #var Array
*/
protected $rules = array();
/**
* Custom validation messages
*
* #var Array
*/
protected $messages = array();
public function __construct(Factory $validator)
{
$this->validator = $validator;
}
This is the code where I bind it all to the app:
namespace Project\Backend\Service\Validation;
use Illuminate\Support\ServiceProvider;
use Project\Backend\Service\Form\Job\JobFormValidator;
class ValidationServiceProvider extends ServiceProvider {
public function register()
{
$app = $this->app;
$app->bind('Project\Backend\Service\Form\Job\JobFormValidator', function($app)
{
return new JobFormValidator($app['validator']);
});
}
}
This is then registered in app/config/app.php:
.....
'Project\Backend\Service\Validation\ValidationServiceProvider',
....
Finally these are the first few lines of my controller:
use Project\Backend\Repo\Job\JobInterface;
use Project\Backend\Service\Form\Job\JobForm;
class JobController extends \BaseController {
protected $jobform;
function __construct(JobInterface $job, JobForm $jobform)
{
$this->job = $job;
$this->jobform = $jobform;
}
You need to tell Laravel which instance it should use for a certain interface when injecting it into the constructor via type hinting.
You do this using the bind() method (in your service provider for example)
$app->bind('JobInterface', 'Job'); // Job being the class you want to be used
I highly recommend you watch the video here where Taylor Otwell, the creator of Laravel, explains this and some other things.
First you need to bind using
/app/Providers/AppServiceProvider.php
<?php namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider {
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot()
{
//
}
/**
* Register any application services.
*
* #return void
*/
public function register()
{
//
$this->app->bind('JobInterface', 'Job');
}
}
Once you complete this change
Run composer update