Cakephp 3.0 - Load Model inside Component - php

How to load a Model inside a Component in Cakephp 3.0?
Before(in Cakephp 2) you could use
$Model = ClassRegistry::init($modelName);
$Model->create(false);
$saved = $Model->save($data);
Whats the equivalent of that in 3.0?

As pointed out before, you can use the TableRegistry to access a model:
use Cake\ORM\TableRegistry;
$this->Articles = TableRegistry::get('Articles');
See here for documentation.

As someone said in the comments, you should at least read the migration guide to understand what the differences with 3.0 are. To address your specific question, you now can use the TableRegistry:
$table = TableRegistry::get($tableName);

Accessing a Component’s Controller
From within a Component you can access the current controller through the registry:
$controller = $this->_registry->getController();
for more please read this link : http://book.cakephp.org/3.0/en/controllers/components.html

One thing that I've done is to build a loadModel class in the component. This keeps my code consistent.
namespace App\Controller\Component;
use Cake\Controller\Component;
use Cake\ORM\TableRegistry;
class MyComponent extends Component {
public function initialize(array $config) {
parent::initialize($config);
$this->loadModel('Users');
}
private function loadModel($model) {
$this->$model = TableRegistry::get($model);
}
}

If you insist to use loadModel which adds the instance to the controller as a property then that's how you do it.
class ArticleComponent extends Component
{
public function initialize(array $config)
{
$this->controler = $this->_registry->getController();
}
public function myFunction($id)
{
$this->controller->loadModel('Articles');
$article = $this->controller->Articles->get($id);
debug($article);
}
}
This way is like telling controller to open a model for you:
$article = $component->controller->UserModel;
But when you can call a model straight away using TableRegistry what's the point of calling controller to call a model for you.
$article = $component->UserModel;
Long story short loadModel() is a wrapper for TableRegistry

my answer is same approch other answers. but, I try to save record inside component.
In this case, code is like following...
use Cake\ORM\TableRegistry;
---
$model = TableRegistry::get('MyModeles');
$entity = $model->newEntity();
$entity->set('filed1', 'newValue');
....
$model->save($entity);

You can dynamic access to table with the next snippet:
use Cake\Event\Event;
use Cake\Controller\Component;
use Cake\ORM\TableRegistry;
class TestComponent extends Component {
private $controller;
private $table;
public function startup(Event $event) {
$this->controller = $event->getSubject();
$this->table = TableRegistry::get($this->controller->name);
}
}

Related

How Can I Use Global Scope in Laravel Query Builder? (No Eloquent Model)

I'm working with too many mysql large views. I don't want to use Eloquent Model for the views.
I created "ViewBalance extends Illuminate\Support\Facades\DB". Everything worked as I wanted.
But i need to set init() method for company scope.
How can I use the global scope without init() method?
ViewModel
<?php
namespace App\Models\Views;
use App\Facades\CoreService;
use Illuminate\Support\Facades\DB;
class ViewBalance extends DB
{
const COMPANY_COLUMN = 'company_id';
const TABLE = 'view_balances';
public static function init()
{
return parent::table(self::COMPANY_COLUMN)
->where(self::COMPANY_COLUMN, CoreService::companyId());
}
}
In Controller
<?php
$data = ViewBalance::init()->get(); // Worked!
I have answered my own question. Because, I don't want to edit my question for more complicate. I want to talk about a solution to this problem.
I added $table_view variable and getView() method in Laravel model. If you want, you can create trait for clean codes.
It can be accessed easily views. Also it is part of the main model.
For example;
Laravel Basic Account Model
class Account extends Model {
protected $table = 'accounts';
protected $table_view = 'view_accounts';
public function getView()
{
return \DB::table($this->table_view)->where('global_scope', 1);
}
}
Laravel Account Controller
class AccountController extends Controller {
public function index()
{
$items = (new Account)->getView()->paginate(20);
}
}
public function scopeActive($query)
{
return $query->where('active', true);
}
or
public function scopeInactive($query)
{
return $query->where('active', false);
}

Laravel, namespaces and PSR-4

I'm trying to set up PSR-4 within a new Laravel 4 application, but I'm getting some troubles achieving what I want when it comes to build controllers.
Here's what I have now :
namespace MyApp\Controllers\Domain;
class DomainController extends \BaseController {
public $layout = 'layouts.default';
public function home() {
$this->layout->content = \View::make('domain.home');
}
}
I'm not so fond of using \View, \Config, \Whatever to use Laravel's classes. So I was wondering if I could put a use Illuminate\View; to be able to use View::make without putting a \.
Unfortunately, while doing this, I'm getting the following error : Class 'Illuminate\View' not found.
Could somebody help with this please ?
The problem in your case is that View is not located in Illuminate namespace but in Illuminate\View namespace, so correct import would be not:
use Illuminate\View;
but
use Illuminate\View\View;
You can look at http://laravel.com/api/4.2/ to find out which namespace is correct for class you want to use
Assuming BaseController.php has a namespace of MyApp\Controllers\Domain
namespace MyApp\Controllers\Domain;
use View;
class DomainController extends BaseController {
public $layout = 'layouts.default';
public function home() {
$this->layout->content = View::make('domain.home');
}
}
If BaseController.php has other namespace, i.e MyApp\Controllers
namespace MyApp\Controllers\Domain;
use MyApp\Controllers\BaseController;
use View;
class DomainController extends BaseController {
public $layout = 'layouts.default';
public function home() {
$this->layout->content = View::make('domain.home');
}
}
If, for instance, you controller needs to use another base class from Laravel, lets say Config.
namespace MyApp\Controllers\Domain;
use MyApp\Controllers\BaseController;
use View;
use Config;
class DomainController extends BaseController {
public $layout = 'layouts.default';
public function home() {
$this->layout->content = View::make('domain.home')->withName(Config::get('site.name'));
}
}
The use of View::make() takes advantage of the Laravel facades. To properly reference the facade, instead of directly referencing the class that gets resolved out of the iOC container, I would use the following:
use Illuminate\Support\Facades\View;
This will reference the View facade that is being used when calling View::make()

