CakePHP 3.x - Associations Error- unable Linking Tables Together - mysql

i'm trying to Associate 2 tables:Jobes and Types. the table structure of types is very simple and includes only id and name ( 1.full-time 2.partial 3.freelance)
Jobs table, in addition to all other fields contains also the foreign key of Types named:type_id so Jobs belongsTo Types.
i follow the Cake convention but still the same error:
Jobs is not associated with Types...
i'v created JobsTable class
use Cake\ORM\Table;
class JobsTable extends Table{
public $name= 'Jobs';
public function initialize(array $config){
$this->belongsTo('Types');
}
}
declare it in the controller:
<?php
namespace App\Controller;
use App\Controller\AppController;
class JobsController extends AppController
{
public $name='Jobs';
public function index(){
//Get job info
$jobs =$this->Jobs->find('all')->contain(['Types']);
$this->set('jobs',$jobs);
}
}
and then past it to view (index.ctp):
<?php foreach ($jobs as $job) : ?>
<p> <?php echo $job->title; ?> <?php echo $job->types->name; ?></p>
<?php endforeach; ?>
Where is my mistake?

You need to set foreignKey too.
JobsTable.php
$this->belongsTo('Types', [
'foreignKey' => 'type_id'
]);
TypesTable.php
$this->hasMany('Jobs', [
'foreignKey' => 'type_id'
]);
To generate proper relations from CLI go to 'project_directory/bin' in command promot and hit following bake command:
cake bake types model // for types table
and
cake bake jobs model // for jobs table
See details here : CakePhp3 Code Generation With Bake

Related

YII2 Codeception - create fixture. [Error] Class 'tests\fixtures\UserFixture' not found

