Laravel4 init another Model from a Model - php

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.

Related

PHP class property contains child of a parent but was shown error due to parent class not containing method from child

I am learning OOP right now and I have a property that specifies what class it should be.
class Controller{
public ?Model $model;
}
class LoginModel extends Model{
public function login(){}
}
Now, I want to load a class that is an inheritance of Model but contains a unique method not from Model. That causes the lint to think that there is an error in the code. Is there a way to fix the issue from Controller->model?
$controller = new Controller();
$controller->model = new LoginModel();
echo $controller->model->login();
I know that one way is we can change Model to LoginModel but that would be tedious if there are a lot of different controllers with different model designed to do different things.
consider this example
class Controller
{
public ?Model $model;
}
class Model { }
class LoginModel extends Model
{
public function login() { }
}
class LogoutModel extends Model { }
$controller = new Controller();
$controller->model = new LoginModel();
$controller->model->login(); //This works
$controller->model = new LogoutModel();
$controller->model->login(); //This doesn't works
The lint is saying that you cannot assure that there will be a login() to call. So unless you'll have a login() method in all models, in which case you can define an abstract or interface, otherwise since it can fail it will show you the error.
PS: there is a way around it, but I wouldn't recommend it for regular use.
if($controller->model instanceof LoginModel)
{
$controller->model->login(); //This works
}

Config class not found when unit testing laravel package

I'm working on a Laravel (5.4) package, and I'm trying to do unit testing. I have this class :
<?php
namespace Sample;
class Foo
{
public function getConfig()
{
$config = \Config::get('test');
return $config;
}
}
I have this test :
<?php
use PHPUnit\Framework\TestCase;
use Sample\Foo;
class FooTest extends TestCase
{
public function testGetConfig()
{
$foo = new Foo;
$config = $foo->getConfig();
}
}
When I execute phpunit I have this error :
Error: Class 'Config' not found
How can I unit test this class ?
Thank you.
Instead of extends PHPUnit\Framework\TestCase, you should extends Tests\TestCase:
<?php
namespace Tests\Unit;
// use PHPUnit\Framework\TestCase;
use Tests\TestCase;
use Sample\Foo;
class FooTest extends TestCase
{
public function testGetConfig()
{
$foo = new Foo;
$config = $foo->getConfig();
}
}
Moreover, Config or other Laravel facades may not work in #dataProvider method, please see Laravel framework classes not available in PHPUnit data provider for more info.
It is good practice to mock the dependencies in your code. In this case you are depending on an outside class (Config). Usually I test it like this:
// make sure the mock config facade receives the request and returns something
Config::shouldReceive('get')->with('test')->once()->andReturn('bla');
// check if the value is returned by your getConfig().
$this->assertEquals('bla', $config);
Obviously, you need to import the Config facade in your test.
BUT: I would inject the Config class in the constructor in my real code, instead of using the facade. But that's me... :-)
Something like this
class Foo
{
/** container for injection */
private $config;
public function __construct(Config config) {
$this->config = $config;
}
public function getConfig()
{
$config = $this->config->get('test');
return $config;
}
}
And then test it by injecting a mock Config into the constructor.
Try by including like this
use Illuminate\Support\Facades\Config;

Cakephp 3.0 - Load Model inside Component

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);
}
}

Issue with Facade and injected dependency in Laravel 4

