just developed a simple CLI php code that calculates the multiplication table of your choosen size but when I check the files to make sure they stick to PSR coding standards, it gives me four errors/violations. I don't know where in the files the errors are after several attempts and days of work on the files.
there are two files:
cliVersion.php and generateCLITable.php
The first file gives me 1 PSR error and the second one gives me 3 PSR errors.
this is how I generate the multiplication table of size 12 on command line :
php cliVersion.php 12
can anyone help me to find out the PSR errors in the files.
here's the files and the error report:
cliVersion.php
<?php
declare(strict_types=1);
require_once 'generateCLITable.php';
require_once '../model/validateInput.php';
?>
<?php
// Assign the user's input argument value to $input variable
$inputString = $argv[1];
$errorMessage = "Please enter a valid argument (a whole number greater than 1)";
// Check if the user's input argument is not null or empty
if ($inputString == null || $inputString == "") {
echo $errorMessage;
} else {
// Create an object of ValidateInput Class
$inputData = new ValidateInput();
/*
Validate the $input variable received from the user as an argument.
The code will be safe to be processed after this line.
*/
$validatedInput = $inputData->validateInputData($inputString);
$validatedInputInt = (int)$validatedInput;
/*
Check if the validated input is an Integer and if it is,
generates the table else returns the error message
*/
$isInputValidInt = $inputData->isInputInt($validatedInputInt);
if ($isInputValidInt && $validatedInputInt > 1) {
$multTable = new MultTable();
$multTable->generateTable($validatedInputInt);
} else {
echo $errorMessage;
}
}
echo PHP_EOL;
GenerateCLITable.php
<?php
declare(strict_types=1);
class MultTable
{
/**
* The public generateTable function generates the multiplication table
*
* #param int $inputValue
*
* #return void
*/
public function generateTable(int $inputValue)
{
// Create first row of table headers - green colour
for ($col=1; $col <= $inputValue; $col++) {
echo "\033[35m \t$col \033[0m";
}
// Create remaining rows
for ($row=1, $col=1; $row <= $inputValue; $row++) {
echo "\n";
// First cell is a table header - green colour
if ($col == 1) {
echo "\033[35m \n$row \033[0m";
}
while ($col <= $inputValue) {
echo "\t" . $row * $col++ ;
}
// Reset $col at the end of the row
$col = 1;
}
}
}
Error report:
cliVersion.php
----------------------------------------------------------------------
FOUND 1 ERROR AFFECTING 1 LINE
generateCLITable.php
----------------------------------------------------------------------
FOUND 3 ERRORS AFFECTING 3 LINES
I strongly recommend to use https://github.com/FriendsOfPHP/PHP-CS-Fixer in such cases.
I guess you are trying to unit test the code. I would probably focus on trying to be as thoughtful with the code first . Take cliVersion, I think you can simplify it greatly by creating a single method to handle the input. Also I find a lot of issue with your comments and variables and overdesign.
Revised Version:
<?php
//declare(strict_types=1); // I'm using php 5 so I don't have this (but ok for you)
require_once 'generateCLITable.php';
require_once '../model/validateInput.php';
$must_be_gtr_than = 1; // set floor val for validation
$inputData = new ValidateInput($must_be_gtr_than);
$multTable = new MultTable();
if ($inputData->isValidIntegerData($argv[1])) {
$tableSize = (int) $argv[1];
$multTable->generateTable($tableSize);
} else {
echo "Error: Please enter a valid argument (a whole number greater than ".$must_be_gtr_than.")";
die();
}
In this example I have one method alone that validates that I have an integer > 0, if isValidIntegerData than proceed . Think about ease of code and names that make sense generateTable doesn't tell me much, is there a better name ? Things like that. Take "$validatedInputInt", that doesn't speak to what you are doing as well as what that int is, "tableSize" makes more sense to me. Also we many times save camel back for Classes etc.. I would look up PSR2.
For example we use
CONST_SOMETHING = xx; //constants
var_x or varx // lowercase for vars
methodX //camel back
ClassName // ucwords for classes
etc..
UPDATE:
This is how I would probably go about building something like this:
<?php
//declare(strict_types=1); // PHP5.x Example
class GenerateCLITable
{
const DEFAULT_BOARD_SIZE = 12;
public $game_board, $table_size;
public function __construct($input = self::DEFAULT_BOARD_SIZE)
{
$this->game_board = $this->generateTable($input);
}
public function generateTable($inputValue = self::DEFAULT_BOARD_SIZE)
{
$table = "";
// Create first row of table headers - green colour
for ($col=1; $col <= $inputValue; $col++) {
$table .= "\033[35m \t$col \033[0m";
}
// Create remaining rows
for ($row=1, $col=1; $row <= $inputValue; $row++) {
$table .= "\n";
// First cell is a table header - green colour
if ($col == 1) {
$table .= "\033[35m \n$row \033[0m";
}
while ($col <= $inputValue) {
$table .= "\t" . $row * $col++ ;
}
// Reset $col at the end of the row
$col = 1;
}
$this->game_board = $table;
$this->table_size = $inputValue;
return $table;
}
public function isValidInputValue($input = '', $size = 0)
{
return (!empty($input) && $input > $size) ? (is_int((int) $input)) : false;
}
}
//require_once 'generateCLITable.php';
$multTable = new GenerateCLITable();
$must_be_gtr_than = 1;
if (!$multTable->isValidInputValue($argv[1], $must_be_gtr_than)) {
echo "Error: Please enter a valid argument (a whole number greater than ".$must_be_gtr_than.")";
die();
}
$table = $multTable->generateTable((int) $argv[1]);
echo $table . "\n";
Related
My first ever question on here as I'm completely stuck, so apologies if I leave out any key information - please let me know!
I am creating a PHP Battleships game and trying to use full OO. I'm really close, however, an array for one of my classes does not hold any updates I make to it.
First off, I dynamically
created a HTML table with an onclick event - which passes the coordinates to a JS function.
I then make an AJAX call in jQuery:
function shotFired(row, column) {
var coords = {
x: row,
y: column
};
$.post("data/game_controller.php", {
jsonCoords: JSON.stringify(coords)
}, function(results) {
console.log(results)
console.log(results[4])
var playerShotResult = results[0];
var computerShotX = results[1] + 1;
var computerShotY = results[2] + 1;
var computerShotResult = results[3];
var positionsClicked = document.getElementById("computer_" + row + "," + column)
switch (playerShotResult) {
case "MISS":
positionsClicked.classList.add("miss");
break;
case "HIT":
positionsClicked.classList.add("hit");
break;
case "Already Hit":
document.getElementById("outputMessage").innerHTML = result
break;
default:
console.log("Player shot defaulted");
}
}, "json")
I then use game_controller.php to handle the request and call shotFired:
<?php
session_start();
require("../classes/Game.class.php");
if (isset($_POST['jsonCoords'])) {
if (isset($_SESSION['newGame'])) {
$game = unserialize($_SESSION['newGame']);
$coords = json_decode($_POST['jsonCoords']);
$results = $game->shotFired($coords->x, $coords->y);
echo json_encode($results);
}
}
shotFired from the Game.php Class file, gets an instance of the Fleet class called computer, and runs the checkPosition function:
public function shotFired($x, $y)
{
$computer = $this->getComputer();
$playerHit = $computer->checkPosition(($x - 1), ($y - 1));
$computerGrid = $computer->getBattleshipsGrid();
$computerHit = $this->simulateComputerShot();
return [$playerHit, $computerHit[0], $computerHit[1], $computerHit[2], $computerGrid];
}
checksPosition checks the State of the Position instance in the BattleshipGrid array, and then attempts to update the array with a H or M - using a standard setter method:
public function checkPosition($x, $y): string
{
$positionObj = $this->battleshipsGrid["(" . $x . "," . $y . ")"];
$positionState = $positionObj->getState();
if ($positionState == "#") {
$positionObj->setState("M");
return "MISS";
} elseif ($positionState == "M" || $positionState == "H") {
return "Already Fired";
} else {
$positionObj->setState("H");
return "HIT";
}
}
For reference, I set the Battleships board in the constructor for Fleet.php:
// Populate associative array with instances of position
for ($y = 0; $y < $gridSize; $y++) {
for ($x = 0; $x < $gridSize; $x++) {
$coordinates = "(" . $x . "," . $y . ")";
$this->battleshipsGrid[$coordinates] = new Position($x, $y);
}
}
It works directly after it has been set - however, on the next onclick event, the H or M value is reset to it's previous value?
Seen here in console output
After a couple of hours, the closest I've come to is passing byRef in the setState function (didn't make a difference).
I've seen some notes on array_map, but I'm not sure this is what I'm looking for?
For ref, this is how I output the battleshipGrid to the console:
public function getBattleshipsGrid()
{
$readableGrid = "";
$grid = $this->battleshipsGrid;
foreach ($grid as $coordsID => $positionObj) {
$readableGrid .= "\n" . $coordsID . ": " . $positionObj->getState();
}
return $readableGrid;
}
Apologies for the long post, but I didn't want to leave anything out. Any and all help would be extremely appreciated!
Many thanks
It looks like you're not saving the state of the coordinates of the hits. If you are using the eloquent model, and setState is changing the attribute's value, make sure that you call $positionObj->save() as php does not save state on each ajax request. You will need to use a database or some sort of storage to have the server 'remember' that you clicked a specific location.
I am trying to validate 3 scenarios but something is wrong and the if statements are not being honored properly
Here are the scenarios I need to work:
If the string "2.5.4.15" exists in array then output "Extended Validation".
If the string "2.5.4.15" does NOT exist in array then output "Organization Validated".
If the string "id-at-organizationName" does NOT exist in array then output "Domain Validated".
I am getting incorrect results. For example, if the data I am parsing does contains "2.5.4.15" for some reason its returning "Domain Validated" ??
Here is my code:
if(isset($cert['tbsCertificate']['subject']['rdnSequence'])) {
$EV = array('2.5.4.15');
$org = array('id-at-organizationName');
$count = count($cert['tbsCertificate']['subject']['rdnSequence']);
for($i = 0; $i < $count; $i++) {
if(in_array($cert['tbsCertificate']['subject']['rdnSequence'][$i][0]['type'], $EV)) {
$validation = "<tr><td>Validation</td><td>Extended Validation (EV)</td></tr>";
echo $validation;
break;
}
if(!in_array($cert['tbsCertificate']['subject']['rdnSequence'][$i][0]['type'], $EV)) {
$validation = "<tr><td>Validation</td><td>Organization Validated (OV)</td></tr>";
echo $validation;
break;
}
if(!in_array($cert['tbsCertificate']['subject']['rdnSequence'][$i][0]['type'], $org)) {
$validation = "<tr><td>Validation</td><td>Domain Validated (DV)</td></tr>";
echo $validation;
break;
}
}
}
-- UPDATE --
I removed the break; and I can see it's now returning multiple results before it gives our the correct one (highlighted in red the correct match).. but why is it returning the bogus response instead of just returning the correct response the first time ?
-- UPDATE 2 --
I think I understand the results I am getting, it seems to be outputting result for each iteration where the string is not found. Whereas what I want to do is return one response.
I think then because of this perhaps using a loop is not the answer. Is there a way to search the whole array for a string and output the result instead of looping through each array ?
I didn't understand why are you using 'array' to store single values, you can simple compare strings.
In case the field can match only to one option - you can use if..elseif or even better - switch.
Please notice that your $validation variable will always overwrite itself in every irritation. So, If you're looking for a specific row - you should mention it. If you're looking for one multi-result in the end, you need to store that data in another array.
In continuation to the chat, let me break the scenarios of the key's value:
If 2.5.4.15 exists in the array - return EV
If it (1) doesn't exist but 'id-at-organizationName' does - return
If it (1) doesn't exist and (2) also doesn't exist - return
For the first scenario I used break since if it exists we don't need to continue to check the rest of the array, also it's automatically means that the 2 other conditions could never exist. EDIT also added a break to the second scenario condition.
Here is my suggestion: (Please check it and share the output/problems in the chat until will accomplish to solve your problem)
if(isset($cert['tbsCertificate']['subject']['rdnSequence'])) {
$count = count($cert['tbsCertificate']['subject']['rdnSequence']);
for($i = 0; $i < $count; $i++) {
$value = $cert['tbsCertificate']['subject']['rdnSequence'][$i][0]['type'];
if($value == "2.5.4.15") {
$output = "EV";
break;
} else {
if($value == "id-at-organizationName") {
$output = "OV";
break; //Edit 1
} else {
$output = "DV";
}
}
}
echo $output;
}
You echoes bad variables:
for($i = 0; $i < $count; $i++) {
if(in_array($cert['tbsCertificate']['subject']['rdnSequence'][$i][0]['type'], $EV)) {
$validation = "<tr><td>Validation</td><td>Extended Validation (EV)</td></tr>";
echo $validation;
break;
}
if(!in_array($cert['tbsCertificate']['subject']['rdnSequence'][$i][0]['type'], $EV)) {
$validation1 = "<tr><td>Validation</td><td>Organization Validated (OV)</td></tr>";
echo $validation1; // $validation1 instead of $validation
break;
}
if(!in_array($cert['tbsCertificate']['subject']['rdnSequence'][$i][0]['type'], $org)) {
$validation2 = "<tr><td>Validation</td><td>Domain Validated (DV)</td></tr>";
echo $validation2; // $validation2 instead of $validation
break;
}
}
The second thing is that for this task is better to use elseif instead of 3 ifs:
for () {
if () {
// validation
} elseif () {
// validation 1
} elseif () {
// validation 2
}
}
Trying to locate the first blank cell in a column. The idea is to pick a column that I know has to have a value (in this case, JOB_NUMBER) and scan through it until a blank cell is found. The code below, in my mind, should do that. However, it never stops. I imagine it is stuck in the while loop, but I don't understand why.
Code:
<?php
require('./Classes/PHPExcel/IOFactory.php');
ini_set('max_execution_time', 800);
ini_set('memory_limit', 2000000000);
$inputFileType = 'Excel2007';
$inputFileName = $_FILES['file']['tmp_name'];
class MyReadFilter implements PHPExcel_Reader_IReadFilter {
public function __construct($fromColumn, $toColumn) {
$this->columns = array();
$toColumn++;
while ($fromColumn !== $toColumn) {
$this->columns[] = $fromColumn++;
}
}
public function readCell($column, $row, $worksheetName = '') {
// Read columns from 'A' to 'AF'
if (in_array($column, $this->columns)) {
return true;
}
return false;
}
}
$filterSubset = new MyReadFilter('A', 'AF');
$objReader = PHPExcel_IOFactory::createReader($inputFileType);
$objReader->setReadFilter($filterSubset);
$objReader->setLoadSheetsOnly( array("NORTH") );
$objPHPExcelReader = $objReader->load($inputFileName);
$r = 3500;
while(isset($maxrow_north) != 1){
$cellvalue = $objPHPExcelReader->getSheetByName('NORTH')->getCellByColumnAndRow(2, $r);
if(isset($cellvalue) != 1){
$maxrow_north = $r;
} elseif($r > 4000) {
echo "It's over 4000!";
} else {
$r = $r++;
}
}
echo $maxrow_north;
?>
Some more background
I am having admins upload .xlsx .xls or .csv files into an html form. The code, above, is the handler. I have limited the number of columns seen because the original creator of the .xlsx file thought it would be a great idea to have the columns go all the way out to XCF.
The rows also go all the way out to somewhere around 10,000. So, I want to find the first blank row and stop there.
TIA!
Don't use
if(isset($cellvalue) != 1){
A cell value always exists even if it's an empty string or a null: and you're not testing the actual cell value, but the existence of a cell.... simply get() ting a cell will create a new empty cell object if one didn't already exist
You need to test the actual value stored in the cell
if($cellvalue->getValue() === NULL || $cellvalue->getValue() === '') {
$maxrow_north = $r;
And if you're trying to find the first blank cell in the column, then break once you've found it rather than carry on iterating till you reach your max
(Note, doesn't check for rich text in cells)
EDIT
Example, that also allows for merged cells
function testInMergeRangeNotParent($objWorksheet, $cell)
{
$inMergeRange = false;
foreach($objWorksheet->getMergeCells() as $mergeRange) {
if ($cell->isInRange($mergeRange)) {
$range = PHPExcel_Cell::splitRange($mergeRange);
list($startCell) = $range[0];
if ($cell->getCoordinate() !== $startCell) {
$inMergeRange = true;
}
break;
}
}
return $inMergeRange;
}
$column = 2; // Column to check
$max = 4000;
echo 'Get First blank row in column ', $column, PHP_EOL;
$r = 3500; // Starting row
while(true){
$cell = $objPHPExcelReader->getSheetByName('NORTH')->getCellByColumnAndRow($column, $r);
if ($cell->getValue() === NULL &&
!testInMergeRangeNotParent($objPHPExcelReader->getSheetByName('NORTH'), $cell)) {
break;
}elseif($r > $max) {
echo "It's over $max !";
break;
}
$r++;
}
echo 'First blank row in column ', $column, ' is ', $r, PHP_EOL;
I'm new to programming and I'm having to teach myself. But, I can't figure out what I'm doing wrong in this project. This project is for myself, to make shortcuts in PHP so I don't have to program so many lines of code; when I program, sometimes I use the same 20 lines for different applications.
Here is my script:
function writeDir($directory = null, $link = null, $exception = null) {
if (!isset($directory)) {
$directory = './';
}
if (!isset($link)) {
$link = false;
}
if (!isset($exception)) {
$exception = null;
}
// now...
if ($link==true&&$exception!=null) { // do a link and exception(s)
$directoryList = scandir($directory); // get an array of all directory items
$directoryLength = count($directoryList); // count $directoryList array length
if (is_string($exception)) { // if one (1) exception
for ($i=2; $i<$directoryLength; $i++) { // cycle through all directory items
if ($directoryList[$i] == $exception) { // if we hit that one (1) exception
echo ''; // do nothing
} else {
echo ' ' . $directoryList[$i] . ' <br />' . "\n";
}
}
}
if (is_array($exception)) { // if multiple exceptions
$exceptionList = count($exception); // count $exception array length
for ($i=2; $i<$directoryList; $i++) { // cycle through all directory items
for ($j=0; $j<$exceptionList; $j++) { // cycle through all exceptions
if ($directoryList[$i] == $exceptionList[$j]) { // if we hit one of the multiple exceptions
echo ''; // do nothing
} else {
echo ' ' . $directoryList[$i] . ' <br />' . "\n";
}
}
}
}
}
if ($link==true&&$exception==null) {
$directoryList = scandir($directory);
$directoryLength = count($directoryList);
for ($i=2; $i<$directoryLength; $i++) {
echo ' ' . $directoryList[$i] . ' <br />' . "\n";
}
}
if ($link==false&&$exception!=null) { // do only exception(s) without links
$directoryList = scandir($directory); // get an array of all directory items
$directoryLength = count($directoryList); // count $directoryList array length
if (is_string($exception)) { // if one (1) exception
for ($i=2; $i<$directoryLength; $i++) { // cycle through all directory items
if ($directoryList[$i] == $exception) { // if we hit that one (1) exception
echo ''; // do nothing
} else {
echo $directoryList[$i] . '<br />' . "\n";
}
}
}
if (is_array($exception)) { // if multiple exceptions
$exceptionList = count($exception); // count $exception array length
for ($i=2; $i<$directoryList; $i++) {
for ($j=0; $j<$exceptionList; $j++) {
if ($directoryList[$i] == $exceptionList[$j]) {
echo '';
} else {
echo $directoryList[$i] . '<br />' . "\n";
}
}
}
}
}
if ($link==false&&$exception==null) {
$directoryList = scandir($directory);
$directoryLength = count($directoryList);
for ($i=2; $i<$directoryLength; $i++) {
echo $directoryList[$i] . '<br />' . "\n";
}
}
}
I know it looks like a lot. But, I'm trying to make my life simpler when programming.
Basically, the syntax for this when called in a PHP file is:
writeDir(); // at the very least :OR: writeDir('./', true, 'index.php');
The second one writes files in the current directory with corresponding links to them, but skips over the index.php file.
The third (3rd) argument can be either a single omitted page (as a string) or an array of multiple omitted pages. Or, at least that's what I'm trying to achieve.
Of course an include to this source file would be required on all pages I use it for. Before, when IT WAS working, I could only format the list of directory items with the exclusion of one (1) file. So, I tried to allow for an array of files as well. Now, it loads for ever. I finally had to use a set_time_limit() function to quit the script.
Now, one last thing. When I used the set_time_limit() function, it displayed my directory items, but for some reason two (2) of everything... What have I done wrong?
Are there too many if-statements, or have I overlooked something? Should I just start over?
I've only programmed (unprofessionally) for about 5 years so I don't really know what it is I'm doing. Any guidance would be greatly appreciated.
Hope I've given enough information and details.
JDot
P.S.
Anybody who wants to use this script is more than welcome to (if it's even worth using).
use esle if
if($a==1)
{
echo $a;
}
elseif($b==1)
{
echo $b;
}
else
{
echo "c";
}
and there is ternary operator fo single if else statement: learn it
Basically I want to echo only summary of my blog post on a certain page by making a function() that must limit the number of counts of words as specified there.
function sumarize($your_string){
$count++;
$maximum = 10;
foreach(explode("\n", $your_string) as $line){
$count++;
echo $line."\n";
if ($count == $maximum) break;
}
}
Lets say your table (named main) looks like that.
id | blogpost
1 sample1
2 sample2
...
At first you need to connect to db
$db=NEW MYSQLI('localhost', 'username', 'pass', 'dbname') or die ($db->error);
Then write following piece of code
function sumarize($your_string){
$count++;
$maximum = 10;
foreach(explode("\n", $your_string) as $line){
$count++;
echo $line."\n";
if ($count == $maximum) break;
}
}
$result=$db->query("SELECT `id`, `blogpost` FROM `main`");
while($row->fetch_object()){
echo sumarize($row->blogpost);
}
This is how to get work genesis φ's solution
this one takes into account numbers of character whilst ending at the last word without cutting out a character
use
select .... SUBSTR(body,1,300) .....
later you can use this function in php to cut the string at the last space or period so you wont get a half cut word in the end. The second parameter is the number of characters you want.
function shorten_string($string, $characters)
{
$shortened_string = "";
$smaller_string = substr($string, 0, $characters);
$pos_of_last_space = strrpos($smaller_string, " ");
$pos_of_last_break = strrpos($smaller_string, " ");
if (strlen($string) <= $characters) {
$shortened_string = $string;
} elseif (!$pos_of_last_space && !$pos_of_last_break) {
$shortened_string = $smaller_string;
} else {
$break_at = 0;
if ($pos_of_last_space > $pos_of_last_break) {
$break_at = $pos_of_last_space;
} else {
$break_at = $pos_of_last_break;
}
$shortened_string = substr($smaller_string, 0, $break_at);
}
}
NOTE: takes care of spaces put in html with 'nbsp'
Save the summary and body of your blog posts in different columns.