here I am again, had before more complicated issue, but now got another (smaller I think).
In template file there's variables in use as "author_id", "authlink", but in controller file doesn't getting author url (but it should).
In template file there's defined variables as authlink and author_id.
Also, in controller file I've included file path where is these variables in use.
<?php
set_include_path(".:/domains/example.com/public_html/.../single-2.php"); //destination to file where's author_id variables either.
function ajax_rental_add_to_cart()
{
if ( STInput::request( 'action' ) == 'rental_add_cart' ) {
$response = array();
$response['status'] = 0;
$response['message'] = "";
$response['redirect'] = '';
$author_id = get_post_field( 'post_author', get_the_ID() );
$authlink = get_author_posts_url($author_id);
if ( $this->do_add_to_cart() ) {
$response['redirect'] = $authlink;
$response['status'] = 1;
wp_send_json($response, 200);
} else {
$message = STTemplate::message();
$response['message'] = $message;
wp_send_json($response, 200);
}
}
}
static function inst()
{
if (!self::$_instance) {
self::$_instance = new self();
}
return self::$_instance;
}
}
STRental::inst()->init();
}
?>
Not sure is that static function inst() related, but pasting anyway. Problem is, on variable $response['redirect'] = $authlink; I should be redirected to https://example.com/author/author_id , but I'm getting redirected only into https://example.com/author/
It seems like controller file doesn't getting anyway author_id, maybe because after redirect it loosing author_id and that's why I'm not redirected to right way? Should I store author_id somehow and use it again in this file?
P.S. If I'm using same redirection in template file (not controller) - works perfectly, but then bypassing all date checks, so that's why I'm still messing up with controller file.
Related
I am trying to make a CRUD Module in Codeigniter HMVC but I seem to be missing something in the process. Here is what I am facing.
I have a News Module which has a Manage function
function manage(){
$grid = Modules::run('Crud/renderGrid', 'News' , 'News management');
}
Render Grid Function
function renderGrid($module , $page_title){
$data['page_title'] = $page_title; //Dynamic
$data['module'] = $module;
$data['view_module'] = 'Crud';
$data['displayfields'] = Modules::run($module.'/get_displayfields');
$data['key'] = Modules::run($module.'/get_key');
$data['rows'] = Modules::run($module.'/get' , $data['key']);
$data['view_file'] = 'manage';
$this->load->module('dashboard');
$this->dashboard->show_dashboard($data);
}
Here, the show_dashboard function just loads up a template layout with a desired view in it.
function show_dashboard($data = NULL){
if($data == NULL){
$data['view_file'] = "manage";
$data['page_title'] = 'Sigma Web Solutions';
}
$this->load->module('templates');
$this->templates->admin($data);
}
Templates->admin
function admin($data){
$this->load->view('admin' , $data);
}
The View (omitting the header n Footer)
<?php
if (!isset($view_file)) {
$view_file = "";
}
if (!isset($view_module)) {
$module = $this->uri->segment(1);
}
if (($view_module!="") && ($view_file!="")) {
$path = $view_module."/".$view_file;
$this->load->view($path);
}
?>
Now, when I try the url news/manage, it gives me a blank page with no source code in it. But when I try something like
crud/renderGrid/news/sometitle/ it works just fine.
Kindly point out what did I miss here. Thanks.
Working Solution:
Thanks to wolf I added a route
$route['managenews']= 'crud/renderGrid/news/News';
And it works like charm. But why do I need a route here? Shouldn't it just work. And this means for every module I need to have 4 entries in my route file for the CRUD system to work. can anyone suggest a better method?
I am adapting StationWagon (FuelPHP app) and so far it's working really well.
I have adapted it (with some help) to allow multiple images to be uploaded to the server. This is also working great.
However, I am thinking it would make more sense if I had 2 Tables: 1) Articles and 2) ArticleImages. I would use a Foreign Key to associate the Images with the Article. So when publishing an article it would add the article data to 'Articles' table and move each image to a new row in 'ArticleImages'.
So ultimately my 'ArticleImages' table could be:
ID | ImageURL | ArticleID
Portion of my 'articles.php' controller:
<?php
public function action_add()
{
$val = Model_Article::validate('add_article'); //<-- maybe its just me but i never saw any similar to this in fuelphp sorry about this if im wrong
// if your form validation is okay than continue with everyhing else
if ($val->run())
{
$article = Model_Article::forge();
// Custom configuration for this upload
$config = array(
'path' => DOCROOT.DS.'images',
'randomize' => true,
'ext_whitelist' => array('img', 'jpg', 'jpeg', 'gif', 'png'),
);
Upload::process($config);
// if a valid file is passed than the function will save, or if its not empty
if (Upload::is_valid())
{
// save them according to the config
Upload::save();
//if you want to save to tha database lets grab the file name
$value = Upload::get_files();
foreach($value as $files) {
print_r($files);
}
$article->filename = $value[0]['saved_as'];
}
$status = (Input::post('save_draft') ? 0 : 1);
if ( ! $val->input('category_id'))
{
$category_id = null;
}
else
{
$category_id = $val->validated('category_id');
}
$article->user_id = $this->user_id;
$article->category_id = $category_id;
$article->title = $val->validated('title');
$article->body = $val->validated('body');
$article->published = $status;
if ($article->save())
{
Session::set_flash('success', 'Article successfully added.');
}
else
{
Session::set_flash('error', 'Something went wrong, '.
'please try again!');
}
Response::redirect('articles/add');
}
$this->template->title = 'Add Article';
$this->template->content = View::forge('articles/add')
->set('categories', Model_Category::find('all'), false)
->set('val', Validation::instance('add_article'), false);
}
/* End of file articles.php */
You are trying to make a relation between Articles and ArticleImages. An ArticleImage belongs to an Article, while an Article has many ArticleImages. FuelPHP has functionality built in for what you are trying to achieve. Have a look at the FuelPHP docs on its Object Relational Mapper, especially the Belongs To and Has Many relations.
So when i made the code for you back a few days a go you only requested, one file input.
And no offense but you are doing it all wrong...
foreach($value as $files) {
print_r($files);
}
$article->filename = $value[0]['saved_as'];
should be
foreach($value as $files) {
$articleimg = Model_Articleimages::forge();
$articleimg->image_row_name = $files['saved_as']
}
To get you to understand
what you did here, $value = Upload::get_files(); yes this gets all the elements but since you need to loop trouh the elements you dont need it
Second
this $value[0]['saved_as'] only grabs the first image name, just the first one, and since you are in a loop now you need to refer to the $files variable as i shown you in the above example, just an example
I am using Kohana 3.2 and I am having problems calling the ouput of a controller in another controller.
What I want...
In some pages I have got a menu, and in others I don't. I want to use make use of the flexability of the HMVC request system. In the controller of a page I want to call another controller which is responsible for the creation of the menu.
What I have a the moment:
file menu.php:
<?php defined('SYSPATH') or die('No direct script access.');
class Controller_Menu extends Controller
{
private $_model = null;
public function __construct(Request $request, Response $response)
{
parent::__construct($request, $response);
$this->_model = Model::factory('menu');
}
public function action_getMenu()
{
$content = array();
$content['menuItems'] = $this->_model->getMenuItems();
// Render and output.
$this->request->response = View::factory('blocks/menu', $content);
//echo '<pre>'; print_r($this->request->response->render()); echo '</pre>'; die();
}
}
somepage.php
public function action_index()
{
$this->template->title = 'someTitle';;
$contentData['pageTitle'] = 'someTitle';
$contentData['contentData'] = 'someData';
#include the menu
$menuBlock = Request::factory('menu/getMenu')->execute();
$menuData = array('menu' => $menuBlock);
$this->template->menu = View::factory('pages/menu')->set('menu',$menuData);
$this->template->content = View::factory('pages/somePage', $contentData);
$view = $this->response->body($this->template);
$this->response->body($view);
}
If I uncomment the following line in menu.php, I see the menu rendered:
//echo '<pre>'; print_r($this->request->response->render()); echo '</pre>'; die();
So I guess that part is alright. The problem is in the following line in somepage.php:
$menuBlock = Request::factory('menu/getMenu')->execute();
This gives me back a response object. Whatever I do, I do not get the output in $this->template->menu.
$this->template->menu = View::factory('pages/menu')->set('menu',$menuData);
What must I do to have $this->template->menu contain the view, so I can use it correctly?
I hope this all makes sense. This is the way I would like to do it, but maybe I am completely on the wrong track.
I would do it this way:
class Controller_Menu extends Controller
{
public function action_build()
{
// Load the menu view.
$view = View::factory('navigation/menu');
// Return view as response-
$this->response->body($view->render());
}
}
In your controller get the menu as follows:
// Make request and get response body.
$menu = Request::factory('menu/build')->execute()->body();
// e.g. assign menu to template sidebar.
$this->template->sidebar = Request:.factory('menu/build')->execute()->body();
I would not use the __construct method in your controllers. Use before() instead, this is sufficient for most of the problems (for example auth):
public function before()
{
// Call aprent before, must be done here.
parent::before();
// e.g. heck whether user is logged in.
if ( !Auth::instance()->logged_in() )
{
//Redirect if not logged in or something like this.
}
}
I found the answer to my problem in less than an hour after asking.
I just forgot to put it here.
In somePage.php change :
$menuBlock = Request::factory('menu/getMenu')->execute();
$menuData = array('menu' => $menuBlock);
$this->template->menu = View::factory('pages/menu')->set('menu',$menuData);
To:
$this->template->menu = Request::factory('menu/getMenuBlock')->execute()->body();
And in menu.php change:
$this->request->response = View::factory('blocks/menu', $content);
To:
$request = View::factory('blocks/menu', $content);
$this->response->body($request);
I hope this will help someone else.
Inherited an old CakePHP site and I'm trying to figure out what some functions do. I have several functions that have the same name as another function but with an underscore first, e.g. save() and _save(). However the function _save() is never called in any context, though save() is.
I read this question and it looks like it's from an old worst-practices exercise, but that doesn't really explain why it's in my code; you still have to call function _save() as _save() right? If there's no calls to _save() is it safe to remove?
I want it gone, even the save() function wasn't supposed to be there, rewriting perfectly good framework functionality. It looks like an older version of the same function, but there's no comments and I don't know if there's some weird context in which php/Cake will fall back to the underscored function name.
Here's the code for the curious. On closer inspection it appears the underscored functions were old versions of a function left in for some reason. At least one was a "private" method being called (from a public function of the same name, minus the underscore...):
function __save() {
$user = $this->redirectWithoutPermission('product.manage','/',true);
if ($this->data) {
$this->Prod->data = $this->data;
$saved_okay = false;
if ($this->Prod->validates()) {
if ($this->Prod->save()) $saved_okay = true;
}
if ($saved_okay) {
$product_id = ($this->data['Prod']['id']) ? $this->data['Prod']['id'] : $this->Prod->getLastInsertId();
if ($this->data['Plant']['id']) {
$this->data['Prod']['id'] = $product_id;
$this->Prod->data = $this->data;
$this->Prod->save_plants();
$this->redirect('/plant/products/'.$this->data['Plant']['id']);
} else {
$this->redirect('/product/view/'.$product_id);
}
die();
} else {
die('did not save properly');
}
} else {
die('whoops');
}
}
function save() {
$user = $this->redirectWithoutPermission('product.manage','/products',true);
if ($this->data) {
$this->Prod->data = $this->data;
if ($this->Prod->validates()) {
$this->Prod->save();
$gotoURL = isset($this->data['Navigation']['goto'])?$this->data['Navigation']['goto']:'/';
$gotoURL = str_replace('%%Prod.id%%', $this->data['Prod']['id'], $gotoURL);
if (isset($this->data['Navigation']['flash'])) {
$this->Session->setFlash($this->data['Navigation']['flash']);
}
if (isset($this->params['url']['ext']) && $this->params['url']['ext']=='ajax') {
$value = array(
'success'=>true
,'redirect'=>$gotoURL
);
print $this->Json->encode($value);
} else {
$this->redirect($gotoURL);
}
} else {
$value = array(
'success'=>false
,'message'=>"You have invalid fields."
,'reason'=>'invalid_fields'
,'fields'=>array(
'Prod'=>$this->Prod->invalidFields()
)
);
print $this->Json->encode($value);
}
} else {
$this->redirect('/products');
}
die();
}
I had hoped to learn whether or not some convention applied to this situation, but from testing I've found the functions are not called which is really the answer to the question I asked.
I have been reading a lot about how and why to use an MVC approach in an application. I have seen and understand examples of a Model, I have seen and understand examples of the View.... but I am STILL kind of fuzzy on the controller. I would really love to see a thorough enough example of a controller(s). (in PHP if possible, but any language will help)
Thank you.
PS: It would also be great if I could see an example of an index.php page, which decides which controller to use and how.
EDIT: I know what the job of the controller is, I just don't really understand how to accomplish this in OOP.
Request example
Put something like this in your index.php:
<?php
// Holds data like $baseUrl etc.
include 'config.php';
$requestUrl = 'http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
$requestString = substr($requestUrl, strlen($baseUrl));
$urlParams = explode('/', $requestString);
// TODO: Consider security (see comments)
$controllerName = ucfirst(array_shift($urlParams)).'Controller';
$actionName = strtolower(array_shift($urlParams)).'Action';
// Here you should probably gather the rest as params
// Call the action
$controller = new $controllerName;
$controller->$actionName();
Really basic, but you get the idea... (I also didn't take care of loading the controller class, but I guess that can be done either via autoloading or you know how to do it.)
Simple controller example (controllers/login.php):
<?php
class LoginController
{
function loginAction()
{
$username = $this->request->get('username');
$password = $this->request->get('password');
$this->loadModel('users');
if ($this->users->validate($username, $password))
{
$userData = $this->users->fetch($username);
AuthStorage::save($username, $userData);
$this->redirect('secret_area');
}
else
{
$this->view->message = 'Invalid login';
$this->view->render('error');
}
}
function logoutAction()
{
if (AuthStorage::logged())
{
AuthStorage::remove();
$this->redirect('index');
}
else
{
$this->view->message = 'You are not logged in.';
$this->view->render('error');
}
}
}
As you see, the controller takes care of the "flow" of the application - the so-called application logic. It does not take care about data storage and presentation. It rather gathers all the necessary data (depending on the current request) and assigns it to the view...
Note that this would not work with any framework I know, but I'm sure you know what the functions are supposed to do.
Imagine three screens in a UI, a screen where a user enters some search criteria, a screen where a list of summaries of matching records is displayed and a screen where, once a record is selected it is displayed for editing. There will be some logic relating to the initial search on the lines of
if search criteria are matched by no records
redisplay criteria screen, with message saying "none found"
else if search criteria are matched by exactly one record
display edit screen with chosen record
else (we have lots of records)
display list screen with matching records
Where should that logic go? Not in the view or model surely? Hence this is the job of the controller. The controller would also be responsible for taking the criteria and invoking the Model method for the search.
<?php
class App {
protected static $router;
public static function getRouter() {
return self::$router;
}
public static function run($uri) {
self::$router = new Router($uri);
//get controller class
$controller_class = ucfirst(self::$router->getController()) . 'Controller';
//get method
$controller_method = strtolower((self::$router->getMethodPrefix() != "" ? self::$router->getMethodPrefix() . '_' : '') . self::$router->getAction());
if(method_exists($controller_class, $controller_method)){
$controller_obj = new $controller_class();
$view_path = $controller_obj->$controller_method();
$view_obj = new View($controller_obj->getData(), $view_path);
$content = $view_obj->render();
}else{
throw new Exception("Called method does not exists!");
}
//layout
$route_path = self::getRouter()->getRoute();
$layout = ROOT . '/views/layout/' . $route_path . '.phtml';
$layout_view_obj = new View(compact('content'), $layout);
echo $layout_view_obj->render();
}
public static function redirect($uri){
print("<script>window.location.href='{$uri}'</script>");
exit();
}
}
<?php
class Router {
protected $uri;
protected $controller;
protected $action;
protected $params;
protected $route;
protected $method_prefix;
/**
*
* #return mixed
*/
function getUri() {
return $this->uri;
}
/**
*
* #return mixed
*/
function getController() {
return $this->controller;
}
/**
*
* #return mixed
*/
function getAction() {
return $this->action;
}
/**
*
* #return mixed
*/
function getParams() {
return $this->params;
}
function getRoute() {
return $this->route;
}
function getMethodPrefix() {
return $this->method_prefix;
}
public function __construct($uri) {
$this->uri = urldecode(trim($uri, "/"));
//defaults
$routes = Config::get("routes");
$this->route = Config::get("default_route");
$this->controller = Config::get("default_controller");
$this->action = Config::get("default_action");
$this->method_prefix= isset($routes[$this->route]) ? $routes[$this->route] : '';
//get uri params
$uri_parts = explode("?", $this->uri);
$path = $uri_parts[0];
$path_parts = explode("/", $path);
if(count($path_parts)){
//get route
if(in_array(strtolower(current($path_parts)), array_keys($routes))){
$this->route = strtolower(current($path_parts));
$this->method_prefix = isset($routes[$this->route]) ? $routes[$this->route] : '';
array_shift($path_parts);
}
//get controller
if(current($path_parts)){
$this->controller = strtolower(current($path_parts));
array_shift($path_parts);
}
//get action
if(current($path_parts)){
$this->action = strtolower(current($path_parts));
array_shift($path_parts);
}
//reset is for parameters
//$this->params = $path_parts;
//processing params from url to array
$aParams = array();
if(current($path_parts)){
for($i=0; $i<count($path_parts); $i++){
$aParams[$path_parts[$i]] = isset($path_parts[$i+1]) ? $path_parts[$i+1] : null;
$i++;
}
}
$this->params = (object)$aParams;
}
}
}
Create folder structure
Setup .htaccess & virtual hosts
Create config class to build config array
Controller
Create router class with protected non static, with getters
Create init.php with config include & autoload and include paths (lib, controlelrs,models)
Create config file with routes, default values (route, controllers, action)
Set values in router - defaults
Set uri paths, explode the uri and set route, controller, action, params ,process params.
Create app class to run the application by passing uri - (protected router obj, run func)
Create controller parent class to inherit all other controllers (protected data, model, params - non static)
set data, params in constructor.
Create controller and extend with above parent class and add default method.
Call the controller class and method in run function. method has to be with prefix.
Call the method if exisist
Views
Create a parent view class to generate views. (data, path) with default path, set controller, , render funcs to
return the full tempalte path (non static)
Create render function with ob_start(), ob_get_clean to return and send the content to browser.
Change app class to parse the data to view class. if path is returned, pass to view class too.
Layouts..layout is depend on router. re parse the layout html to view and render
Please check this:
<?php
global $conn;
require_once("../config/database.php");
require_once("../config/model.php");
$conn= new Db;
$event = isset($_GET['event']) ? $_GET['event'] : '';
if ($event == 'save') {
if($conn->insert("employee", $_POST)){
$data = array(
'success' => true,
'message' => 'Saving Successful!',
);
}
echo json_encode($data);
}
if ($event == 'update') {
if($conn->update("employee", $_POST, "id=" . $_POST['id'])){
$data = array(
'success' => true,
'message' => 'Update Successful!',
);
}
echo json_encode($data);
}
if ($event == 'delete') {
if($conn->delete("employee", "id=" . $_POST['id'])){
$data = array(
'success' => true,
'message' => 'Delete Successful!',
);
}
echo json_encode($data);
}
if ($event == 'edit') {
$data = $conn->get("select * from employee where id={$_POST['id']};")[0];
echo json_encode($data);
}
?>