I am having an issue getting a Facade to work properly with a dependency injected into the underlying class.
I have a class called 'Listing'. It has one dependency called 'AdvertRepository' which is an interface and a class called EloquentAdvert which implements the interface. The code for these three classes is here:
// PlaneSaleing\Providers\Listing.php
<?php namespace PlaneSaleing\Providers;
use PlaneSaleing\Repositories\Advert\AdvertRepository;
class Listing {
protected $advert;
public function __construct (AdvertRepository $advert_repository) {
$this->advert = $advert_repository;
}
public function test() {
$this->advert->test();
}
public function test2() {
echo "this has worked";
}
}
// PlaneSaleing\Repositories\Advert\AdvertRepository.php
<?php namespace PlaneSaleing\Repositories\Advert;
interface AdvertRepository {
public function test();
}
// PlaneSaleing\Repositories\Advert\EloquentAdvert.php;
<?php namespace PlaneSaleing\Repositories\Advert;
class EloquentAdvert implements AdvertRepository {
public function test() {
echo 'this has worked';
}
}
I have then created a service provider called ListingServiceProvider.php, which has the following code:
// PlaneSaleing/Providers/ListingServiceProvider.php
<?php namespace PlaneSaleing\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\App;
class ListingServiceProvider extends ServiceProvider {
public function register() {
App::bind('PlaneSaleing\Repositories\Advert\AdvertRepository', 'PlaneSaleing\Repositories\Advert\EloquentAdvert');
}
}
I also added this to the ServiceProviders array in app.php
Now, if I inject Listing as a dependency into a controller and call the test method (as shown below) Laravel correctly detects the dependency, instantiates EloquentAdvert via its binding and displays 'this has worked'.
// Controllers/TestController.php
use PlaneSaleing\Providers\Listing;
class TestController extends BaseController {
protected $listing;
public function __construct(Listing $listing) {
$this->listing = $listing;
}
public function test1() {
$this->listing->test();
}
}
Now, I then created a facade for Listing. I added a new facade as follows and added an alias in app.php:
// PlaneSaleing\Providers\ListingFacade.php
<?php namespace PlaneSaleing\Providers;
use Illuminate\Support\Facades\Facade;
class ListingFacade extends Facade {
protected static function getFacadeAccessor() {
return 'Listing';
}
}
I also added the following new lines to ListingServiceProvider.php:
<?php namespace PlaneSaleing\Providers;
use PlaneSaleing\Repositories\Advert\AdvertRepository;
use PlaneSaleing\Repositories\Advert\EloquentAdvert;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\App;
class ListingServiceProvider extends ServiceProvider {
public function register() {
App::bind('PlaneSaleing\Repositories\Advert\AdvertRepository', 'PlaneSaleing\Repositories\Advert\EloquentAdvert');
// New lines...
$this->app['Listing'] = $this->app->share(function() {
return new Listing(new AdvertRepository);
});
}
}
NOW...if I call Listing::test(), I get the following error: Cannot instantiate interface PlaneSaleing\Repositories\Advert\AdvertRepository.
If I call Listing::test2() , I get 'this has worked' so it seems the Facade is working correctly.
It seems that when accessing Listing via its Facade the binding between AdvertRepository and EloquentAdvert doesnt work. I have looked at my code in the ServiceProvider thinking it was the issue, but I cant figure it out.
Both the Facade and binding work when tested individually but not when both are used at the same time.
Any ideas???
OK, So I have figured it out...For those who run into a similar problem...
The offending statement was in ListingServiceProvider.php which read:
$this->app['Listing'] = $this->app->share(function() {
return new Listing(new AdvertRepository);
});
The error is the new AdvertRepository statement. The reason being is that, we are telling php to directly instantiate the interface 'AdvertRepository'. Instead, we need to tell Laravel to instantiate the appropriate implementation of the 'AdvertRepository' interface. To do that, we use App::make('AdvertRepository'). That way, Laravel uses the binding previously declared to instantiate the correct implementation.
If your constructor is not being inject with a class, you must tell Laravel what class will be used when it needs to instantiate a particular interface:
Put this in your filters or bindings file:
App::bind('PlaneSaleing\Repositories\Advert\AdvertRepository', function()
{
return new PlaneSaleing\Repositories\Advert\EloquentAdvert;
});

Loading a Parent Class in Symfony 2

I've set up a test parent class in my Symfony 2 controller as follows:
<?php
namespace Zetcho\AmColAnBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
class BaseController extends Controller
{
public function validateUser()
{
$user['first_name'] = "Name";
$user['signin'] = true;
return $user;
}
}
class DefaultController extends BaseController
{
public function indexAction()
{
$user = $this->validateUser();
$displayParms['user'] = $user;
return $this->render('ZetchoAmColAnBundle:Default:index.html.twig',$displayParms);
}
}
The code is in src/Zetcho/AmColAnBundle/Controller/DefaultController.php
The test code works. I'd now like to move the parent class (BaseController) out of the controller file to its own so I can reuse it in my other controllers. I want to put it in the same directory as the other controllers and I'd like to declare it the same way as the Controller in the use statement above. What's the best/accepted way to do this in Symfony 2?
You do this in Symfony2 exactly the same way as you would with any PHP class. Split your classes into separate files like this:-
src/Zetcho/AmColAnBundle/Controller/BaseController.php
namespace Zetcho\AmColAnBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
class BaseController extends Controller
{
public function validateUser()
{
$user['first_name'] = "Name";
$user['signin'] = true;
return $user;
}
}
src/Zetcho/AmColAnBundle/Controller/DefaultController.php
namespace Zetcho\AmColAnBundle\Controller;
use Zetcho\AmColAnBundle\Controller\BaseController;
class DefaultController extends BaseController
{
public function indexAction()
{
$user = $this->validateUser();
$displayParms['user'] = $user;
return $this->render('ZetchoAmColAnBundle:Default:index.html.twig',$displayParms);
}
}
Its really quite simple once you know how. Remember that controllers in symfony2 are just normal PHP classes, there is nothing special about them.

Categories