I'm using YII2 2.0.10, basic. It seems that it don't use yii-codeception module anymore. So documentation from this page is not actual:
http://www.yiiframework.com/doc-2.0/guide-test-fixtures.html
My problem is that I can't load fixture to my test.
I'm using such way:
tests\unit\models\UserTest.php
<?php
namespace tests\models;
use app\models\User;
use tests\fixtures\UserFixture;
class UserTest extends \Codeception\Test\Unit
{
public function testFindUserById()
{
// load fixtures
$this->tester->haveFixtures([
'user' => [
'class' => UserFixture::className(),
// fixture data located in tests/_data/user.php
'dataFile' => codecept_data_dir() . 'user.php'
]
]);
// get first user from fixtures
$this->tester->grabFixture('user', 0);
...
tests\fixtures\UserFixture.php
namespace tests\fixtures;
use yii\test\ActiveFixture;
class UserFixture extends ActiveFixture
{
public $modelClass = 'dektrium\user\models\User';
}
And have some data returned from tests\fixtures\data\user.php
After vendor/codeception/base/codecept run I get
2) UserTest: Find user by id
Test tests/unit/models/UserTest.php:testFindUserById
[Error] Class 'tests\_fixtures\UserFixture' not found
#1 tests\models\UserTest->testFindUserById
What I'm doing wrong?

Join multiple tables Eloquent

Laravel version 4.2
I am trying to Join multiple tables and get results
I have now 2 tables
1- projects_info (id - pro_title - pro_address ...)
2- projects_images (id - image - image_id)
I need to grape the related images from the 'projects_images' where image_id = projects_info id
here what I try
here is my Route
//Projects Route
Route::get('our-projects', 'projectController#currentProjects');
Route::get('project/{id}', 'projectController#viewProject');
//Projects details
//Route::get('project/{id}/about-project', 'projectController#viewProject');
Route::get('project/{id}/about-project', array('as' => 'about-project', 'uses' => 'projectController#viewProject'));
Route::get('project/{id}/project-images', array('as' => 'project-images', 'uses' => 'projectController#viewProjectImages'));
Projects Model
class Projects extends Eloquent implements UserInterface, RemindableInterface
{
use UserTrait, RemindableTrait;
protected $table = 'project_info_arabic';
public function projectImages()
{
return $this->belongsTo('ProjectsImages', 'image_id');
}
}
ProjectsImages Model
class ProjectsImages extends Eloquent implements UserInterface, RemindableInterface
{
use UserTrait, RemindableTrait;
protected $table = 'projects_images';
public function project()
{
return $this->hasOne('Projects', 'id');
}
}
and this is my ProjectController
public function currentProjects()
{
$pro = Projects::all();
return View::make('projects.currentProjects', ['pro' => $pro]);
}
public function viewProject($id)
{
$vp = Projects::find($id);
return View::make('projects.viewProject', ['viewPro' => $vp]);
}
public function viewProjectImages($id)
{
$vpi = ProjectsImages::with('project')->get();
//$vpi = DB::table('projects_images')->select('id', 'image', 'image_id')->get();
return View::make('projects.projectDetails.projectImages', ['viewProImg' => $vpi]);
}
and here is how I am trying to include each page in my projectsDetails VIEW
<div class="mCustomScrollbar">
#if(Request::path()=="project/$viewPro->id/about-project")
#include('projects.projectDetails.aboutProject')
#elseif(Request::path()=="project/$viewPro->id")
#include('projects.projectDetails.aboutProject')
#elseif(Request::path()=="project/$viewPro->id/project-images")
#include('projects.projectDetails.projectImages')
#endif
</div>
and last the projectImages VIEW
<ul>
#foreach($viewProImg as $vpi)
<li class="col-sm-3 col-xs-12">
{{ HTML::image("images/projects/$vpi->image", '', array('class'=>'img-responsive')) }}
</li>
#endforeach
</ul>
My Problem
1- what I got here is all the images in the table it should be only the images related to this project
any help here please
First of all, the project has many images
public function projectImages()
{
return $this->hasMany('App\ProjectsImage');
}
.. and the image belongs to a project
public function project()
{
return $this->belongsTo('App\Project', 'project_id');
}
You should always refer to the model. If you are referring to a model then you should have in mind that its good practice to name the models in singular form, as in Project and ProjectImage. In Laravel, they expect you to have name the tables name in plural and the model name in singular. So if you haven't explicit set the table name, it will look for the model name plus a s (ProjectS).
Then, you can call the projectImages -function from a Project object. So in the view it will look something like this
#foreach($project->projectImages()->get() as $image)
// Do what you want with each project images
#endforeach

How to using echo HTML::script in laravel 5.0 in Controller

I need to use
echo HTML::script('js/ckeditor/ckeditor.js');
in my controller and function, but error not found HTML
I am using larvel 5.0.
tnx
HTML and FORM are removed from Laravel 5+ to use them you have to include them in composer.json. And add an Alias and Service Provider in config\app.php
You can find them here
And as from laravel 5 {{}} is same as {{e('sting')}} //htmlentities
To output html you need to use {!! HTML::() !!} without htmlentities
And if you need to use echo
Simply wrap it to <?php ?> tags <?php echo HTML::() ?>
And if you use it Controller
you need to use like \Html::() or before Controller class add
use HTML;
HTML or Html depends on you Alias array in config\app.php
composer.json
"illuminate/html": "^5.0",
Config/app.php Service Provider
'Illuminate\Html\HtmlServiceProvider',
Config/app.php aliases
'Form' => 'Illuminate\Html\FormFacade',
'HTML' => 'Illuminate\Html\HtmlFacade',
Controller
<?php namespace App\Http\Controllers;
use HTML;
class SomeController extends Controller{
public function foo(){
echo HTML::();
}
}

Codeigniter 1-many db query on two tables which call for nested loops

I've read through a couple posts which are really close to the same question I am about to ask, but I'm still not grasping the MVC way. One example was close and titled "Codeigniter db query on two tables", but I'm getting the "Undefined property" errors which reinforces that fact I'm not calling objects properly. I would prefer not to use DataMapper simply because if I need to go out and get additional classes, then I might just go back to the procedural coding route. I was just a little excited on understanding how this framework implementation works.
I have two tables, lets call one "apps" and the other would be "mappings". "Apps" are applications which use apache as a reverse proxy configuration like this:
ProxyPass /mapping/ https:///
ProxyPassReverse /mapping/ https:///
Some of the apps could request multiple reverse proxy mappings, so its a 1-many design.
My objective is to use a select statement for the apps table then print out every column I desire from that table:
for example, I currently have two application defined in my "apps" table, in which one of the applications has two reverse proxy mappings,and the other has one. The prxypass lines below the data from the apps table would be coming from the apps_mapping table.
App: App ABC
Owner: ABC Team
Date Requested: 2013-10-27
ProxyPass /ABC-Resource/ https://<to-some-internal-URL>/
ProxyPassReverse /ABC-resource/ https://<to-some-internal-URL>/
App: App XYZ
Owner: XYZ Team
Date Requested: 2013-10-27
ProxyPass /XYZ-mapping/ https://<to-some-internal-URL>/
ProxyPassReverse /XYZ-mapping/ https://<to-some-internal-URL2>/
ProxyPass /anothermapp/ https://<to-some-internal-URL>/
ProxyPassReverse /anothermapping/ https://<to-some-internal-URL2>/
I've tried to model my first attempt of using CodeIgniter by way of modifying their tutorial provided by the CodeIgniter example in their user_guide.
Now what I haveis.
Model Class:
<?php
class Prp_model extends CI_Model {
public function __construct()
{
$this->load->database();
}
//GET APP THE ROWs FROM THE apps TABLE
public function get_appsUsingPrp()
{
$query = $this->db->get('apps');
return $query->result_array();
}
//GET THE MAPPINGS FROM THE apps_mappings TABLE
//FOR EACH APP BY WAY OF UNIQUE id IN THE appsTABLE
public function get_prpMappings($id = FALSE)
{
$query = $this->db->get_where('apps_mappings', array('resourceID' => $id));
return $query->result_array();
}
?>
for the above class, instead of using a return function on get_prpMappings() should I be putting it in a variable? Even then, how would one supply a value for the $id in the code called int he views page?
Controller Class
<?php
class Prp extends CI_Controller {
public function __construct()
{
parent::__construct();
$this->load->model('prp_model');
}
public function index()
{
$data['apps'] = $this->prp_model->get_prp();
$data['mappings'] = $this->prp_model->get_prpMappings($id);
$data['title'] = 'PRP archive';
$this->load->view('templates/header', $data);
$this->load->view('prp/index', $data);
$this->load->view('templates/footer');
}
public function view($id)
{
$data['apps'] = $this->prp_model->get_prp();
$data['mappings'] = $this->prp_model->get_prpMappings($id);
}
}
View
<?php
print_r($apps);
print_r($mappings);
foreach ($apps as $details): ?>
<div id="main">
<ul>
<?php echo "<li>App Name: ".$details['app_name'] ?>
<?php echo "<li>EPRID: ".$details['EPRID'] ?>
<?php echo "<li>Requestor: ".$details['requestor'] ?>
<?php echo "<li>Team PDL: ".$details['PDL'] ?>
<?php foreach ($mappings as $map): ?>
<?php echo "<li>ProxyPass /".$map['resource']."/ ".$map['destURL'] ?>
<?php echo "<li>ProxyPassReverse /".$map['resource']."/ ".$map['destURL'] ?>
<?php endforeach ?>
</ul>
</div>
<hr />
<?php endforeach ?>
?>
Getting down to my confusion.... Should I be doing all the foreach looping in the model and/or the controller classes if I'm not going to setup the DataMapper Class?
Is there a way to call the get_prpMappings($id) function defined in the model class directly in the view? The only way for that function to work for me, is when the id of the app row is provided when iterating through the rows.
I tried putting $this->prp_model->get_prpMappings($id); in the view, but the view page doesn't seem to identify the class.
Lastly.. By the looks of it, it appears I would be doing more coding with a framework (such as CodeIgniter or Zend), then it would be to just write everything from scratch. But I'm under the impression the framework is to provide convenience down the road of additional coding. I'm just not seeing it. Please help.
UPDATED! I hope I understand this.
I have modified my logic to express the output desired. Would you be able to tell me if it is an inefficient way? Here is the logic:
MODEL CLASS:
<?php
class Prp_model extends CI_Model {
public function __construct()
{
$this->load->database();
}
//GET APP THE ROWs FROM THE sharedITG TABLE
public function get_appsUsingPrp()
{
$query = $this->db->get('sharedITG');
return $query->result_array();
}
//GET THE MAPPINGS FROM THE sharedITG_mappings TABLE
//FOR EACH APP BY WAY OF UNIQUE id IN THE shareITG TABLE
public function get_prpMappings($id = FALSE)
{
$this->db->select('resourceID, resource, destURL');
$query = $this->db->get_where('sharedITG_mappings', array('resourceID' => $id));
return $query->result_array();
}
public function get_prp()
{
//loop through all apps
foreach ($this->get_appsUsingPrp() as $app)
{
//print_r($app);
foreach ($this->get_prpMappings($app['id']) as $mappings)
{
$map[] = $mappings;
}
}
return $map;
}
}
Controller Class
<?php
class Prp extends CI_Controller {
public function __construct()
{
parent::__construct();
$this->load->model('prp_model');
}
public function index()
{
$data['mappings'] = $this->prp_model->get_prp();
$data['apps'] = $this->prp_model->get_appsUsingPrp();
$data['title'] = 'PRP archive';
$this->load->view('templates/header', $data);
$this->load->view('prp/index', $data);
$this->load->view('templates/footer');
}
public function view($id)
{
$data['apps'] = $this->prp_model->get_appsUsingPrp();
$data['mappings'] = $this->prp_model->get_prp();
}
}
VIEW code:
<?php
//print_r($apps);
//print_r($mappings);
foreach ($apps as $details): ?>
<div id="main">
<ul>
<?php echo "<li>App Name: ".$details['app_name'] ?>
<?php echo "<li>EPRID: ".$details['EPRID'] ?>
<?php echo "<li>Requestor: ".$details['requestor'] ?>
<?php echo "<li>Team PDL: ".$details['PDL'] ?>
<?php
foreach ($mappings as $map)
{
if ($details['id'] == $map['resourceID'])
{
echo "<li>ProxyPass /".$map['resource']."/ ".$map['destURL'];
echo "<li>ProxyPassReverse /".$map['resource']."/ ".$map['destURL'];
}
}
?>
</ul>
</div>
<hr />
<?php endforeach ?>
So after further research, I found a forum that gave me a pretty decent example. I'm not sure if its the most optimal way to do this, but it worked for me and still (kind of) maintained the MVC model for Code igniter. The foreach in the function below is what I added. It appears it loops through the current result and obtains all rows for the second table that has a relationship between Table2ID and IDFromTable. Then adds the results by way of $result{$key}.
public function get_resuts()
{
$query = $this->db->get('table1');
$result = $query->result_array();
foreach ( $result as $key => $row )
{
$query = $this->db->get_where('Table2', array('Table2ID' => $row['IDFromTable']));
$row['DesiredFieldFromTable#'] = $query->result_array();
$result[$key] = $row;
}
return $result;
}
Then its available in the view by looping through the second array with the content from the foreach results in the get_resuts() function. I'm interested in learning of other ways to do this too.

Query is returning empty arrays in CakePHP (model and controller are set up)

I'm using Cake's find('all') method in the controller to query a table I have, and the requestAction method to use the controller function (and so to output the data) within the view. The problem is that the find method is returning empty arrays(ouput is 'ArrayArrayArray'). The table is named 'users' (as per Cake conventions) and the code for all three files are below:
Code for the view (test.ctp)
<?php
$users = $this->requestAction('/users/read');
foreach($users as $user) {
echo $user;
}
?>
Code for the controller (users_controller.php)
<?php
class UsersController extends AppController {
var $name = 'Users';
function read(){
$users = $this->User->find('all');
if(isset($this->params['requested'])) {
return $users;
}
}
}
?>
Code for the model (user.php)
<?php
class User extends AppModel {
var $name = 'User';
}
?>
I've dwindled it down and discovered that $users is being set to NULL by the $this->User->find('all') statement because that statement is actually not returning any values. I know Cake is finding the table because of a typo I had earlier with the table name ('usres' instead of 'users'). I can't figure out what I'm missing or what I'm doing wrong. Would love some help. :)
The ouput is 'ArrayArrayArray' doen't means itz empty
try
foreach($users as $user) {
debug($user);
}
For me this code is meaningless.
if you want to use requestAction() use it in the proper way. It's used to call (and print) the parts of the application in the view.
Here is how to achieve the working and correct code:
Your Users class:
class Users extends AppController {
function read(){
$this->set('users', $this->User->find('all'));
$this->layout = "ajax";
$this->render();
}
}
Your read.ctp:
<ul><?php
if(isset($users)){
foreach($users as $user) {
echo '<li>'.$user.'</li>';
}
}
?></ul>
Now in your test.ctp you need to call:
<?php echo $this->requestAction(
array(
'controller'=>'users',
'action'=>'read'
)
);?>
And you will see the result in your test action as unsorted list.