Laravel4 init another Model from a Model

How do initiate model from model in Laravel 4. I try the following but without any success
namespace App\Models;
use \Httpful\Request;
use \RecursiveIteratorIterator;
use \RecursiveArrayIterator;
use Illuminate\Support\Facades\DB as DB;
class Parser extends \Eloquent {
public function __construct(AffiApi $affiapi) {
$this->affiapi = $affiapi;
$url = "HTTP://some.com/xml/feed_config.xml";
$xml = Request::get($url)->expectsXml()->send();
$this->xml = $xml->body;
}
public function Test(){
$api = new Api();
//I get error Class 'App\Models\Api' not found
}
}
class Api extends Parser {
}
How di i do it properly or what is the cleanest way to achive this
The neatest and best practiced way to do this is by using a principle called dependency injection (DI). This way it is loosely coupled and it will also be possible to inject stub classes for unit testing.
class Parser extends \Eloquent {
public function __construct(Api $api) {
$this->api = $api;
}
public function Test() {
}
}
Be sure to run php artisan dump-autoload from the root of your project after adding new classes.

What is the correct way to access a model in an controller on Laravel

I'm new on Laravel 4 and I am trying to understand it.
is searched on google and on stackoverflow. Maybe i am not searching for the right syntax but i hope someone can help me, with it.
In CodeIgniter i understand it (probably). There I use in an Controller:
function __construct()
{ $this->load->model('example_m'); }
But how about in Laravel 4?
I figured out the following:
i make a static function in de model so i can access it everywhere. Example:
class Example extends Eloquent // this is the model
{
public static function TestExample(){
// do some stuff here
}
}
Or i could do it like this:
class ExampleController extends BaseController
{
public $test = null;
public function __construct()
{
$this->test = new Example();
}
public function index()
{
$this->test->TestExample();
}
}
My question is: Is there an other way and/or what is the correct way?
http://four.laravel.com/docs/ioc
App::bind('ExampleModelInterface', 'Example');
class ExampleController extends BaseController {
public function __construct(ExampleModelInterface $model)
{
$this->model = $model;
}
}
Do you mean simply accessing the method of a model?
Since they are static you use: Modell::method()
You might have to do a composer dump-autoload though so L4 autoloads it correctly.

Symfony2 How to have access to a set of data in all controllers?

I have searched but I can't find any similar issues or maybe I am phrasing it wrong. What I want to achieve is access to an object in all the controllers in my Bundle. For example:
<?php
namespace Example\CoreBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
class FolderController extends Controller
{
function indexAction()
{
$title = $this->folder->getTitle();
$description = $this->folder->getDescription();
}
}
Usually outside of Symfony I would have extended the Controller class myself with BaseController extends Controller and set this up in the construct method but I know Symfony doesn't use the construct method so I am a bit stuck as to where to go.
I would usually do something like this:
class BaseController extends Controller
{
function __construct()
{
parent::__construct();
//load up the folder from my model with an ID
$this->folder = $folder;
}
}
I would then extend BaseController from FolderController and go from there but I have tried this with Symfony and it does not work. I have looked into Services but do not think this is what I need to make this work. If any more details are required please let me know, thanks.
If I understand your question correctly, services are indeed what you're looking for.
First, define a service in services.yml:
services:
vendor.folder_manager:
class: Vendor\FolderBundle\Entity\Manager\FolderManager
arguments:
em: "#doctrine.orm.entity_manager"
class: Vendor\FolderBundle\Entity\Folder
Then create that FolderManager class:
<?php
namespace Vendor\FolderBundle\Entity\Manager;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\EntityRepository;
class FolderManager
{
protected $em;
protected $repo;
protected $class;
public function __construct(EntityManager $em, $class) {
$this->em = $em;
$this->class = $class;
$this->repo = $em->getRepository($class);
}
public function findById($id) {
return $this->repo->findById($id);
}
public function getRepository() {
return $this->repo;
}
}
Finally, in your controller:
$this->container->get('vendor.folder_manager')->findById($folderId);
Or:
$this->container->get('vendor.folder_manager')->getRepository()->findById($folderId);
Symfony2 will automatically inject the entity manager the class into the manager, so all you have to provide in the controller is the folder's id.
Edit:
To make it prettier, you could also make a shortcut function in your controller:
protected function getFolderManager()
{
return $this->container->get('vendor.folder_manager');
}
Then you can do:
$this->getFolderManager()->findById($folderId);

Categories